Skip to content

Commit c473ea8

Browse files
committed
fix: Don't require downstream users to register Python toolchains.
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
1 parent 79fd582 commit c473ea8

File tree

4 files changed

+101
-3
lines changed

4 files changed

+101
-3
lines changed

MODULE.bazel

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,29 @@ python.toolchain(
2929
name = "python3_11",
3030
python_version = "3.11",
3131
)
32-
use_repo(python, "python3_11_toolchains")
3332

34-
register_toolchains(
35-
"@python3_11_toolchains//:all",
33+
# NOTE: use_repo() must be called for each platform that runs the docgen tools
34+
use_repo(
35+
python,
36+
"python3_11_toolchains",
37+
"python3_11_x86_64-unknown-linux-gnu",
3638
)
3739

40+
# NOTE: This is actualy a dev dependency, but due to
41+
# https://github.com/bazelbuild/bazel/issues/18248
42+
# it has to be non-dev to generate the repo name used
43+
# in the subsequent register_toolchains() call.
44+
dev = use_extension(
45+
"//:dev_extension.bzl",
46+
"dev",
47+
)
48+
dev.setup()
49+
use_repo(dev, "rules_testing_dev_toolchains")
50+
51+
# NOTE: This call will be run by downstream users, so the
52+
# repos it mentions must exist.
53+
register_toolchains("@rules_testing_dev_toolchains//:all")
54+
3855
pip = use_extension(
3956
"@rules_python//python:extensions.bzl",
4057
"pip",

dev_extension.bzl

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# Copyright 2023 The Bazel Authors. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
"""Extension only used for development purposes."""
16+
17+
def _dev_ext_impl(mctx):
18+
module = mctx.modules[0]
19+
_dev_toolchains_repo(
20+
name = "rules_testing_dev_toolchains",
21+
is_root = module.is_root,
22+
)
23+
24+
dev = module_extension(
25+
implementation = _dev_ext_impl,
26+
tag_classes = {
27+
"setup": tag_class(),
28+
},
29+
)
30+
31+
def _dev_toolchains_repo_impl(rctx):
32+
# If its the root module, then we're in rules_testing and
33+
# it's a dev dependency situation.
34+
if rctx.attr.is_root:
35+
toolchain_build = Label("@python3_11_toolchains//:BUILD.bazel")
36+
37+
# NOTE: This is brittle. It only works because, luckily,
38+
# rules_python's toolchain BUILD file is essentially self-contained.
39+
# It only uses absolute references and doesn't load anything,
40+
# so we can copy it elsewhere and it still works.
41+
rctx.symlink(toolchain_build, "BUILD.bazel")
42+
else:
43+
rctx.file("BUILD.bazel", "")
44+
45+
_dev_toolchains_repo = repository_rule(
46+
implementation = _dev_toolchains_repo_impl,
47+
attrs = {
48+
"is_root": attr.bool(),
49+
},
50+
)

e2e/bzlmod/BUILD.bazel

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,7 @@
33
load(":tests.bzl", "bzlmod_test_suite")
44

55
bzlmod_test_suite(name = "bzlmod_tests")
6+
7+
toolchain_type(
8+
name = "fake",
9+
)

e2e/bzlmod/tests.bzl

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,31 @@ def _simple_test_impl(env, target):
3838
def bzlmod_test_suite(name):
3939
test_suite(name = name, tests = [
4040
_simple_test,
41+
_trigger_toolchains_test,
4142
])
43+
44+
def _needs_toolchain_impl(ctx):
45+
# We just need to trigger toolchain resolution, we don't
46+
# care about the result.
47+
_ = ctx.toolchains["//:fake"] # @unused
48+
49+
_needs_toolchain = rule(
50+
implementation = _needs_toolchain_impl,
51+
toolchains = [config_common.toolchain_type("//:fake", mandatory = False)],
52+
)
53+
54+
def _trigger_toolchains_test_impl(env, target):
55+
# Building is sufficient evidence of success
56+
_ = env, target # @unused
57+
58+
# A regression test for https://github.com/bazelbuild/rules_testing/issues/33
59+
def _trigger_toolchains_test(name):
60+
util.helper_target(
61+
_needs_toolchain,
62+
name = name + "_subject",
63+
)
64+
analysis_test(
65+
name = name,
66+
impl = _trigger_toolchains_test_impl,
67+
target = name + "_subject",
68+
)

0 commit comments

Comments
 (0)