From 044a11b59437caccea7c731b55b117f5b6aa73e3 Mon Sep 17 00:00:00 2001 From: Matt Clarkson Date: Mon, 16 Sep 2024 09:21:25 +0100 Subject: [PATCH] feat: add `labgrid_config_toolchain` This adds a significant refactor of the project. BREAKING CHANGE: `//labgrid/toolchain/executor:type` has been removed. Use `labgrid_config_toolchain` instead. An issue has been found that prevents a LabGrid configuration being loaded because the Python dependencies for the configuration are not available. This manifests in the current end-to-end Docker tests as the `DockerDriver` not being able to find the `docker` module. The issue is that we need a `py_library` dependency for the resolved LabGrid configuration for the target platform. However, where the toolchain gets resolved in `labgrid_genrule` is too high up the rule graph. The resolution needs to happen within the passed in Python tool. This patch provides three lazily resolved labels: - `//labgrid/config:src` (aliased as `//labgrid/config`) - `//labgrid/config:deps` - `//labgrid/manager:src` (aliased as `//labgrid/manager`) A script that is provided to `labgrid_genrule` can do: ```py py_binary( name = "something", srcs = ["something.py"], deps = ["@rules_labgrid//labgrid/config:deps"], ) ``` When the tool loads the LabGrid configuration from `LG_ENV`, it is guranteed to have the correct Python dependencies available. The crucial feature is that the labels are extract their values from two toolchains. Two are required otherwise there is a circular dependency between the manager and the configuration. - `//labgrid/toolchain/config:type` - `//labgrid/toolchain/manager:type` To do the lazy resolution of the toolchain, we do a configuration trick to transition further down the stack back into the target/exec combo that `labgrid_genrule` is in. This is contained under `//labgrid/cfg`. The way this works is: - `labgrid_genrule` uses `//labgrid/cfg/store.bzl` as an incoming transition - That transition stores the current platform in `//labgrid/cfg:platform` - Later, the `/labgrid/{config,manager}` targets use the `//labgrid/cfg/unstore.bzl` transition to put `//labgrid/cfg:platform` back into the target platform - Those rules then resolve the toolchains to get the registered information for the LabGrid target platform As of this patch, the Docker end-to-end test shows an example of the usage of `labgrid_config_toolchain`. `bazelisk test docker:test` has the same operation as before. --- e2e/docker/BUILD.bazel | 36 ++------ e2e/docker/manager.py | 16 ---- .../config}/BUILD.bazel | 2 +- e2e/toolchain/manager/BUILD.bazel | 6 ++ labgrid/cfg/BUILD.bazel | 4 + labgrid/cfg/store.bzl | 21 +++++ labgrid/cfg/unstore.bzl | 13 +++ labgrid/config/BUILD.bazel | 18 ++++ labgrid/config/defs.bzl | 5 ++ labgrid/config/deps.bzl | 21 +++++ labgrid/config/rule.bzl | 82 +++++++++++++++++++ labgrid/config/src.bzl | 26 ++++++ labgrid/config/toolchain/BUILD.bazel | 0 labgrid/config/toolchain/defs.bzl | 5 ++ labgrid/config/toolchain/macro.bzl | 34 ++++++++ labgrid/executor/BUILD.bazel | 38 ++++----- labgrid/executor/defs.bzl | 5 -- labgrid/executor/executor.py | 9 +- labgrid/executor/macro.bzl | 34 -------- labgrid/genrule/rule.bzl | 15 ++-- labgrid/manager/BUILD.bazel | 25 ++++++ labgrid/manager/config.py | 23 ++++++ labgrid/manager/defs.bzl | 5 ++ labgrid/manager/rule.bzl | 52 ++++++++++++ labgrid/manager/src.bzl | 21 +++++ labgrid/toolchain/config/BUILD.bazel | 4 + labgrid/toolchain/executor/BUILD.bazel | 11 --- labgrid/toolchain/manager/BUILD.bazel | 4 + 28 files changed, 409 insertions(+), 126 deletions(-) delete mode 100644 e2e/docker/manager.py rename e2e/{executor => toolchain/config}/BUILD.bazel (57%) create mode 100644 e2e/toolchain/manager/BUILD.bazel create mode 100644 labgrid/cfg/BUILD.bazel create mode 100644 labgrid/cfg/store.bzl create mode 100644 labgrid/cfg/unstore.bzl create mode 100644 labgrid/config/BUILD.bazel create mode 100644 labgrid/config/defs.bzl create mode 100644 labgrid/config/deps.bzl create mode 100644 labgrid/config/rule.bzl create mode 100644 labgrid/config/src.bzl create mode 100644 labgrid/config/toolchain/BUILD.bazel create mode 100644 labgrid/config/toolchain/defs.bzl create mode 100644 labgrid/config/toolchain/macro.bzl delete mode 100644 labgrid/executor/defs.bzl delete mode 100644 labgrid/executor/macro.bzl create mode 100644 labgrid/manager/BUILD.bazel create mode 100644 labgrid/manager/config.py create mode 100644 labgrid/manager/defs.bzl create mode 100644 labgrid/manager/rule.bzl create mode 100644 labgrid/manager/src.bzl create mode 100644 labgrid/toolchain/config/BUILD.bazel delete mode 100644 labgrid/toolchain/executor/BUILD.bazel create mode 100644 labgrid/toolchain/manager/BUILD.bazel diff --git a/e2e/docker/BUILD.bazel b/e2e/docker/BUILD.bazel index d174c1ff..5eaa22a3 100644 --- a/e2e/docker/BUILD.bazel +++ b/e2e/docker/BUILD.bazel @@ -1,9 +1,8 @@ load("@rules_diff//diff/file/test:defs.bzl", "diff_file_test") -load("@rules_labgrid//labgrid/executor:defs.bzl", "labgrid_executor") +load("@rules_labgrid//labgrid/config/toolchain:defs.bzl", "labgrid_config_toolchain") load("@rules_labgrid//labgrid/genrule:defs.bzl", "labgrid_genrule") load("@rules_labgrid//labgrid/transition:defs.bzl", "labgrid_transition") -load("@rules_python//python:defs.bzl", "py_binary", "py_library") -load("@toolchain_utils//toolchain/info:defs.bzl", "toolchain_info") +load("@rules_python//python:defs.bzl", "py_binary") # The goal of this test/example is to use the nut/bolts of `rules_labgrid` # It exposes _all_ the steps to configure the `labgrid_genrule` @@ -25,31 +24,11 @@ py_binary( data = ["local-ubuntu.16.04-gnu.yaml"], tags = ["manual"], deps = [ - "@pip//docker", + "@rules_labgrid//labgrid/config:deps", "@rules_labgrid//labgrid/python", ], ) -# An execution manager that is responsible for setting up the LabGrid environment -py_library( - name = "manager", - srcs = ["manager.py"], - data = ["local-ubuntu.16.04-gnu.yaml"], - deps = ["@rules_labgrid//bazel/labgrid/executor"], -) - -# Create the LabGrid executor binary using our manager -labgrid_executor( - name = "executor", - deps = [":manager"], -) - -# Create toolchain information around the executor -toolchain_info( - name = "info", - target = ":executor", -) - # A constraint to register the toolchain to constraint_setting(name = "device") @@ -69,14 +48,15 @@ platform( ) # Provide the toolchain with Bazel -toolchain( - name = "toolchain", +labgrid_config_toolchain( + name = "config", + src = "local-ubuntu.16.04-gnu.yaml", + manager = "@rules_labgrid//labgrid/manager:config", target_compatible_with = [ ":constraint", "@toolchain_utils//toolchain/constraint/os:linux", ], - toolchain = ":info", - toolchain_type = "@rules_labgrid//labgrid/toolchain/executor:type", + deps = ["@pip//docker"], ) # A simplistic implementation of cat which dependends on runfiles diff --git a/e2e/docker/manager.py b/e2e/docker/manager.py deleted file mode 100644 index 192ab9df..00000000 --- a/e2e/docker/manager.py +++ /dev/null @@ -1,16 +0,0 @@ -from __future__ import annotations - -from contextlib import contextmanager -from typing import Iterator - -from python.runfiles import Runfiles - -from bazel.labgrid.executor.manager import Data, Manager - - -@contextmanager -def manager() -> Iterator[Run]: - runfiles = Runfiles.Create() - config = runfiles.Rlocation("_main/docker/local-ubuntu.16.04-gnu.yaml") - env = {"LG_ENV": config} - yield Data(env=env) diff --git a/e2e/executor/BUILD.bazel b/e2e/toolchain/config/BUILD.bazel similarity index 57% rename from e2e/executor/BUILD.bazel rename to e2e/toolchain/config/BUILD.bazel index 8ae8f4b5..d2bf2e1c 100644 --- a/e2e/executor/BUILD.bazel +++ b/e2e/toolchain/config/BUILD.bazel @@ -2,5 +2,5 @@ load("@bazel_skylib//rules:build_test.bzl", "build_test") build_test( name = "type", - targets = ["@rules_labgrid//labgrid/toolchain/executor:type"], + targets = ["@rules_labgrid//labgrid/toolchain/config:type"], ) diff --git a/e2e/toolchain/manager/BUILD.bazel b/e2e/toolchain/manager/BUILD.bazel new file mode 100644 index 00000000..8bd461b4 --- /dev/null +++ b/e2e/toolchain/manager/BUILD.bazel @@ -0,0 +1,6 @@ +load("@bazel_skylib//rules:build_test.bzl", "build_test") + +build_test( + name = "type", + targets = ["@rules_labgrid//labgrid/toolchain/manager:type"], +) diff --git a/labgrid/cfg/BUILD.bazel b/labgrid/cfg/BUILD.bazel new file mode 100644 index 00000000..14766462 --- /dev/null +++ b/labgrid/cfg/BUILD.bazel @@ -0,0 +1,4 @@ +label_setting( + name = "platform", + build_setting_default = "@platforms//host", +) diff --git a/labgrid/cfg/store.bzl b/labgrid/cfg/store.bzl new file mode 100644 index 00000000..15d63c40 --- /dev/null +++ b/labgrid/cfg/store.bzl @@ -0,0 +1,21 @@ +load("@bazel_skylib//lib:types.bzl", "types") + +visibility("//...") + +def _each(platform): + return { + "//command_line_option:platforms": str(platform), + "//labgrid/cfg:platform": str(platform), + } + +def implementation(settings, attr): + platform = settings["//command_line_option:platforms"] + if types.is_list(platform): + return [_each(p) for p in platform] + return _each(platform) + +store = transition( + implementation = implementation, + inputs = ["//command_line_option:platforms"], + outputs = ["//command_line_option:platforms", "//labgrid/cfg:platform"], +) diff --git a/labgrid/cfg/unstore.bzl b/labgrid/cfg/unstore.bzl new file mode 100644 index 00000000..f15b264d --- /dev/null +++ b/labgrid/cfg/unstore.bzl @@ -0,0 +1,13 @@ +visibility("//...") + +def implementation(settings, attr): + platform = settings["//labgrid/cfg:platform"] + return { + "//command_line_option:platforms": str(platform), + } + +unstore = transition( + implementation = implementation, + inputs = ["//labgrid/cfg:platform"], + outputs = ["//command_line_option:platforms"], +) diff --git a/labgrid/config/BUILD.bazel b/labgrid/config/BUILD.bazel new file mode 100644 index 00000000..71e79285 --- /dev/null +++ b/labgrid/config/BUILD.bazel @@ -0,0 +1,18 @@ +load(":src.bzl", "src") +load(":deps.bzl", "deps") + +src( + name = "src", + visibility = ["//visibility:public"], +) + +alias( + name = "config", + actual = "src", + visibility = ["//visibility:public"], +) + +deps( + name = "deps", + visibility = ["//visibility:public"], +) diff --git a/labgrid/config/defs.bzl b/labgrid/config/defs.bzl new file mode 100644 index 00000000..a82a67ff --- /dev/null +++ b/labgrid/config/defs.bzl @@ -0,0 +1,5 @@ +load(":rule.bzl", _config = "config") + +visibility("public") + +labgrid_config = _config diff --git a/labgrid/config/deps.bzl b/labgrid/config/deps.bzl new file mode 100644 index 00000000..3866e918 --- /dev/null +++ b/labgrid/config/deps.bzl @@ -0,0 +1,21 @@ +load("//labgrid/cfg:unstore.bzl", _cfg = "unstore") +load("@rules_python//python:defs.bzl", "PyInfo") + +visibility("//labgrid/config/...") + +DOC = "Unpacks the `deps` from the `//labgrid/toolchain/config:type` toolchain" + +ATTRS = {} + +def implementation(ctx): + toolchain = ctx.toolchains["//labgrid/toolchain/config:type"] + return list(toolchain.deps) + +deps = rule( + doc = DOC, + attrs = ATTRS, + implementation = implementation, + provides = [PyInfo], + toolchains = ["//labgrid/toolchain/config:type"], + cfg = _cfg, +) diff --git a/labgrid/config/rule.bzl b/labgrid/config/rule.bzl new file mode 100644 index 00000000..ced0a6f8 --- /dev/null +++ b/labgrid/config/rule.bzl @@ -0,0 +1,82 @@ +load("@rules_python//python:defs.bzl", "PyInfo") + +visibility("//...") + +DOC = """ +Binds a LabGrid configuration file to the associated data required to setup, load and teardown the LabGrid environment. + +```py +labgrid_config( + name = "config", + src = "docker.yaml", + deps = ["@pip//:docker"], +) + +toolchain( + name = "docker", + target_compatible_with = ["//constraint:docker"], + toolchain = ":config", + toolchain_type = "@rules_labgrid//labgrid/toolchain/config:type", +) +``` + +A tool can resolve the attributes via the late-bound labels: + +- `@rules_labgrid//labgrid/config:src` +- `@rules_labgrid//labgrid/config:deps` + +For example, a tool that works with `labgrid_genrule`: + +```py +py_binary( + name = "example", + srcs = ["example.py"], + deps = ["@rules_labgrid//labgrid/config:deps"], +) + +labgrid_genrule( + name = "gen", + cmd = "$(location :example)", + tools = [":example"], + platform = "//platform:docker", +) +``` + +The `deps` label will be resolved to the correct Python depedendencies needed to load the configuration. +""" + +ATTRS = { + "src": attr.label( + doc = "The LabGrid configuration YAML.", + allow_single_file = [".yml", ".yaml"], + ), + "deps": attr.label_list( + doc = "LabGrid configuration Python dependencies.", + providers = [[DefaultInfo, PyInfo]], + cfg = "exec", + ), +} + +def _forward(target): + return target[DefaultInfo], target[PyInfo] + +def _flatten(iterable): + return [e for x in iterable for e in x] + +def implementation(ctx): + default = DefaultInfo(files = depset([ctx.file.src])) + toolchain = platform_common.ToolchainInfo( + src = ctx.file.src, + deps = _flatten([_forward(d) for d in ctx.attr.deps]), + ) + + return [default, toolchain] + +labgrid_config = rule( + doc = DOC, + attrs = ATTRS, + implementation = implementation, + provides = [DefaultInfo, platform_common.ToolchainInfo], +) + +config = labgrid_config diff --git a/labgrid/config/src.bzl b/labgrid/config/src.bzl new file mode 100644 index 00000000..0e010838 --- /dev/null +++ b/labgrid/config/src.bzl @@ -0,0 +1,26 @@ +load("//labgrid/cfg:unstore.bzl", _cfg = "unstore") +load("@rules_python//python:defs.bzl", "PyInfo") + +visibility("//labgrid/config/...") + +DOC = "Unpacks the `src` from the `//labgrid/toolchain/config:type` toolchain" + +ATTRS = {} + +def implementation(ctx): + toolchain = ctx.toolchains["//labgrid/toolchain/config:type"] + output = ctx.actions.declare_file("{}.yaml".format(ctx.label.name)) + ctx.actions.symlink( + target_file = toolchain.src, + output = output, + is_executable = False, + ) + return DefaultInfo(files = depset([output])) + +src = rule( + doc = DOC, + attrs = ATTRS, + implementation = implementation, + toolchains = ["//labgrid/toolchain/config:type"], + cfg = _cfg, +) diff --git a/labgrid/config/toolchain/BUILD.bazel b/labgrid/config/toolchain/BUILD.bazel new file mode 100644 index 00000000..e69de29b diff --git a/labgrid/config/toolchain/defs.bzl b/labgrid/config/toolchain/defs.bzl new file mode 100644 index 00000000..129d40b3 --- /dev/null +++ b/labgrid/config/toolchain/defs.bzl @@ -0,0 +1,5 @@ +load(":macro.bzl", _toolchain = "toolchain") + +visibility("public") + +labgrid_config_toolchain = _toolchain diff --git a/labgrid/config/toolchain/macro.bzl b/labgrid/config/toolchain/macro.bzl new file mode 100644 index 00000000..1ad3692d --- /dev/null +++ b/labgrid/config/toolchain/macro.bzl @@ -0,0 +1,34 @@ +load("@rules_labgrid//labgrid/config:defs.bzl", "labgrid_config") +load("@rules_labgrid//labgrid/manager:defs.bzl", "labgrid_manager") + +visibility("//...") + +def labgrid_config_toolchain(*, name, src, manager, target_compatible_with, deps = ()): + labgrid_config( + name = "{}-config".format(name), + src = native.package_relative_label(src), + deps = [native.package_relative_label(d) for d in deps], + ) + + labgrid_manager( + name = "{}-manager".format(name), + src = native.package_relative_label(manager), + ) + + constraints = [native.package_relative_label(c) for c in target_compatible_with] + + native.toolchain( + name = "{}-config-toolchain".format(name), + target_compatible_with = constraints, + toolchain = "{}-config".format(name), + toolchain_type = "@rules_labgrid//labgrid/toolchain/config:type", + ) + + native.toolchain( + name = "{}-manager-toolchain".format(name), + target_compatible_with = constraints, + toolchain = "{}-manager".format(name), + toolchain_type = "@rules_labgrid//labgrid/toolchain/manager:type", + ) + +toolchain = labgrid_config_toolchain diff --git a/labgrid/executor/BUILD.bazel b/labgrid/executor/BUILD.bazel index ba75acaf..20db4415 100644 --- a/labgrid/executor/BUILD.bazel +++ b/labgrid/executor/BUILD.bazel @@ -1,27 +1,17 @@ load("@rules_python//python:defs.bzl", "py_binary", "py_library", "py_test") -load("@toolchain_utils//toolchain/symlink/target:defs.bzl", "toolchain_symlink_target") - -exports_files( - ["executor.py"], -) - -alias( - name = "main", - actual = "executor.py", - visibility = ["//visibility:public"], -) - -filegroup( - name = "srcs", - srcs = ["executor.py"], - visibility = ["//visibility:public"], -) py_binary( name = "executor", - srcs = [":srcs"], - visibility = ["//visibility:public"], - deps = ["//bazel/labgrid/executor"], + srcs = ["executor.py"], + env = { + "LABGRID_EXECUTOR_MANAGER": "$(location //labgrid/manager)", + }, + tags = ["manual"], + visibility = ["//:__subpackages__"], + deps = [ + "//bazel/labgrid/executor", + "//labgrid/manager", + ], ) py_library( @@ -37,21 +27,21 @@ py_library( py_test( name = "argument", size = "small", - srcs = [":srcs"], + srcs = ["executor.py"], args = [ "--manager", "labgrid.executor.host:manager", "echo", "$${DATA}", ], - main = ":main", + main = "executor.py", deps = ["host"], ) py_test( name = "envvar", size = "small", - srcs = [":srcs"], + srcs = ["executor.py"], args = [ "echo", "$${DATA}", @@ -59,6 +49,6 @@ py_test( env = { "LABGRID_EXECUTOR_MANAGER": "labgrid.executor.host:manager", }, - main = ":main", + main = "executor.py", deps = ["host"], ) diff --git a/labgrid/executor/defs.bzl b/labgrid/executor/defs.bzl deleted file mode 100644 index feed49e1..00000000 --- a/labgrid/executor/defs.bzl +++ /dev/null @@ -1,5 +0,0 @@ -load(":macro.bzl", _executor = "executor") - -visibility("public") - -labgrid_executor = _executor diff --git a/labgrid/executor/executor.py b/labgrid/executor/executor.py index 570ad65b..81c246d3 100644 --- a/labgrid/executor/executor.py +++ b/labgrid/executor/executor.py @@ -7,7 +7,7 @@ from contextlib import AbstractContextManager from importlib import import_module from inspect import signature from os import environ -from pathlib import Path +from pathlib import Path, PurePath from platform import machine, system from shutil import which from subprocess import CalledProcessError, run @@ -19,7 +19,12 @@ from bazel.labgrid.executor.manager import Manager def load(value: str) -> Manager: name, sep, attr = value.partition(":") if sep != ":": - raise ArgumentTypeError(f"`{value}` must be of the form `:`") + path = PurePath(value).with_suffix("") + parts = path.parts + if parts[0] == "..": + parts = parts[2:] + name = ".".join(parts) + attr = "manager" module = import_module(name) diff --git a/labgrid/executor/macro.bzl b/labgrid/executor/macro.bzl deleted file mode 100644 index da9217e8..00000000 --- a/labgrid/executor/macro.bzl +++ /dev/null @@ -1,34 +0,0 @@ -load("@rules_python//python:defs.bzl", "py_binary") - -visibility("//...") - -def _manager(labels, manager): - if manager: - return manager - - if len(labels) == 1: - label = labels[0] - if label.repo_name != "": - fail("TODO: Unsupported") - return "{}.{}:manager".format(label.package.replace("/", "."), label.name) - - fail('Unable to determine LabGrid manager, provide `manager = ":"`') - -def labgrid_executor( - *, - name, - deps, - manager = None, - env = {}): - labels = [native.package_relative_label(d) for d in deps] - py_binary( - name = name, - srcs = [Label(":srcs")], - main = Label(":main"), - deps = labels + [Label("@rules_python//python/runfiles")], - env = env | { - "LABGRID_EXECUTOR_MANAGER": _manager(labels, manager), - }, - ) - -executor = labgrid_executor diff --git a/labgrid/genrule/rule.bzl b/labgrid/genrule/rule.bzl index 752dbbe3..2ba49880 100644 --- a/labgrid/genrule/rule.bzl +++ b/labgrid/genrule/rule.bzl @@ -1,3 +1,4 @@ +load("//labgrid/cfg:store.bzl", _cfg = "store") load("@bazel_skylib//lib:shell.bzl", "shell") visibility("//...") @@ -28,6 +29,12 @@ ATTRS = { mandatory = True, allow_empty = False, ), + "_executor": attr.label( + doc = "The LabGrid environment executor", + default = "//labgrid/executor", + executable = True, + cfg = "exec", + ), "_sh": attr.label( doc = "The Shell interpreter", default = "@ape//:bash", @@ -62,8 +69,6 @@ def _substitutions(ctx): return substitutions def implementation(ctx): - executor = ctx.toolchains["//labgrid/toolchain/executor:type"] - cmd = ctx.expand_location(ctx.attr.cmd) for key, value in _substitutions(ctx).items(): cmd = cmd.replace(key, value) @@ -75,11 +80,11 @@ def implementation(ctx): args.add(cmd) ctx.actions.run( - executable = executor.run, + executable = ctx.executable._executor, arguments = [args], outputs = ctx.outputs.outs, tools = [t.files_to_run for t in (ctx.attr.tools + ctx.attr.srcs)] + [ctx.executable._sh], - env = executor.env, + env = ctx.attr._executor[RunEnvironmentInfo].environment, mnemonic = "LabGridGenrule", ) @@ -89,7 +94,7 @@ labgrid_genrule = rule( doc = DOC, attrs = ATTRS, implementation = implementation, - toolchains = ["//labgrid/toolchain/executor:type"], + cfg = _cfg, ) genrule = labgrid_genrule diff --git a/labgrid/manager/BUILD.bazel b/labgrid/manager/BUILD.bazel new file mode 100644 index 00000000..3be3ebd8 --- /dev/null +++ b/labgrid/manager/BUILD.bazel @@ -0,0 +1,25 @@ +load("@rules_python//python:defs.bzl", "py_library") +load(":src.bzl", "src") + +py_library( + name = "config", + srcs = ["config.py"], + data = ["//labgrid/config"], + tags = ["manual"], + visibility = ["//visibility:public"], + deps = [ + "@rules_labgrid//bazel/labgrid/executor", + "@rules_python//python/runfiles", + ], +) + +src( + name = "src", + visibility = ["//visibility:public"], +) + +alias( + name = "manager", + actual = "src", + visibility = ["//visibility:public"], +) diff --git a/labgrid/manager/config.py b/labgrid/manager/config.py new file mode 100644 index 00000000..a50560ef --- /dev/null +++ b/labgrid/manager/config.py @@ -0,0 +1,23 @@ +from __future__ import annotations + +from contextlib import contextmanager +from pathlib import Path +from typing import Iterator + +from python.runfiles import Runfiles + +from bazel.labgrid.executor.manager import Data + + +@contextmanager +def manager() -> Iterator[Data]: + """ + A LabGrid context manager that loads the resolved configuration into the `LG_ENV` environment variable. + """ + runfiles = Runfiles.Create() + config = runfiles.Rlocation("rules_labgrid/labgrid/config/src.yaml") + path = Path(config) + if not path.exists(): + raise FileNotFoundError(str(path)) + env = {"LG_ENV": str(path)} + yield Data(env=env) diff --git a/labgrid/manager/defs.bzl b/labgrid/manager/defs.bzl new file mode 100644 index 00000000..9d4ccce8 --- /dev/null +++ b/labgrid/manager/defs.bzl @@ -0,0 +1,5 @@ +load(":rule.bzl", _manager = "manager") + +visibility("public") + +labgrid_manager = _manager diff --git a/labgrid/manager/rule.bzl b/labgrid/manager/rule.bzl new file mode 100644 index 00000000..9326ccd4 --- /dev/null +++ b/labgrid/manager/rule.bzl @@ -0,0 +1,52 @@ +load("@rules_python//python:defs.bzl", "PyInfo") + +visibility("//...") + +DOC = """ +Determines the manager to load a LabGrid configuration. + +```py +labgrid_manager( + name = "config", + src = "@rules_labgrid//labgrid/manager:config", +) + +toolchain( + name = "docker", + target_compatible_with = ["//constraint:docker"], + toolchain = ":manager", + toolchain_type = "@rules_labgrid//labgrid/toolchain/manager:type", +) +``` + +A tool can resolve the attributes via the late-bound labels: + +- `@rules_labgrid//labgrid/manager:src` +""" + +ATTRS = { + "src": attr.label( + doc = "A context manager that `//labgrid/executor` will use that sets up the LabGrid environment.", + providers = [[DefaultInfo, PyInfo]], + cfg = "exec", + ), +} + +def _forward(target): + return target[DefaultInfo], target[PyInfo] + +def implementation(ctx): + toolchain = platform_common.ToolchainInfo( + src = _forward(ctx.attr.src), + ) + + return toolchain + +labgrid_manager = rule( + doc = DOC, + attrs = ATTRS, + implementation = implementation, + provides = [platform_common.ToolchainInfo], +) + +manager = labgrid_manager diff --git a/labgrid/manager/src.bzl b/labgrid/manager/src.bzl new file mode 100644 index 00000000..d194c641 --- /dev/null +++ b/labgrid/manager/src.bzl @@ -0,0 +1,21 @@ +load("//labgrid/cfg:unstore.bzl", _cfg = "unstore") +load("@rules_python//python:defs.bzl", "PyInfo") + +visibility("//labgrid/manager/...") + +DOC = "Unpacks the `src` from the `//labgrid/toolchain/manager:type` toolchain" + +ATTRS = {} + +def implementation(ctx): + toolchain = ctx.toolchains["//labgrid/toolchain/manager:type"] + return toolchain.src + +src = rule( + doc = DOC, + attrs = ATTRS, + implementation = implementation, + provides = [PyInfo], + toolchains = ["//labgrid/toolchain/manager:type"], + cfg = _cfg, +) diff --git a/labgrid/toolchain/config/BUILD.bazel b/labgrid/toolchain/config/BUILD.bazel new file mode 100644 index 00000000..51ee1b30 --- /dev/null +++ b/labgrid/toolchain/config/BUILD.bazel @@ -0,0 +1,4 @@ +toolchain_type( + name = "type", + visibility = ["//visibility:public"], +) diff --git a/labgrid/toolchain/executor/BUILD.bazel b/labgrid/toolchain/executor/BUILD.bazel deleted file mode 100644 index 2f9904d4..00000000 --- a/labgrid/toolchain/executor/BUILD.bazel +++ /dev/null @@ -1,11 +0,0 @@ -toolchain_type( - name = "type", - visibility = ["//visibility:public"], -) - -alias( - name = "resolved", - actual = "@resolved-executor", - tags = ["manual"], - visibility = ["//visibility:public"], -) diff --git a/labgrid/toolchain/manager/BUILD.bazel b/labgrid/toolchain/manager/BUILD.bazel new file mode 100644 index 00000000..51ee1b30 --- /dev/null +++ b/labgrid/toolchain/manager/BUILD.bazel @@ -0,0 +1,4 @@ +toolchain_type( + name = "type", + visibility = ["//visibility:public"], +) -- GitLab