Skip to content

Commit ade0b2b

Browse files
authored
refactor(toolchains): split the implementation of toolchain rules to separate files (bazel-contrib#2232)
This makes the dependency management in WORKSPACE much easier to do. Summary: - refactor: split out the py_repositories call to a separate file - refactor: split out the python_repository rule to a separate file - refactor: split out the standalone interpreter utility function - refactor: split out the python_register_toolchains function - refactor: rename the remaining file Work towards bazel-contrib#2081.
1 parent 27276b6 commit ade0b2b

12 files changed

+417
-276
lines changed

examples/bzlmod/MODULE.bazel.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

python/BUILD.bazel

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,11 @@ bzl_library(
229229
name = "repositories_bzl",
230230
srcs = ["repositories.bzl"],
231231
deps = [
232-
"//python/private:python_repositories_bzl",
232+
"//python/private:is_standalone_interpreter_bzl",
233+
"//python/private:py_repositories_bzl",
234+
"//python/private:python_register_multi_toolchains_bzl",
235+
"//python/private:python_register_toolchains_bzl",
236+
"//python/private:python_repository_bzl",
233237
],
234238
)
235239

python/private/BUILD.bazel

Lines changed: 49 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,14 @@ bzl_library(
123123
deps = [":bzlmod_enabled_bzl"],
124124
)
125125

126+
bzl_library(
127+
name = "is_standalone_interpreter_bzl",
128+
srcs = ["is_standalone_interpreter.bzl"],
129+
deps = [
130+
":repo_utils_bzl",
131+
],
132+
)
133+
126134
bzl_library(
127135
name = "normalize_name_bzl",
128136
srcs = ["normalize_name.bzl"],
@@ -143,22 +151,53 @@ bzl_library(
143151
)
144152

145153
bzl_library(
146-
name = "python_repositories_bzl",
147-
srcs = ["python_repositories.bzl"],
154+
name = "py_repositories_bzl",
155+
srcs = ["py_repositories.bzl"],
156+
deps = [
157+
":bazel_tools_bzl",
158+
":internal_config_repo_bzl",
159+
"//python/private/pypi:deps_bzl",
160+
],
161+
)
162+
163+
bzl_library(
164+
name = "python_register_toolchains_bzl",
165+
srcs = ["python_register_toolchains.bzl"],
148166
deps = [
167+
":auth_bzl",
168+
":bazel_tools_bzl",
169+
":bzlmod_enabled_bzl",
170+
":coverage_deps_bzl",
171+
":full_version_bzl",
172+
":internal_config_repo_bzl",
173+
":python_repository_bzl",
174+
":toolchains_repo_bzl",
149175
"//python:versions_bzl",
150-
"//python/private:auth_bzl",
151-
"//python/private:bazel_tools_bzl",
152-
"//python/private:bzlmod_enabled_bzl",
153-
"//python/private:coverage_deps_bzl",
154-
"//python/private:full_version_bzl",
155-
"//python/private:internal_config_repo_bzl",
156-
"//python/private:repo_utils_bzl",
157-
"//python/private:toolchains_repo_bzl",
158176
"//python/private/pypi:deps_bzl",
159177
],
160178
)
161179

180+
bzl_library(
181+
name = "python_repository_bzl",
182+
srcs = ["python_repository.bzl"],
183+
deps = [
184+
":auth_bzl",
185+
":repo_utils_bzl",
186+
":text_util_bzl",
187+
"//python:versions_bzl",
188+
],
189+
)
190+
191+
bzl_library(
192+
name = "python_register_multi_toolchains_bzl",
193+
srcs = ["python_register_multi_toolchains.bzl"],
194+
deps = [
195+
":python_register_toolchains_bzl",
196+
":toolchains_repo_bzl",
197+
"//python:versions_bzl",
198+
],
199+
)
200+
162201
bzl_library(
163202
name = "pythons_hub_bzl",
164203
srcs = ["pythons_hub.bzl"],
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# Copyright 2024 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+
"""This file contains repository rules and macros to support toolchain registration.
16+
"""
17+
18+
load(":repo_utils.bzl", "repo_utils")
19+
20+
STANDALONE_INTERPRETER_FILENAME = "STANDALONE_INTERPRETER"
21+
22+
def is_standalone_interpreter(rctx, python_interpreter_path, *, logger = None):
23+
"""Query a python interpreter target for whether or not it's a rules_rust provided toolchain
24+
25+
Args:
26+
rctx: {type}`repository_ctx` The repository rule's context object.
27+
python_interpreter_path: {type}`path` A path representing the interpreter.
28+
logger: Optional logger to use for operations.
29+
30+
Returns:
31+
{type}`bool` Whether or not the target is from a rules_python generated toolchain.
32+
"""
33+
34+
# Only update the location when using a hermetic toolchain.
35+
if not python_interpreter_path:
36+
return False
37+
38+
# This is a rules_python provided toolchain.
39+
return repo_utils.execute_unchecked(
40+
rctx,
41+
op = "IsStandaloneInterpreter",
42+
arguments = [
43+
"ls",
44+
"{}/{}".format(
45+
python_interpreter_path.dirname,
46+
STANDALONE_INTERPRETER_FILENAME,
47+
),
48+
],
49+
logger = logger,
50+
).return_code == 0

python/private/py_repositories.bzl

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# Copyright 2024 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+
"""This file contains macros to be called during WORKSPACE evaluation."""
16+
17+
load("@bazel_tools//tools/build_defs/repo:http.bzl", _http_archive = "http_archive")
18+
load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe")
19+
load("//python/private/pypi:deps.bzl", "pypi_deps")
20+
load(":internal_config_repo.bzl", "internal_config_repo")
21+
22+
def http_archive(**kwargs):
23+
maybe(_http_archive, **kwargs)
24+
25+
def py_repositories():
26+
"""Runtime dependencies that users must install.
27+
28+
This function should be loaded and called in the user's WORKSPACE.
29+
With bzlmod enabled, this function is not needed since MODULE.bazel handles transitive deps.
30+
"""
31+
maybe(
32+
internal_config_repo,
33+
name = "rules_python_internal",
34+
)
35+
http_archive(
36+
name = "bazel_skylib",
37+
sha256 = "74d544d96f4a5bb630d465ca8bbcfe231e3594e5aae57e1edbf17a6eb3ca2506",
38+
urls = [
39+
"https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.3.0/bazel-skylib-1.3.0.tar.gz",
40+
"https://github.com/bazelbuild/bazel-skylib/releases/download/1.3.0/bazel-skylib-1.3.0.tar.gz",
41+
],
42+
)
43+
http_archive(
44+
name = "rules_cc",
45+
urls = ["https://github.com/bazelbuild/rules_cc/releases/download/0.0.9/rules_cc-0.0.9.tar.gz"],
46+
sha256 = "2037875b9a4456dce4a79d112a8ae885bbc4aad968e6587dca6e64f3a0900cdf",
47+
strip_prefix = "rules_cc-0.0.9",
48+
)
49+
pypi_deps()

python/private/pypi/BUILD.bazel

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -306,9 +306,9 @@ bzl_library(
306306
":patch_whl_bzl",
307307
":pypi_repo_utils_bzl",
308308
":whl_target_platforms_bzl",
309-
"//python:repositories_bzl",
310309
"//python/private:auth_bzl",
311310
"//python/private:envsubst_bzl",
311+
"//python/private:is_standalone_interpreter_bzl",
312312
"//python/private:repo_utils_bzl",
313313
],
314314
)

python/private/pypi/whl_library.bzl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
load("//python/private:auth.bzl", "AUTH_ATTRS", "get_auth")
1818
load("//python/private:envsubst.bzl", "envsubst")
19-
load("//python/private:python_repositories.bzl", "is_standalone_interpreter")
19+
load("//python/private:is_standalone_interpreter.bzl", "is_standalone_interpreter")
2020
load("//python/private:repo_utils.bzl", "REPO_DEBUG_ENV_VAR", "repo_utils")
2121
load(":attrs.bzl", "ATTRS", "use_isolated")
2222
load(":deps.bzl", "all_repo_names")

python/private/python.bzl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@
1515
"Python toolchain module extensions for use with bzlmod"
1616

1717
load("@bazel_features//:features.bzl", "bazel_features")
18-
load("//python:repositories.bzl", "python_register_toolchains")
1918
load("//python:versions.bzl", "MINOR_MAPPING", "TOOL_VERSIONS")
2019
load(":full_version.bzl", "full_version")
20+
load(":python_register_toolchains.bzl", "python_register_toolchains")
2121
load(":pythons_hub.bzl", "hub_repo")
2222
load(":repo_utils.bzl", "repo_utils")
2323
load(":text_util.bzl", "render")
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
# Copyright 2024 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+
"""This file contains repository rules and macros to support toolchain registration.
16+
"""
17+
18+
load("//python:versions.bzl", "MINOR_MAPPING")
19+
load(":python_register_toolchains.bzl", "python_register_toolchains")
20+
load(":toolchains_repo.bzl", "multi_toolchain_aliases")
21+
22+
def python_register_multi_toolchains(
23+
name,
24+
python_versions,
25+
default_version = None,
26+
minor_mapping = None,
27+
**kwargs):
28+
"""Convenience macro for registering multiple Python toolchains.
29+
30+
Args:
31+
name: {type}`str` base name for each name in {obj}`python_register_toolchains` call.
32+
python_versions: {type}`list[str]` the Python versions.
33+
default_version: {type}`str` the default Python version. If not set,
34+
the first version in python_versions is used.
35+
minor_mapping: {type}`dict[str, str]` mapping between `X.Y` to `X.Y.Z`
36+
format. Defaults to the value in `//python:versions.bzl`.
37+
**kwargs: passed to each {obj}`python_register_toolchains` call.
38+
"""
39+
if len(python_versions) == 0:
40+
fail("python_versions must not be empty")
41+
42+
minor_mapping = minor_mapping or MINOR_MAPPING
43+
44+
if not default_version:
45+
default_version = python_versions.pop(0)
46+
for python_version in python_versions:
47+
if python_version == default_version:
48+
# We register the default version lastly so that it's not picked first when --platforms
49+
# is set with a constraint during toolchain resolution. This is due to the fact that
50+
# Bazel will match the unconstrained toolchain if we register it before the constrained
51+
# ones.
52+
continue
53+
python_register_toolchains(
54+
name = name + "_" + python_version.replace(".", "_"),
55+
python_version = python_version,
56+
set_python_version_constraint = True,
57+
minor_mapping = minor_mapping,
58+
**kwargs
59+
)
60+
python_register_toolchains(
61+
name = name + "_" + default_version.replace(".", "_"),
62+
python_version = default_version,
63+
set_python_version_constraint = False,
64+
minor_mapping = minor_mapping,
65+
**kwargs
66+
)
67+
68+
multi_toolchain_aliases(
69+
name = name,
70+
python_versions = {
71+
python_version: name + "_" + python_version.replace(".", "_")
72+
for python_version in (python_versions + [default_version])
73+
},
74+
minor_mapping = minor_mapping,
75+
)

0 commit comments

Comments
 (0)