Skip to content

Commit

Permalink
fix: Don't require downstream users to register Python toolchains.
Browse files Browse the repository at this point in the history
The Python toolchains are only needed for dev purposes (doc generation).

Unfortunately, Bazel doesn't provide an easy way to mark a
register_toolchains() call as dev-only. To work around this, we use an
extension to create a repository whose contents depend on if its the
root module or not. If its the root module, it means we're the
rules_testing module and its the dev-dependency case, so write a
build file with the real toolchains. If its not the root module, then
its not the dev-dependency case, so write an empty build file.

Fixes #33
  • Loading branch information
rickeylev committed Apr 27, 2023
1 parent 79fd582 commit 45471ea
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 3 deletions.
23 changes: 20 additions & 3 deletions MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,29 @@ python.toolchain(
name = "python3_11",
python_version = "3.11",
)
use_repo(python, "python3_11_toolchains")

register_toolchains(
"@python3_11_toolchains//:all",
# NOTE: use_repo() must be called for each platform that runs the docgen tools
use_repo(
python,
"python3_11_toolchains",
"python3_11_x86_64-unknown-linux-gnu",
)

# NOTE: This is actualy a dev dependency, but due to
# https://github.com/bazelbuild/bazel/issues/18248
# it has to be non-dev to generate the repo name used
# in the subsequent register_toolchains() call.
dev = use_extension(
"//:dev_extension.bzl",
"dev",
)
dev.setup()
use_repo(dev, "rules_testing_dev_toolchains")

# NOTE: This call will be run by downstream users, so the
# repos it mentions must exist.
register_toolchains("@rules_testing_dev_toolchains//:all")

pip = use_extension(
"@rules_python//python:extensions.bzl",
"pip",
Expand Down
36 changes: 36 additions & 0 deletions dev_extension.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
"""Extension only used for development purposes."""

def _dev_ext_impl(mctx):
module = mctx.modules[0]
_dev_toolchains_repo(
name = "rules_testing_dev_toolchains",
is_root = module.is_root,
)

dev = module_extension(
implementation = _dev_ext_impl,
tag_classes = {
"setup": tag_class(),
},
)

def _dev_toolchains_repo_impl(rctx):
# If its the root module, then we're in rules_testing and
# it's a dev dependency situation.
if rctx.attr.is_root:
toolchain_build = Label("@python3_11_toolchains//:BUILD.bazel")

# NOTE: This is brittle. It only works because, luckily,
# rules_python's toolchain BUILD file is essentially self-contained.
# It only uses absolute references and doesn't load anything,
# so we can copy it elsewhere and it still works.
rctx.symlink(toolchain_build, "BUILD.bazel")
else:
rctx.file("BUILD.bazel", "")

_dev_toolchains_repo = repository_rule(
implementation = _dev_toolchains_repo_impl,
attrs = {
"is_root": attr.bool(),
},
)
4 changes: 4 additions & 0 deletions e2e/bzlmod/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,7 @@
load(":tests.bzl", "bzlmod_test_suite")

bzlmod_test_suite(name = "bzlmod_tests")

toolchain_type(
name = "fake",
)
27 changes: 27 additions & 0 deletions e2e/bzlmod/tests.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,31 @@ def _simple_test_impl(env, target):
def bzlmod_test_suite(name):
test_suite(name = name, tests = [
_simple_test,
_trigger_toolchains_test,
])

def _needs_toolchain_impl(ctx):
# We just need to trigger toolchain resolution, we don't
# care about the result.
_unused = ctx.toolchains["//:fake"]

_needs_toolchain = rule(
implementation = _needs_toolchain_impl,
toolchains = [config_common.toolchain_type("//:fake", mandatory = False)],
)

def _trigger_toolchains_test_impl(env, target):
# Building is sufficient evidence of success
_ = env, target # @unused

# A regression test for https://github.com/bazelbuild/rules_testing/issues/33
def _trigger_toolchains_test(name):
util.helper_target(
_needs_toolchain,
name = name + "_subject",
)
analysis_test(
name = name,
impl = _trigger_toolchains_test_impl,
target = name + "_subject",
)

0 comments on commit 45471ea

Please sign in to comment.