refactor(toolchains): split the implementation of toolchain rules to separate files (#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 #2081.
diff --git a/examples/bzlmod/MODULE.bazel.lock b/examples/bzlmod/MODULE.bazel.lock
index f0144e8..234dc46 100644
--- a/examples/bzlmod/MODULE.bazel.lock
+++ b/examples/bzlmod/MODULE.bazel.lock
@@ -1231,7 +1231,7 @@
},
"@@rules_python~//python/extensions:pip.bzl%pip": {
"general": {
- "bzlTransitiveDigest": "jb9c5l3dvSB2MHd/zfkT8Yr8efvg+K/YHtiRHU3aU6o=",
+ "bzlTransitiveDigest": "Cca+OPIA5xqQl5ND8j44y5jBkjQfz+36h8Hgq0N26I0=",
"usagesDigest": "MChlcSw99EuW3K7OOoMcXQIdcJnEh6YmfyjJm+9mxIg=",
"recordedFileInputs": {
"@@other_module~//requirements_lock_3_11.txt": "a7d0061366569043d5efcf80e34a32c732679367cb3c831c4cdc606adc36d314",
@@ -6140,7 +6140,7 @@
},
"@@rules_python~//python/private/pypi:pip.bzl%pip_internal": {
"general": {
- "bzlTransitiveDigest": "cLqaqCEOdhle6//lX1Kcs2hfkmSerh2fk0izwhV8/GU=",
+ "bzlTransitiveDigest": "wkQNgti5fKONsAUn77ZyTWdfaJfI2cSDrSI0b4JzmI8=",
"usagesDigest": "Y8ihY+R57BAFhalrVLVdJFrpwlbsiKz9JPJ99ljF7HA=",
"recordedFileInputs": {
"@@rules_python~//tools/publish/requirements.txt": "031e35d03dde03ae6305fe4b3d1f58ad7bdad857379752deede0f93649991b8a",
diff --git a/python/BUILD.bazel b/python/BUILD.bazel
index 6fcde38..b7a2172 100644
--- a/python/BUILD.bazel
+++ b/python/BUILD.bazel
@@ -229,7 +229,11 @@
name = "repositories_bzl",
srcs = ["repositories.bzl"],
deps = [
- "//python/private:python_repositories_bzl",
+ "//python/private:is_standalone_interpreter_bzl",
+ "//python/private:py_repositories_bzl",
+ "//python/private:python_register_multi_toolchains_bzl",
+ "//python/private:python_register_toolchains_bzl",
+ "//python/private:python_repository_bzl",
],
)
diff --git a/python/private/BUILD.bazel b/python/private/BUILD.bazel
index 1e05b92..5fa5514 100644
--- a/python/private/BUILD.bazel
+++ b/python/private/BUILD.bazel
@@ -124,6 +124,14 @@
)
bzl_library(
+ name = "is_standalone_interpreter_bzl",
+ srcs = ["is_standalone_interpreter.bzl"],
+ deps = [
+ ":repo_utils_bzl",
+ ],
+)
+
+bzl_library(
name = "normalize_name_bzl",
srcs = ["normalize_name.bzl"],
)
@@ -143,23 +151,54 @@
)
bzl_library(
- name = "python_repositories_bzl",
- srcs = ["python_repositories.bzl"],
+ name = "py_repositories_bzl",
+ srcs = ["py_repositories.bzl"],
deps = [
- "//python:versions_bzl",
- "//python/private:auth_bzl",
- "//python/private:bazel_tools_bzl",
- "//python/private:bzlmod_enabled_bzl",
- "//python/private:coverage_deps_bzl",
- "//python/private:full_version_bzl",
- "//python/private:internal_config_repo_bzl",
- "//python/private:repo_utils_bzl",
- "//python/private:toolchains_repo_bzl",
+ ":bazel_tools_bzl",
+ ":internal_config_repo_bzl",
"//python/private/pypi:deps_bzl",
],
)
bzl_library(
+ name = "python_register_toolchains_bzl",
+ srcs = ["python_register_toolchains.bzl"],
+ deps = [
+ ":auth_bzl",
+ ":bazel_tools_bzl",
+ ":bzlmod_enabled_bzl",
+ ":coverage_deps_bzl",
+ ":full_version_bzl",
+ ":internal_config_repo_bzl",
+ ":python_repository_bzl",
+ ":toolchains_repo_bzl",
+ "//python:versions_bzl",
+ "//python/private/pypi:deps_bzl",
+ ],
+)
+
+bzl_library(
+ name = "python_repository_bzl",
+ srcs = ["python_repository.bzl"],
+ deps = [
+ ":auth_bzl",
+ ":repo_utils_bzl",
+ ":text_util_bzl",
+ "//python:versions_bzl",
+ ],
+)
+
+bzl_library(
+ name = "python_register_multi_toolchains_bzl",
+ srcs = ["python_register_multi_toolchains.bzl"],
+ deps = [
+ ":python_register_toolchains_bzl",
+ ":toolchains_repo_bzl",
+ "//python:versions_bzl",
+ ],
+)
+
+bzl_library(
name = "pythons_hub_bzl",
srcs = ["pythons_hub.bzl"],
deps = [
diff --git a/python/private/is_standalone_interpreter.bzl b/python/private/is_standalone_interpreter.bzl
new file mode 100644
index 0000000..5da7389
--- /dev/null
+++ b/python/private/is_standalone_interpreter.bzl
@@ -0,0 +1,50 @@
+# Copyright 2024 The Bazel Authors. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""This file contains repository rules and macros to support toolchain registration.
+"""
+
+load(":repo_utils.bzl", "repo_utils")
+
+STANDALONE_INTERPRETER_FILENAME = "STANDALONE_INTERPRETER"
+
+def is_standalone_interpreter(rctx, python_interpreter_path, *, logger = None):
+ """Query a python interpreter target for whether or not it's a rules_rust provided toolchain
+
+ Args:
+ rctx: {type}`repository_ctx` The repository rule's context object.
+ python_interpreter_path: {type}`path` A path representing the interpreter.
+ logger: Optional logger to use for operations.
+
+ Returns:
+ {type}`bool` Whether or not the target is from a rules_python generated toolchain.
+ """
+
+ # Only update the location when using a hermetic toolchain.
+ if not python_interpreter_path:
+ return False
+
+ # This is a rules_python provided toolchain.
+ return repo_utils.execute_unchecked(
+ rctx,
+ op = "IsStandaloneInterpreter",
+ arguments = [
+ "ls",
+ "{}/{}".format(
+ python_interpreter_path.dirname,
+ STANDALONE_INTERPRETER_FILENAME,
+ ),
+ ],
+ logger = logger,
+ ).return_code == 0
diff --git a/python/private/py_repositories.bzl b/python/private/py_repositories.bzl
new file mode 100644
index 0000000..ace3750
--- /dev/null
+++ b/python/private/py_repositories.bzl
@@ -0,0 +1,49 @@
+# Copyright 2024 The Bazel Authors. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""This file contains macros to be called during WORKSPACE evaluation."""
+
+load("@bazel_tools//tools/build_defs/repo:http.bzl", _http_archive = "http_archive")
+load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe")
+load("//python/private/pypi:deps.bzl", "pypi_deps")
+load(":internal_config_repo.bzl", "internal_config_repo")
+
+def http_archive(**kwargs):
+ maybe(_http_archive, **kwargs)
+
+def py_repositories():
+ """Runtime dependencies that users must install.
+
+ This function should be loaded and called in the user's WORKSPACE.
+ With bzlmod enabled, this function is not needed since MODULE.bazel handles transitive deps.
+ """
+ maybe(
+ internal_config_repo,
+ name = "rules_python_internal",
+ )
+ http_archive(
+ name = "bazel_skylib",
+ sha256 = "74d544d96f4a5bb630d465ca8bbcfe231e3594e5aae57e1edbf17a6eb3ca2506",
+ urls = [
+ "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.3.0/bazel-skylib-1.3.0.tar.gz",
+ "https://github.com/bazelbuild/bazel-skylib/releases/download/1.3.0/bazel-skylib-1.3.0.tar.gz",
+ ],
+ )
+ http_archive(
+ name = "rules_cc",
+ urls = ["https://github.com/bazelbuild/rules_cc/releases/download/0.0.9/rules_cc-0.0.9.tar.gz"],
+ sha256 = "2037875b9a4456dce4a79d112a8ae885bbc4aad968e6587dca6e64f3a0900cdf",
+ strip_prefix = "rules_cc-0.0.9",
+ )
+ pypi_deps()
diff --git a/python/private/pypi/BUILD.bazel b/python/private/pypi/BUILD.bazel
index 1db50af..2b25bfb 100644
--- a/python/private/pypi/BUILD.bazel
+++ b/python/private/pypi/BUILD.bazel
@@ -306,9 +306,9 @@
":patch_whl_bzl",
":pypi_repo_utils_bzl",
":whl_target_platforms_bzl",
- "//python:repositories_bzl",
"//python/private:auth_bzl",
"//python/private:envsubst_bzl",
+ "//python/private:is_standalone_interpreter_bzl",
"//python/private:repo_utils_bzl",
],
)
diff --git a/python/private/pypi/whl_library.bzl b/python/private/pypi/whl_library.bzl
index 5b14151..309316b 100644
--- a/python/private/pypi/whl_library.bzl
+++ b/python/private/pypi/whl_library.bzl
@@ -16,7 +16,7 @@
load("//python/private:auth.bzl", "AUTH_ATTRS", "get_auth")
load("//python/private:envsubst.bzl", "envsubst")
-load("//python/private:python_repositories.bzl", "is_standalone_interpreter")
+load("//python/private:is_standalone_interpreter.bzl", "is_standalone_interpreter")
load("//python/private:repo_utils.bzl", "REPO_DEBUG_ENV_VAR", "repo_utils")
load(":attrs.bzl", "ATTRS", "use_isolated")
load(":deps.bzl", "all_repo_names")
diff --git a/python/private/python.bzl b/python/private/python.bzl
index 9a9a240..98b089f 100644
--- a/python/private/python.bzl
+++ b/python/private/python.bzl
@@ -15,9 +15,9 @@
"Python toolchain module extensions for use with bzlmod"
load("@bazel_features//:features.bzl", "bazel_features")
-load("//python:repositories.bzl", "python_register_toolchains")
load("//python:versions.bzl", "MINOR_MAPPING", "TOOL_VERSIONS")
load(":full_version.bzl", "full_version")
+load(":python_register_toolchains.bzl", "python_register_toolchains")
load(":pythons_hub.bzl", "hub_repo")
load(":repo_utils.bzl", "repo_utils")
load(":text_util.bzl", "render")
diff --git a/python/private/python_register_multi_toolchains.bzl b/python/private/python_register_multi_toolchains.bzl
new file mode 100644
index 0000000..68f5249
--- /dev/null
+++ b/python/private/python_register_multi_toolchains.bzl
@@ -0,0 +1,75 @@
+# Copyright 2024 The Bazel Authors. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""This file contains repository rules and macros to support toolchain registration.
+"""
+
+load("//python:versions.bzl", "MINOR_MAPPING")
+load(":python_register_toolchains.bzl", "python_register_toolchains")
+load(":toolchains_repo.bzl", "multi_toolchain_aliases")
+
+def python_register_multi_toolchains(
+ name,
+ python_versions,
+ default_version = None,
+ minor_mapping = None,
+ **kwargs):
+ """Convenience macro for registering multiple Python toolchains.
+
+ Args:
+ name: {type}`str` base name for each name in {obj}`python_register_toolchains` call.
+ python_versions: {type}`list[str]` the Python versions.
+ default_version: {type}`str` the default Python version. If not set,
+ the first version in python_versions is used.
+ minor_mapping: {type}`dict[str, str]` mapping between `X.Y` to `X.Y.Z`
+ format. Defaults to the value in `//python:versions.bzl`.
+ **kwargs: passed to each {obj}`python_register_toolchains` call.
+ """
+ if len(python_versions) == 0:
+ fail("python_versions must not be empty")
+
+ minor_mapping = minor_mapping or MINOR_MAPPING
+
+ if not default_version:
+ default_version = python_versions.pop(0)
+ for python_version in python_versions:
+ if python_version == default_version:
+ # We register the default version lastly so that it's not picked first when --platforms
+ # is set with a constraint during toolchain resolution. This is due to the fact that
+ # Bazel will match the unconstrained toolchain if we register it before the constrained
+ # ones.
+ continue
+ python_register_toolchains(
+ name = name + "_" + python_version.replace(".", "_"),
+ python_version = python_version,
+ set_python_version_constraint = True,
+ minor_mapping = minor_mapping,
+ **kwargs
+ )
+ python_register_toolchains(
+ name = name + "_" + default_version.replace(".", "_"),
+ python_version = default_version,
+ set_python_version_constraint = False,
+ minor_mapping = minor_mapping,
+ **kwargs
+ )
+
+ multi_toolchain_aliases(
+ name = name,
+ python_versions = {
+ python_version: name + "_" + python_version.replace(".", "_")
+ for python_version in (python_versions + [default_version])
+ },
+ minor_mapping = minor_mapping,
+ )
diff --git a/python/private/python_register_toolchains.bzl b/python/private/python_register_toolchains.bzl
new file mode 100644
index 0000000..7638d76
--- /dev/null
+++ b/python/private/python_register_toolchains.bzl
@@ -0,0 +1,176 @@
+# Copyright 2024 The Bazel Authors. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""This file contains repository rules and macros to support toolchain registration.
+"""
+
+load(
+ "//python:versions.bzl",
+ "DEFAULT_RELEASE_BASE_URL",
+ "MINOR_MAPPING",
+ "PLATFORMS",
+ "TOOL_VERSIONS",
+ "get_release_info",
+)
+load(":bzlmod_enabled.bzl", "BZLMOD_ENABLED")
+load(":coverage_deps.bzl", "coverage_dep")
+load(":full_version.bzl", "full_version")
+load(":python_repository.bzl", "python_repository")
+load(
+ ":toolchains_repo.bzl",
+ "host_toolchain",
+ "toolchain_aliases",
+ "toolchains_repo",
+)
+
+# Wrapper macro around everything above, this is the primary API.
+def python_register_toolchains(
+ name,
+ python_version,
+ register_toolchains = True,
+ register_coverage_tool = False,
+ set_python_version_constraint = False,
+ tool_versions = None,
+ minor_mapping = None,
+ **kwargs):
+ """Convenience macro for users which does typical setup.
+
+ - Create a repository for each built-in platform like "python_3_8_linux_amd64" -
+ this repository is lazily fetched when Python is needed for that platform.
+ - Create a repository exposing toolchains for each platform like
+ "python_platforms".
+ - Register a toolchain pointing at each platform.
+
+ Users can avoid this macro and do these steps themselves, if they want more
+ control.
+
+ Args:
+ name: {type}`str` base name for all created repos, e.g. "python_3_8".
+ python_version: {type}`str` the Python version.
+ register_toolchains: {type}`bool` Whether or not to register the downloaded toolchains.
+ register_coverage_tool: {type}`bool` Whether or not to register the
+ downloaded coverage tool to the toolchains.
+ set_python_version_constraint: {type}`bool` When set to `True`,
+ `target_compatible_with` for the toolchains will include a version
+ constraint.
+ tool_versions: {type}`dict` contains a mapping of version with SHASUM
+ and platform info. If not supplied, the defaults in
+ python/versions.bzl will be used.
+ minor_mapping: {type}`dict[str, str]` contains a mapping from `X.Y` to `X.Y.Z`
+ version.
+ **kwargs: passed to each {obj}`python_repository` call.
+ """
+
+ if BZLMOD_ENABLED:
+ # you cannot used native.register_toolchains when using bzlmod.
+ register_toolchains = False
+
+ base_url = kwargs.pop("base_url", DEFAULT_RELEASE_BASE_URL)
+ tool_versions = tool_versions or TOOL_VERSIONS
+ minor_mapping = minor_mapping or MINOR_MAPPING
+
+ python_version = full_version(version = python_version, minor_mapping = minor_mapping)
+
+ toolchain_repo_name = "{name}_toolchains".format(name = name)
+
+ # When using unreleased Bazel versions, the version is an empty string
+ if native.bazel_version:
+ bazel_major = int(native.bazel_version.split(".")[0])
+ if bazel_major < 6:
+ if register_coverage_tool:
+ # buildifier: disable=print
+ print((
+ "WARNING: ignoring register_coverage_tool=True when " +
+ "registering @{name}: Bazel 6+ required, got {version}"
+ ).format(
+ name = name,
+ version = native.bazel_version,
+ ))
+ register_coverage_tool = False
+
+ loaded_platforms = []
+ for platform in PLATFORMS.keys():
+ sha256 = tool_versions[python_version]["sha256"].get(platform, None)
+ if not sha256:
+ continue
+
+ loaded_platforms.append(platform)
+ (release_filename, urls, strip_prefix, patches, patch_strip) = get_release_info(platform, python_version, base_url, tool_versions)
+
+ # allow passing in a tool version
+ coverage_tool = None
+ coverage_tool = tool_versions[python_version].get("coverage_tool", {}).get(platform, None)
+ if register_coverage_tool and coverage_tool == None:
+ coverage_tool = coverage_dep(
+ name = "{name}_{platform}_coverage".format(
+ name = name,
+ platform = platform,
+ ),
+ python_version = python_version,
+ platform = platform,
+ visibility = ["@{name}_{platform}//:__subpackages__".format(
+ name = name,
+ platform = platform,
+ )],
+ )
+
+ python_repository(
+ name = "{name}_{platform}".format(
+ name = name,
+ platform = platform,
+ ),
+ sha256 = sha256,
+ patches = patches,
+ patch_strip = patch_strip,
+ platform = platform,
+ python_version = python_version,
+ release_filename = release_filename,
+ urls = urls,
+ strip_prefix = strip_prefix,
+ coverage_tool = coverage_tool,
+ **kwargs
+ )
+ if register_toolchains:
+ native.register_toolchains("@{toolchain_repo_name}//:{platform}_toolchain".format(
+ toolchain_repo_name = toolchain_repo_name,
+ platform = platform,
+ ))
+ native.register_toolchains("@{toolchain_repo_name}//:{platform}_py_cc_toolchain".format(
+ toolchain_repo_name = toolchain_repo_name,
+ platform = platform,
+ ))
+ native.register_toolchains("@{toolchain_repo_name}//:{platform}_py_exec_tools_toolchain".format(
+ toolchain_repo_name = toolchain_repo_name,
+ platform = platform,
+ ))
+
+ host_toolchain(name = name + "_host")
+
+ toolchain_aliases(
+ name = name,
+ python_version = python_version,
+ user_repository_name = name,
+ platforms = loaded_platforms,
+ )
+
+ # in bzlmod we write out our own toolchain repos
+ if BZLMOD_ENABLED:
+ return
+
+ toolchains_repo(
+ name = toolchain_repo_name,
+ python_version = python_version,
+ set_python_version_constraint = set_python_version_constraint,
+ user_repository_name = name,
+ )
diff --git a/python/private/python_repositories.bzl b/python/private/python_repository.bzl
similarity index 61%
rename from python/private/python_repositories.bzl
rename to python/private/python_repository.bzl
index 0286160..28a2c95 100644
--- a/python/private/python_repositories.bzl
+++ b/python/private/python_repository.bzl
@@ -1,4 +1,4 @@
-# Copyright 2022 The Bazel Authors. All rights reserved.
+# Copyright 2024 The Bazel Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -12,69 +12,13 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-"""This file contains macros to be called during WORKSPACE evaluation.
-
-For historic reasons, pip_repositories() is defined in //python:pip.bzl.
+"""This file contains repository rules and macros to support toolchain registration.
"""
-load("@bazel_tools//tools/build_defs/repo:http.bzl", _http_archive = "http_archive")
-load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe")
-load(
- "//python:versions.bzl",
- "DEFAULT_RELEASE_BASE_URL",
- "MINOR_MAPPING",
- "PLATFORMS",
- "TOOL_VERSIONS",
- "get_release_info",
-)
-load("//python/private/pypi:deps.bzl", "pypi_deps")
+load("//python:versions.bzl", "PLATFORMS")
load(":auth.bzl", "get_auth")
-load(":bzlmod_enabled.bzl", "BZLMOD_ENABLED")
-load(":coverage_deps.bzl", "coverage_dep")
-load(":full_version.bzl", "full_version")
-load(":internal_config_repo.bzl", "internal_config_repo")
load(":repo_utils.bzl", "REPO_DEBUG_ENV_VAR", "repo_utils")
load(":text_util.bzl", "render")
-load(
- ":toolchains_repo.bzl",
- "host_toolchain",
- "multi_toolchain_aliases",
- "toolchain_aliases",
- "toolchains_repo",
-)
-
-def http_archive(**kwargs):
- maybe(_http_archive, **kwargs)
-
-def py_repositories():
- """Runtime dependencies that users must install.
-
- This function should be loaded and called in the user's WORKSPACE.
- With bzlmod enabled, this function is not needed since MODULE.bazel handles transitive deps.
- """
- maybe(
- internal_config_repo,
- name = "rules_python_internal",
- )
- http_archive(
- name = "bazel_skylib",
- sha256 = "74d544d96f4a5bb630d465ca8bbcfe231e3594e5aae57e1edbf17a6eb3ca2506",
- urls = [
- "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.3.0/bazel-skylib-1.3.0.tar.gz",
- "https://github.com/bazelbuild/bazel-skylib/releases/download/1.3.0/bazel-skylib-1.3.0.tar.gz",
- ],
- )
- http_archive(
- name = "rules_cc",
- urls = ["https://github.com/bazelbuild/rules_cc/releases/download/0.0.9/rules_cc-0.0.9.tar.gz"],
- sha256 = "2037875b9a4456dce4a79d112a8ae885bbc4aad968e6587dca6e64f3a0900cdf",
- strip_prefix = "rules_cc-0.0.9",
- )
- pypi_deps()
-
-########
-# Remaining content of the file is only used to support toolchains.
-########
STANDALONE_INTERPRETER_FILENAME = "STANDALONE_INTERPRETER"
@@ -458,199 +402,3 @@
},
environ = [REPO_DEBUG_ENV_VAR],
)
-
-# Wrapper macro around everything above, this is the primary API.
-def python_register_toolchains(
- name,
- python_version,
- register_toolchains = True,
- register_coverage_tool = False,
- set_python_version_constraint = False,
- tool_versions = None,
- minor_mapping = None,
- **kwargs):
- """Convenience macro for users which does typical setup.
-
- - Create a repository for each built-in platform like "python_3_8_linux_amd64" -
- this repository is lazily fetched when Python is needed for that platform.
- - Create a repository exposing toolchains for each platform like
- "python_platforms".
- - Register a toolchain pointing at each platform.
-
- Users can avoid this macro and do these steps themselves, if they want more
- control.
-
- Args:
- name: {type}`str` base name for all created repos, e.g. "python_3_8".
- python_version: {type}`str` the Python version.
- register_toolchains: {type}`bool` Whether or not to register the downloaded toolchains.
- register_coverage_tool: {type}`bool` Whether or not to register the
- downloaded coverage tool to the toolchains.
- set_python_version_constraint: {type}`bool` When set to `True`,
- `target_compatible_with` for the toolchains will include a version
- constraint.
- tool_versions: {type}`dict` contains a mapping of version with SHASUM
- and platform info. If not supplied, the defaults in
- python/versions.bzl will be used.
- minor_mapping: {type}`dict[str, str]` contains a mapping from `X.Y` to `X.Y.Z`
- version.
- **kwargs: passed to each {obj}`python_repository` call.
- """
-
- if BZLMOD_ENABLED:
- # you cannot used native.register_toolchains when using bzlmod.
- register_toolchains = False
-
- base_url = kwargs.pop("base_url", DEFAULT_RELEASE_BASE_URL)
- tool_versions = tool_versions or TOOL_VERSIONS
- minor_mapping = minor_mapping or MINOR_MAPPING
-
- python_version = full_version(version = python_version, minor_mapping = minor_mapping)
-
- toolchain_repo_name = "{name}_toolchains".format(name = name)
-
- # When using unreleased Bazel versions, the version is an empty string
- if native.bazel_version:
- bazel_major = int(native.bazel_version.split(".")[0])
- if bazel_major < 6:
- if register_coverage_tool:
- # buildifier: disable=print
- print((
- "WARNING: ignoring register_coverage_tool=True when " +
- "registering @{name}: Bazel 6+ required, got {version}"
- ).format(
- name = name,
- version = native.bazel_version,
- ))
- register_coverage_tool = False
-
- loaded_platforms = []
- for platform in PLATFORMS.keys():
- sha256 = tool_versions[python_version]["sha256"].get(platform, None)
- if not sha256:
- continue
-
- loaded_platforms.append(platform)
- (release_filename, urls, strip_prefix, patches, patch_strip) = get_release_info(platform, python_version, base_url, tool_versions)
-
- # allow passing in a tool version
- coverage_tool = None
- coverage_tool = tool_versions[python_version].get("coverage_tool", {}).get(platform, None)
- if register_coverage_tool and coverage_tool == None:
- coverage_tool = coverage_dep(
- name = "{name}_{platform}_coverage".format(
- name = name,
- platform = platform,
- ),
- python_version = python_version,
- platform = platform,
- visibility = ["@{name}_{platform}//:__subpackages__".format(
- name = name,
- platform = platform,
- )],
- )
-
- python_repository(
- name = "{name}_{platform}".format(
- name = name,
- platform = platform,
- ),
- sha256 = sha256,
- patches = patches,
- patch_strip = patch_strip,
- platform = platform,
- python_version = python_version,
- release_filename = release_filename,
- urls = urls,
- strip_prefix = strip_prefix,
- coverage_tool = coverage_tool,
- **kwargs
- )
- if register_toolchains:
- native.register_toolchains("@{toolchain_repo_name}//:{platform}_toolchain".format(
- toolchain_repo_name = toolchain_repo_name,
- platform = platform,
- ))
- native.register_toolchains("@{toolchain_repo_name}//:{platform}_py_cc_toolchain".format(
- toolchain_repo_name = toolchain_repo_name,
- platform = platform,
- ))
- native.register_toolchains("@{toolchain_repo_name}//:{platform}_py_exec_tools_toolchain".format(
- toolchain_repo_name = toolchain_repo_name,
- platform = platform,
- ))
-
- host_toolchain(name = name + "_host")
-
- toolchain_aliases(
- name = name,
- python_version = python_version,
- user_repository_name = name,
- platforms = loaded_platforms,
- )
-
- # in bzlmod we write out our own toolchain repos
- if BZLMOD_ENABLED:
- return
-
- toolchains_repo(
- name = toolchain_repo_name,
- python_version = python_version,
- set_python_version_constraint = set_python_version_constraint,
- user_repository_name = name,
- )
-
-def python_register_multi_toolchains(
- name,
- python_versions,
- default_version = None,
- minor_mapping = None,
- **kwargs):
- """Convenience macro for registering multiple Python toolchains.
-
- Args:
- name: {type}`str` base name for each name in {obj}`python_register_toolchains` call.
- python_versions: {type}`list[str]` the Python versions.
- default_version: {type}`str` the default Python version. If not set,
- the first version in python_versions is used.
- minor_mapping: {type}`dict[str, str]` mapping between `X.Y` to `X.Y.Z`
- format. Defaults to the value in `//python:versions.bzl`.
- **kwargs: passed to each {obj}`python_register_toolchains` call.
- """
- if len(python_versions) == 0:
- fail("python_versions must not be empty")
-
- minor_mapping = minor_mapping or MINOR_MAPPING
-
- if not default_version:
- default_version = python_versions.pop(0)
- for python_version in python_versions:
- if python_version == default_version:
- # We register the default version lastly so that it's not picked first when --platforms
- # is set with a constraint during toolchain resolution. This is due to the fact that
- # Bazel will match the unconstrained toolchain if we register it before the constrained
- # ones.
- continue
- python_register_toolchains(
- name = name + "_" + python_version.replace(".", "_"),
- python_version = python_version,
- set_python_version_constraint = True,
- minor_mapping = minor_mapping,
- **kwargs
- )
- python_register_toolchains(
- name = name + "_" + default_version.replace(".", "_"),
- python_version = default_version,
- set_python_version_constraint = False,
- minor_mapping = minor_mapping,
- **kwargs
- )
-
- multi_toolchain_aliases(
- name = name,
- python_versions = {
- python_version: name + "_" + python_version.replace(".", "_")
- for python_version in (python_versions + [default_version])
- },
- minor_mapping = minor_mapping,
- )
diff --git a/python/repositories.bzl b/python/repositories.bzl
index 88c00e2..768b587 100644
--- a/python/repositories.bzl
+++ b/python/repositories.bzl
@@ -16,14 +16,14 @@
"""
load(
- "//python/private:python_repositories.bzl",
+ "//python/private:is_standalone_interpreter.bzl",
_STANDALONE_INTERPRETER_FILENAME = "STANDALONE_INTERPRETER_FILENAME",
_is_standalone_interpreter = "is_standalone_interpreter",
- _py_repositories = "py_repositories",
- _python_register_multi_toolchains = "python_register_multi_toolchains",
- _python_register_toolchains = "python_register_toolchains",
- _python_repository = "python_repository",
)
+load("//python/private:py_repositories.bzl", _py_repositories = "py_repositories")
+load("//python/private:python_register_multi_toolchains.bzl", _python_register_multi_toolchains = "python_register_multi_toolchains")
+load("//python/private:python_register_toolchains.bzl", _python_register_toolchains = "python_register_toolchains")
+load("//python/private:python_repository.bzl", _python_repository = "python_repository")
py_repositories = _py_repositories
python_register_multi_toolchains = _python_register_multi_toolchains