diff --git a/.bazelci/presubmit.yml b/.bazelci/presubmit.yml index 9fd7cae311..b778ac49a4 100644 --- a/.bazelci/presubmit.yml +++ b/.bazelci/presubmit.yml @@ -182,6 +182,7 @@ tasks: platform: rbe_ubuntu1604 test_flags: - "--test_tag_filters=-integration-test,-acceptance-test" + - "--extra_toolchains=@buildkite_config//config:cc-toolchain" integration_test_build_file_generation_ubuntu_minimum_supported_workspace: <<: *minimum_supported_version diff --git a/CHANGELOG.md b/CHANGELOG.md index 9dc5ec4bca..1fe53e70d1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,9 @@ A brief description of the categories of changes: * (toolchains) The exec tools toolchain now finds its interpreter by reusing the regular interpreter toolchain. This avoids having to duplicate specifying where the runtime for the exec tools toolchain is. +* (toolchains) ({obj}`//python:autodetecting_toolchain`) is deprecated. It is + replaced by {obj}`//python/runtime_env_toolchains:all`. The old target will be + removed in a future release. ### Fixed * (bzlmod): Targets in `all_requirements` now use the same form as targets returned by the `requirement` macro. @@ -47,6 +50,10 @@ A brief description of the categories of changes: * (rules) The first element of the default outputs is now the executable again. * (pip) Fixed crash when pypi packages lacked a sha (e.g. yanked packages) +### Added +* (toolchains) {obj}`//python/runtime_env_toolchains:all`, which is a drop-in + replacement for the "autodetecting" toolchain. + ### Removed * (pip): Removes the `entrypoint` macro that was replaced by `py_console_script_binary` in 0.26.0. diff --git a/docs/sphinx/api/python/index.md b/docs/sphinx/api/python/index.md index 494e7b4a02..6c794475ac 100644 --- a/docs/sphinx/api/python/index.md +++ b/docs/sphinx/api/python/index.md @@ -26,18 +26,11 @@ provides: ::::{target} autodetecting_toolchain -A simple toolchain that simply uses `python3` from the runtime environment. +Legacy toolchain; despite its name, it doesn't autodetect anything. -Note that this toolchain provides no build-time information, which makes it of -limited utility. +:::{deprecated} 0.34.0 -This is only provided to aid migration off the builtin Bazel toolchain -(`@bazel_tools//python:autodetecting_toolchain`), and is largely only applicable -to WORKSPACE builds. - -:::{deprecated} unspecified - -Switch to using a hermetic toolchain or manual toolchain configuration instead. +Use {obj}`@rules_python//python/runtime_env_toolchain:all` instead. ::: - :::: + diff --git a/docs/sphinx/api/python/runtime_env_toolchains/index.md b/docs/sphinx/api/python/runtime_env_toolchains/index.md new file mode 100644 index 0000000000..ef31f086d7 --- /dev/null +++ b/docs/sphinx/api/python/runtime_env_toolchains/index.md @@ -0,0 +1,38 @@ +:::{default-domain} bzl +::: +:::{bzl:currentfile} //python/runtime_env_toolchain:BUILD.bazel +::: + +# //python/runtime_env_toolchain + +::::{target} all + +A set of toolchains that invoke `python3` from the runtime environment. + +Note that this toolchain provides no build-time information, which makes it of +limited utility. This is because the invocation of `python3` is done when a +program is run, not at build time. + +This is only provided to aid migration off the builtin Bazel toolchain +(`@bazel_tools//python:autodetecting_toolchain`), and is largely only applicable +to WORKSPACE builds. + +To use this target, register it as a toolchain in WORKSPACE or MODULE.bazel: + +::: +register_toolchains("@rules_python//python/runtime_env_toolchains:all") +::: + +The benefit of this target over the legacy targets is this defines additional +toolchain types that rules_python needs. This prevents toolchain resolution from +continuing to search elsewhere (e.g. potentially incurring a download of the +hermetic runtimes when they won't be used). + +:::{deprecated} 0.34.0 + +Switch to using a hermetic toolchain or manual toolchain configuration instead. +::: + +:::{versionadded} 0.34.0 +::: +:::: diff --git a/docs/sphinx/toolchains.md b/docs/sphinx/toolchains.md index 26557cabed..fac1bfc6b0 100644 --- a/docs/sphinx/toolchains.md +++ b/docs/sphinx/toolchains.md @@ -240,5 +240,5 @@ automatically registers a higher-priority toolchain; it won't be used unless there is a toolchain misconfiguration somewhere. To aid migration off the Bazel-builtin toolchain, rules_python provides -{obj}`@rules_python//python:autodetecting_toolchain`. This is an equivalent +{obj}`@rules_python//python/runtime_env_toolchains:all`. This is an equivalent toolchain, but is implemented using rules_python's objects. diff --git a/python/BUILD.bazel b/python/BUILD.bazel index 96b2282221..7a69ac8051 100644 --- a/python/BUILD.bazel +++ b/python/BUILD.bazel @@ -24,7 +24,6 @@ that @rules_python//python is only concerned with the core rules. """ load("@bazel_skylib//:bzl_library.bzl", "bzl_library") -load("//python/private:autodetecting_toolchain.bzl", "define_autodetecting_toolchain") load(":current_py_toolchain.bzl", "current_py_toolchain") package(default_visibility = ["//visibility:public"]) @@ -320,11 +319,16 @@ toolchain_type( # safe if you know for a fact that your build is completely compatible with the # version of the `python` command installed on the target platform. -define_autodetecting_toolchain(name = "autodetecting_toolchain") +alias( + name = "autodetecting_toolchain", + actual = "//python/runtime_env_toolchains:runtime_env_toolchain", + deprecation = "Use //python/runtime_env_toolchains:all instead", +) alias( name = "autodetecting_toolchain_nonstrict", - actual = ":autodetecting_toolchain", + actual = "//python/runtime_env_toolchains:runtime_env_toolchain", + deprecation = "Use //python/runtime_env_toolchains:all instead", ) # ========= Packaging rules ========= diff --git a/python/private/BUILD.bazel b/python/private/BUILD.bazel index ccc6acdcbf..9c759cba9a 100644 --- a/python/private/BUILD.bazel +++ b/python/private/BUILD.bazel @@ -13,6 +13,7 @@ # limitations under the License. load("@bazel_skylib//:bzl_library.bzl", "bzl_library") +load("@bazel_skylib//rules:common_settings.bzl", "bool_setting") load("//python:py_binary.bzl", "py_binary") load("//python:py_library.bzl", "py_library") load("//python:versions.bzl", "print_toolchains_checksums") @@ -58,9 +59,10 @@ bzl_library( ) bzl_library( - name = "autodetecting_toolchain_bzl", - srcs = ["autodetecting_toolchain.bzl"], + name = "runtime_env_toolchain_bzl", + srcs = ["runtime_env_toolchain.bzl"], deps = [ + ":py_exec_tools_toolchain_bzl", ":toolchain_types_bzl", "//python:py_runtime_bzl", "//python:py_runtime_pair_bzl", @@ -140,6 +142,7 @@ bzl_library( ":py_cc_toolchain_info_bzl", ":rules_cc_srcs_bzl", ":util_bzl", + "@bazel_skylib//rules:common_settings", ], ) @@ -164,7 +167,11 @@ bzl_library( bzl_library( name = "py_exec_tools_toolchain_bzl", srcs = ["py_exec_tools_toolchain.bzl"], - deps = ["//python/private/common:providers_bzl"], + deps = [ + ":toolchain_types_bzl", + "//python/private/common:providers_bzl", + "@bazel_skylib//rules:common_settings", + ], ) bzl_library( @@ -192,6 +199,7 @@ bzl_library( deps = [ "//python:py_runtime_bzl", "//python:py_runtime_info_bzl", + "@bazel_skylib//rules:common_settings", ], ) @@ -365,6 +373,15 @@ config_setting( }, ) +# This should only be set by analysis tests to expose additional metadata to +# aid testing, so a setting instead of a flag. +bool_setting( + name = "visible_for_testing", + build_setting_default = False, + # This is only because it is an implicit dependency by the toolchains. + visibility = ["//visibility:public"], +) + print_toolchains_checksums(name = "print_toolchains_checksums") # Used for py_console_script_gen rule diff --git a/python/private/autodetecting_toolchain.bzl b/python/private/autodetecting_toolchain.bzl deleted file mode 100644 index 174136e870..0000000000 --- a/python/private/autodetecting_toolchain.bzl +++ /dev/null @@ -1,71 +0,0 @@ -# Copyright 2019 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. - -"""Definitions related to the Python toolchain.""" - -load("//python:py_runtime.bzl", "py_runtime") -load("//python:py_runtime_pair.bzl", "py_runtime_pair") -load(":toolchain_types.bzl", "TARGET_TOOLCHAIN_TYPE") - -def define_autodetecting_toolchain(name): - """Defines the autodetecting Python toolchain. - - Args: - name: The name of the toolchain to introduce. Must have value - "autodetecting_toolchain". This param is present only to make the - BUILD file more readable. - """ - if name != "autodetecting_toolchain": - fail("Python autodetecting toolchain must be named " + - "'autodetecting_toolchain'") - - # buildifier: disable=native-py - py_runtime( - name = "_autodetecting_py3_runtime", - interpreter = "//python/private:autodetecting_toolchain_interpreter.sh", - python_version = "PY3", - stub_shebang = "#!/usr/bin/env python3", - visibility = ["//visibility:private"], - ) - - # This is a dummy runtime whose interpreter_path triggers the native rule - # logic to use the legacy behavior on Windows. - # TODO(#7844): Remove this target. - # buildifier: disable=native-py - py_runtime( - name = "_magic_sentinel_runtime", - interpreter_path = "/_magic_pyruntime_sentinel_do_not_use", - python_version = "PY3", - visibility = ["//visibility:private"], - ) - - py_runtime_pair( - name = "_autodetecting_py_runtime_pair", - py3_runtime = select({ - # If we're on windows, inject the sentinel to tell native rule logic - # that we attempted to use the autodetecting toolchain and need to - # switch back to legacy behavior. - # TODO(#7844): Remove this hack. - "@platforms//os:windows": ":_magic_sentinel_runtime", - "//conditions:default": ":_autodetecting_py3_runtime", - }), - visibility = ["//visibility:public"], - ) - - native.toolchain( - name = name, - toolchain = ":_autodetecting_py_runtime_pair", - toolchain_type = TARGET_TOOLCHAIN_TYPE, - visibility = ["//visibility:public"], - ) diff --git a/python/private/py_cc_toolchain_rule.bzl b/python/private/py_cc_toolchain_rule.bzl index 5d3debb702..1599415ac7 100644 --- a/python/private/py_cc_toolchain_rule.bzl +++ b/python/private/py_cc_toolchain_rule.bzl @@ -18,6 +18,7 @@ NOTE: This is a beta-quality feature. APIs subject to change until https://github.com/bazelbuild/rules_python/issues/824 is considered done. """ +load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo") load("@rules_cc//cc:defs.bzl", "CcInfo") load(":py_cc_toolchain_info.bzl", "PyCcToolchainInfo") @@ -37,8 +38,12 @@ def _py_cc_toolchain_impl(ctx): ), python_version = ctx.attr.python_version, ) + extra_kwargs = {} + if ctx.attr._visible_for_testing[BuildSettingInfo].value: + extra_kwargs["toolchain_label"] = ctx.label return [platform_common.ToolchainInfo( py_cc_toolchain = py_cc_toolchain, + **extra_kwargs )] py_cc_toolchain = rule( @@ -60,6 +65,9 @@ py_cc_toolchain = rule( doc = "The Major.minor Python version, e.g. 3.11", mandatory = True, ), + "_visible_for_testing": attr.label( + default = "//python/private:visible_for_testing", + ), }, doc = """\ A toolchain for a Python runtime's C/C++ information (e.g. headers) diff --git a/python/private/py_exec_tools_toolchain.bzl b/python/private/py_exec_tools_toolchain.bzl index 5c17b89625..b3d0fb2634 100644 --- a/python/private/py_exec_tools_toolchain.bzl +++ b/python/private/py_exec_tools_toolchain.bzl @@ -14,14 +14,22 @@ """Rule that defines a toolchain for build tools.""" +load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo") load("//python/private:toolchain_types.bzl", "TARGET_TOOLCHAIN_TYPE") load(":py_exec_tools_info.bzl", "PyExecToolsInfo") def _py_exec_tools_toolchain_impl(ctx): - return [platform_common.ToolchainInfo(exec_tools = PyExecToolsInfo( - exec_interpreter = ctx.attr.exec_interpreter, - precompiler = ctx.attr.precompiler, - ))] + extra_kwargs = {} + if ctx.attr._visible_for_testing[BuildSettingInfo].value: + extra_kwargs["toolchain_label"] = ctx.label + + return [platform_common.ToolchainInfo( + exec_tools = PyExecToolsInfo( + exec_interpreter = ctx.attr.exec_interpreter, + precompiler = ctx.attr.precompiler, + ), + **extra_kwargs + )] py_exec_tools_toolchain = rule( implementation = _py_exec_tools_toolchain_impl, @@ -36,6 +44,9 @@ py_exec_tools_toolchain = rule( cfg = "exec", doc = "See PyExecToolsInfo.precompiler", ), + "_visible_for_testing": attr.label( + default = "//python/private:visible_for_testing", + ), }, ) diff --git a/python/private/py_runtime_pair_rule.bzl b/python/private/py_runtime_pair_rule.bzl index 02f9a5ba89..eb91413563 100644 --- a/python/private/py_runtime_pair_rule.bzl +++ b/python/private/py_runtime_pair_rule.bzl @@ -14,6 +14,7 @@ """Implementation of py_runtime_pair.""" +load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo") load("//python:py_runtime_info.bzl", "PyRuntimeInfo") load("//python/private:reexports.bzl", "BuiltinPyRuntimeInfo") load("//python/private:util.bzl", "IS_BAZEL_7_OR_HIGHER") @@ -40,9 +41,14 @@ def _py_runtime_pair_impl(ctx): # fail("Using Python 2 is not supported and disabled; see " + # "https://github.com/bazelbuild/bazel/issues/15684") + extra_kwargs = {} + if ctx.attr._visible_for_testing[BuildSettingInfo].value: + extra_kwargs["toolchain_label"] = ctx.label + return [platform_common.ToolchainInfo( py2_runtime = py2_runtime, py3_runtime = py3_runtime, + **extra_kwargs )] def _get_py_runtime_info(target): @@ -85,6 +91,9 @@ The runtime to use for Python 3 targets. Must have `python_version` set to `PY3`. """, ), + "_visible_for_testing": attr.label( + default = "//python/private:visible_for_testing", + ), }, fragments = ["py"], doc = """\ diff --git a/python/private/runtime_env_toolchain.bzl b/python/private/runtime_env_toolchain.bzl new file mode 100644 index 0000000000..1601926178 --- /dev/null +++ b/python/private/runtime_env_toolchain.bzl @@ -0,0 +1,112 @@ +# Copyright 2019 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. +"""Definitions related to the Python toolchain.""" + +load("@rules_cc//cc:defs.bzl", "cc_library") +load("//python:py_runtime.bzl", "py_runtime") +load("//python:py_runtime_pair.bzl", "py_runtime_pair") +load("//python/cc:py_cc_toolchain.bzl", "py_cc_toolchain") +load(":py_exec_tools_toolchain.bzl", "py_exec_tools_toolchain") +load(":toolchain_types.bzl", "EXEC_TOOLS_TOOLCHAIN_TYPE", "PY_CC_TOOLCHAIN_TYPE", "TARGET_TOOLCHAIN_TYPE") + +_IS_EXEC_TOOLCHAIN_ENABLED = Label("//python/config_settings:is_exec_tools_toolchain_enabled") + +def define_runtime_env_toolchain(name): + """Defines the runtime_env Python toolchain. + + This is a minimal suite of toolchains that provided limited functionality. + They're mostly only useful to aid migration off the builtin + `@bazel_tools//tools/python:autodetecting_toolchain` toolchain. + + NOTE: This was previously called the "autodetecting" toolchain, but was + renamed to better reflect its behavior, since it doesn't autodetect + anything. + + Args: + name: The name of the toolchain to introduce. + """ + base_name = name.replace("_toolchain", "") + + py_runtime( + name = "_runtime_env_py3_runtime", + interpreter = "//python/private:runtime_env_toolchain_interpreter.sh", + python_version = "PY3", + stub_shebang = "#!/usr/bin/env python3", + visibility = ["//visibility:private"], + tags = ["manual"], + ) + + # This is a dummy runtime whose interpreter_path triggers the native rule + # logic to use the legacy behavior on Windows. + # TODO(#7844): Remove this target. + py_runtime( + name = "_magic_sentinel_runtime", + interpreter_path = "/_magic_pyruntime_sentinel_do_not_use", + python_version = "PY3", + visibility = ["//visibility:private"], + tags = ["manual"], + ) + + py_runtime_pair( + name = "_runtime_env_py_runtime_pair", + py3_runtime = select({ + # If we're on windows, inject the sentinel to tell native rule logic + # that we attempted to use the runtime_env toolchain and need to + # switch back to legacy behavior. + # TODO(#7844): Remove this hack. + "@platforms//os:windows": ":_magic_sentinel_runtime", + "//conditions:default": ":_runtime_env_py3_runtime", + }), + visibility = ["//visibility:public"], + tags = ["manual"], + ) + + native.toolchain( + name = name, + toolchain = ":_runtime_env_py_runtime_pair", + toolchain_type = TARGET_TOOLCHAIN_TYPE, + visibility = ["//visibility:public"], + ) + + py_exec_tools_toolchain( + name = "_runtime_env_py_exec_tools_toolchain_impl", + precompiler = Label("//tools/precompiler:precompiler"), + visibility = ["//visibility:private"], + tags = ["manual"], + ) + native.toolchain( + name = base_name + "_py_exec_tools_toolchain", + toolchain = "_runtime_env_py_exec_tools_toolchain_impl", + toolchain_type = EXEC_TOOLS_TOOLCHAIN_TYPE, + target_settings = [_IS_EXEC_TOOLCHAIN_ENABLED], + visibility = ["//visibility:public"], + ) + cc_library( + name = "_empty_cc_lib", + visibility = ["//visibility:private"], + tags = ["manual"], + ) + py_cc_toolchain( + name = "_runtime_env_py_cc_toolchain_impl", + headers = ":_empty_cc_lib", + libs = ":_empty_cc_lib", + python_version = "0.0", + tags = ["manual"], + ) + native.toolchain( + name = base_name + "_py_cc_toolchain", + toolchain = ":_runtime_env_py_cc_toolchain_impl", + toolchain_type = PY_CC_TOOLCHAIN_TYPE, + visibility = ["//visibility:public"], + ) diff --git a/python/private/autodetecting_toolchain_interpreter.sh b/python/private/runtime_env_toolchain_interpreter.sh similarity index 94% rename from python/private/autodetecting_toolchain_interpreter.sh rename to python/private/runtime_env_toolchain_interpreter.sh index 5c8a10d601..2cb7cc7151 100644 --- a/python/private/autodetecting_toolchain_interpreter.sh +++ b/python/private/runtime_env_toolchain_interpreter.sh @@ -8,8 +8,8 @@ set -u # We do lose the ability to set -o pipefail. FAILURE_HEADER="\ -Error occurred while attempting to use the default Python toolchain \ -(@rules_python//python:autodetecting_toolchain)." +Error occurred while attempting to use the deprecated Python toolchain \ +(@rules_python//python/runtime_env_toolchain:all)." die() { echo "$FAILURE_HEADER" 1>&2 diff --git a/python/runtime_env_toolchains/BUILD.bazel b/python/runtime_env_toolchains/BUILD.bazel new file mode 100644 index 0000000000..21355ac939 --- /dev/null +++ b/python/runtime_env_toolchains/BUILD.bazel @@ -0,0 +1,19 @@ +# 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. + +load("//python/private:runtime_env_toolchain.bzl", "define_runtime_env_toolchain") + +package(default_visibility = ["//:__subpackages__"]) + +define_runtime_env_toolchain(name = "runtime_env_toolchain") diff --git a/tests/base_rules/precompile/precompile_tests.bzl b/tests/base_rules/precompile/precompile_tests.bzl index 58bdafe39c..5599f6101f 100644 --- a/tests/base_rules/precompile/precompile_tests.bzl +++ b/tests/base_rules/precompile/precompile_tests.bzl @@ -122,6 +122,7 @@ def _test_pyc_only(name): "//command_line_option:extra_toolchains": _TEST_TOOLCHAINS, ##PRECOMPILE_SOURCE_RETENTION: "omit_source", EXEC_TOOLS_TOOLCHAIN: "enabled", + PRECOMPILE: "enabled", }, target = name + "_subject", ) diff --git a/tests/runtime_env_toolchain/BUILD.bazel b/tests/runtime_env_toolchain/BUILD.bazel new file mode 100644 index 0000000000..ebcdbaf017 --- /dev/null +++ b/tests/runtime_env_toolchain/BUILD.bazel @@ -0,0 +1,17 @@ +# 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. + +load(":runtime_env_toolchain_tests.bzl", "runtime_env_toolchain_test_suite") + +runtime_env_toolchain_test_suite(name = "runtime_env_toolchain_tests") diff --git a/tests/runtime_env_toolchain/runtime_env_toolchain_tests.bzl b/tests/runtime_env_toolchain/runtime_env_toolchain_tests.bzl new file mode 100644 index 0000000000..9885a1ef9b --- /dev/null +++ b/tests/runtime_env_toolchain/runtime_env_toolchain_tests.bzl @@ -0,0 +1,101 @@ +# 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. + +"""Starlark tests for py_runtime rule.""" + +load("@rules_testing//lib:analysis_test.bzl", "analysis_test") +load("@rules_testing//lib:test_suite.bzl", "test_suite") +load("@rules_testing//lib:util.bzl", rt_util = "util") +load( + "//python/private:toolchain_types.bzl", + "EXEC_TOOLS_TOOLCHAIN_TYPE", + "PY_CC_TOOLCHAIN_TYPE", + "TARGET_TOOLCHAIN_TYPE", +) # buildifier: disable=bzl-visibility +load("//python/private:util.bzl", "IS_BAZEL_7_OR_HIGHER") # buildifier: disable=bzl-visibility +load("//tests/support:support.bzl", "CC_TOOLCHAIN", "EXEC_TOOLS_TOOLCHAIN", "VISIBLE_FOR_TESTING") + +_LookupInfo = provider() # buildifier: disable=provider-params + +def _use_toolchains_impl(ctx): + return [ + _LookupInfo( + target = ctx.toolchains[TARGET_TOOLCHAIN_TYPE], + exec = ctx.toolchains[EXEC_TOOLS_TOOLCHAIN_TYPE], + cc = ctx.toolchains[PY_CC_TOOLCHAIN_TYPE], + ), + ] + +_use_toolchains = rule( + implementation = _use_toolchains_impl, + toolchains = [ + TARGET_TOOLCHAIN_TYPE, + EXEC_TOOLS_TOOLCHAIN_TYPE, + PY_CC_TOOLCHAIN_TYPE, + ], +) + +_tests = [] + +def _test_runtime_env_toolchain_matches(name): + rt_util.helper_target( + _use_toolchains, + name = name + "_subject", + ) + extra_toolchains = [ + str(Label("//python/runtime_env_toolchains:all")), + ] + + # We have to add a cc toolchain because py_cc toolchain depends on it. + # However, that package also defines a different fake py_cc toolchain we + # don't want to use, so we need to ensure the runtime_env toolchain has + # higher precendence. + # However, Bazel 6 and Bazel 7 process --extra_toolchains in different + # orders: + # * Bazel 6 goes left to right + # * Bazel 7 goes right to left + # We could just put our preferred toolchain before *and* after + # the undesired toolchain... + # However, Bazel 7 has a bug where *duplicate* entries are ignored, + # and only the *first* entry is respected. + if IS_BAZEL_7_OR_HIGHER: + extra_toolchains.insert(0, CC_TOOLCHAIN) + else: + extra_toolchains.append(CC_TOOLCHAIN) + analysis_test( + name = name, + impl = _test_runtime_env_toolchain_matches_impl, + target = name + "_subject", + config_settings = { + "//command_line_option:extra_toolchains": extra_toolchains, + EXEC_TOOLS_TOOLCHAIN: "enabled", + VISIBLE_FOR_TESTING: True, + }, + ) + +def _test_runtime_env_toolchain_matches_impl(env, target): + env.expect.that_str( + str(target[_LookupInfo].target.toolchain_label), + ).contains("runtime_env_py_runtime_pair") + env.expect.that_str( + str(target[_LookupInfo].exec.toolchain_label), + ).contains("runtime_env_py_exec_tools") + env.expect.that_str( + str(target[_LookupInfo].cc.toolchain_label), + ).contains("runtime_env_py_cc") + +_tests.append(_test_runtime_env_toolchain_matches) + +def runtime_env_toolchain_test_suite(name): + test_suite(name = name, tests = _tests) diff --git a/tests/support/support.bzl b/tests/support/support.bzl index 2e5820312a..a74346d7b3 100644 --- a/tests/support/support.bzl +++ b/tests/support/support.bzl @@ -37,3 +37,4 @@ PRECOMPILE_ADD_TO_RUNFILES = str(Label("//python/config_settings:precompile_add_ PRECOMPILE_SOURCE_RETENTION = str(Label("//python/config_settings:precompile_source_retention")) PYC_COLLECTION = str(Label("//python/config_settings:pyc_collection")) PYTHON_VERSION = str(Label("//python/config_settings:python_version")) +VISIBLE_FOR_TESTING = str(Label("//python/private:visible_for_testing"))