Skip to content

Commit 3a307da

Browse files
committed
fix(precompile): autodetecting toolchain and feature flags
With this we can finally be correct with how we deal with the precompile toolchains. This is done in two ways: 1. Add a config_setting that explicitly enableds/disables the precompile toolchains. 2. Add an autodetecting toolchain for precompile in cases where users may want to use the autodetecting toolchain and we would like to ensure that the hermetic toolchain is not pulled in because it exists and is used in the target. To keep the behaviour backwards compatible, add an alias to the autodetecting toolchain with a deprecation notice. The API is new in 0.33.0 and it is unfortunate that we have to do this, but the users should still be able to use the code as is. Fixes #1967.
1 parent 878d3f7 commit 3a307da

File tree

12 files changed

+139
-25
lines changed

12 files changed

+139
-25
lines changed

CHANGELOG.md

+8-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,14 @@ A brief description of the categories of changes:
2828
* `protobuf`/`com_google_protobuf` dependency bumped to `v24.4`
2929

3030
### Fixed
31-
* Nothing yet
31+
* (precompile) The toolchains are no longer automatically matched if the
32+
precompiling feature is disabled. It can be enabled as described in the
33+
updated docs. What is more, the autodetecting toolchain should be registered
34+
via `--extra_toolchains=@rules_python//python/autodetecting_toolchain:all`
35+
instead of
36+
`--extra_toolchains=@rules_python//python:autodetecting_toolchain`. The old
37+
target is going to work, but may be removed in the future release.
38+
Fixes [1967](https://github.com/bazelbuild/rules_python/issues/1967).
3239

3340
### Removed
3441
* Nothing yet
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
:::{default-domain} bzl
2+
:::
3+
:::{bzl:currentfile} //python/autodetecting_toolchain:BUILD.bazel
4+
:::
5+
6+
# //python/autodetecting_toolchain
7+
8+
::::{target} all
9+
10+
A simple set of toolchains that simply uses `python3` from the runtime environment.
11+
12+
Note that this toolchain provides no build-time information, which makes it of
13+
limited utility.
14+
15+
This is only provided to aid migration off the builtin Bazel toolchain
16+
(`@bazel_tools//python:autodetecting_toolchain`), and is largely only applicable
17+
to WORKSPACE builds.
18+
19+
:::{deprecated} unspecified
20+
21+
Switch to using a hermetic toolchain or manual toolchain configuration instead.
22+
:::
23+
24+
::::

docs/sphinx/api/python/config_settings/index.md

+20-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,17 @@ Determines the default hermetic Python toolchain version. This can be set to
1010
one of the values that `rules_python` maintains.
1111
:::
1212

13+
::::{bzl:flag} precompile_toolchain
14+
Determines if the precompile toolchains are used.
15+
16+
Values:
17+
18+
* `enabled`: Allow matching of the registered toolchains at build time.
19+
* `disabled`: Don't match registered precompile toolchains at build time.
20+
:::{versionadded} 0.33.2
21+
:::
22+
::::
23+
1324
::::{bzl:flag} precompile
1425
Determines if Python source files should be compiled at build time.
1526

@@ -34,6 +45,8 @@ Values:
3445
* `force_disabled`: Like `disabled`, except overrides target-level setting. This
3546
is useful useful for development, testing enabling precompilation more
3647
broadly, or as an escape hatch if build-time compiling is not available.
48+
:::{versionadded} 0.33.0
49+
:::
3750
::::
3851

3952
::::{bzl:flag} precompile_source_retention
@@ -51,9 +64,11 @@ Values:
5164
* `omit_source`: Don't include the orignal py source.
5265
* `omit_if_generated_source`: Keep the original source if it's a regular source
5366
file, but omit it if it's a generated file.
67+
:::{versionadded} 0.33.0
68+
:::
5469
::::
5570

56-
:::{bzl:flag} precompile_add_to_runfiles
71+
::::{bzl:flag} precompile_add_to_runfiles
5772
Determines if a target adds its compiled files to its runfiles.
5873

5974
When a target compiles its files, but doesn't add them to its own runfiles, it
@@ -66,7 +81,9 @@ Values:
6681
runfiles; they are still added to {bzl:obj}`PyInfo.transitive_pyc_files`. See
6782
also: {bzl:obj}`py_binary.pyc_collection` attribute. This is useful for allowing
6883
incrementally enabling precompilation on a per-binary basis.
84+
:::{versionadded} 0.33.0
6985
:::
86+
::::
7087

7188
::::{bzl:flag} pyc_collection
7289
Determine if `py_binary` collects transitive pyc files.
@@ -78,6 +95,8 @@ This flag is overridden by the target level `pyc_collection` attribute.
7895
Values:
7996
* `include_pyc`: Include `PyInfo.transitive_pyc_files` as part of the binary.
8097
* `disabled`: Don't include `PyInfo.transitive_pyc_files` as part of the binary.
98+
:::{versionadded} 0.33.0
99+
:::
81100
::::
82101

83102
::::{bzl:flag} py_linux_libc

docs/sphinx/api/python/index.md

+1-15
Original file line numberDiff line numberDiff line change
@@ -26,18 +26,4 @@ provides:
2626

2727
::::{target} autodetecting_toolchain
2828

29-
A simple toolchain that simply uses `python3` from the runtime environment.
30-
31-
Note that this toolchain provides no build-time information, which makes it of
32-
limited utility.
33-
34-
This is only provided to aid migration off the builtin Bazel toolchain
35-
(`@bazel_tools//python:autodetecting_toolchain`), and is largely only applicable
36-
to WORKSPACE builds.
37-
38-
:::{deprecated} unspecified
39-
40-
Switch to using a hermetic toolchain or manual toolchain configuration instead.
41-
:::
42-
43-
::::
29+
Deprecated, see `{bzl:target}//python/autodetecting_toolchain:all`.

docs/sphinx/toolchains.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -233,12 +233,12 @@ use `python3` from the environment a binary runs within. This provides extremely
233233
limited functionality to the rules (at build time, nothing is knowable about
234234
the Python runtime).
235235

236-
Bazel itself automatically registers `@bazel_tools//python:autodetecting_toolchain`
236+
Bazel itself automatically registers `@bazel_tools//python/autodetecting_toolchain:all`
237237
as the lowest priority toolchain. For WORKSPACE builds, if no other toolchain
238238
is registered, that toolchain will be used. For bzlmod builds, rules_python
239239
automatically registers a higher-priority toolchain; it won't be used unless
240240
there is a toolchain misconfiguration somewhere.
241241

242242
To aid migration off the Bazel-builtin toolchain, rules_python provides
243-
{obj}`@rules_python//python:autodetecting_toolchain`. This is an equivalent
243+
{obj}`@rules_python//python/autodetecting_toolchain:all`. This is an equivalent
244244
toolchain, but is implemented using rules_python's objects.

python/BUILD.bazel

+6-3
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ that @rules_python//python is only concerned with the core rules.
2424
"""
2525

2626
load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
27-
load("//python/private:autodetecting_toolchain.bzl", "define_autodetecting_toolchain")
2827
load(":current_py_toolchain.bzl", "current_py_toolchain")
2928

3029
package(default_visibility = ["//visibility:public"])
@@ -319,11 +318,15 @@ toolchain_type(
319318
# safe if you know for a fact that your build is completely compatible with the
320319
# version of the `python` command installed on the target platform.
321320

322-
define_autodetecting_toolchain(name = "autodetecting_toolchain")
321+
alias(
322+
name = "autodetecting_toolchain",
323+
actual = "//python/autodetecting_toolchain",
324+
deprecation = "Use //python/autodetecting_toolchain:all instead; targets under //docs are internal.",
325+
)
323326

324327
alias(
325328
name = "autodetecting_toolchain_nonstrict",
326-
actual = ":autodetecting_toolchain",
329+
actual = "//python/autodetecting_toolchain",
327330
)
328331

329332
# ========= Packaging rules =========
+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
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+
load("//python/private:autodetecting_toolchain.bzl", "define_autodetecting_toolchain")
16+
17+
package(default_visibility = ["//:__subpackages__"])
18+
19+
define_autodetecting_toolchain(name = "autodetecting_toolchain")

python/config_settings/BUILD.bazel

+18
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ load(
55
"PrecompileAddToRunfilesFlag",
66
"PrecompileFlag",
77
"PrecompileSourceRetentionFlag",
8+
"PrecompileToolchainFlag",
89
"PycCollectionFlag",
910
)
1011
load(
@@ -29,6 +30,23 @@ construct_config_settings(
2930
name = "construct_config_settings",
3031
)
3132

33+
string_flag(
34+
name = "precompile_toolchain",
35+
build_setting_default = PrecompileToolchainFlag.DISABLED,
36+
values = sorted(PrecompileToolchainFlag.__members__.values()),
37+
visibility = ["//visibility:private"],
38+
)
39+
40+
config_setting(
41+
name = "is_precompile_toolchain_enabled",
42+
flag_values = {
43+
"precompile_toolchain": PrecompileToolchainFlag.ENABLED,
44+
},
45+
# NOTE: Only public because it is used in py_toolchain_suite from toolchain
46+
# repositories
47+
visibility = ["//visibility:public"],
48+
)
49+
3250
string_flag(
3351
name = "precompile",
3452
build_setting_default = PrecompileFlag.AUTO,

python/private/BUILD.bazel

+2
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ bzl_library(
5959
name = "autodetecting_toolchain_bzl",
6060
srcs = ["autodetecting_toolchain.bzl"],
6161
deps = [
62+
":py_exec_tools_toolchain_bzl",
63+
":toolchain_types_bzl",
6264
"//python:py_runtime_bzl",
6365
"//python:py_runtime_pair_bzl",
6466
],

python/private/autodetecting_toolchain.bzl

+23-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@
1616

1717
load("//python:py_runtime.bzl", "py_runtime")
1818
load("//python:py_runtime_pair.bzl", "py_runtime_pair")
19+
load(":py_exec_tools_toolchain.bzl", "py_exec_tools_toolchain")
20+
load(
21+
":toolchain_types.bzl",
22+
"EXEC_TOOLS_TOOLCHAIN_TYPE",
23+
"TARGET_TOOLCHAIN_TYPE",
24+
)
1925

2026
def define_autodetecting_toolchain(name):
2127
"""Defines the autodetecting Python toolchain.
@@ -65,6 +71,22 @@ def define_autodetecting_toolchain(name):
6571
native.toolchain(
6672
name = name,
6773
toolchain = ":_autodetecting_py_runtime_pair",
68-
toolchain_type = ":toolchain_type",
74+
toolchain_type = TARGET_TOOLCHAIN_TYPE,
75+
visibility = ["//visibility:public"],
76+
)
77+
78+
is_precompile_enabled = Label("//python/config_settings:is_precompile_toolchain_enabled")
79+
py_exec_tools_toolchain(
80+
name = "_autodetecting_py3_exec_toolchain",
81+
exec_interpreter = "//python/private:autodetecting_toolchain_interpreter.sh",
82+
exec_interpreter_version_info = None,
83+
precompiler = Label("//tools/precompiler:precompiler"),
84+
visibility = ["//visibility:private"],
85+
)
86+
native.toolchain(
87+
name = name + "exec",
88+
toolchain = ":_autodetecting_py3_exec_toolchain",
89+
toolchain_type = EXEC_TOOLS_TOOLCHAIN_TYPE,
90+
target_settings = [is_precompile_enabled],
6991
visibility = ["//visibility:public"],
7092
)

python/private/flags.bzl

+9
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,15 @@ def _precompile_flag_get_effective_value(ctx):
3737
value = PrecompileFlag.DISABLED
3838
return value
3939

40+
# Determines if the Python source precompilation toolchain should be registered.
41+
# buildifier: disable=name-conventions
42+
PrecompileToolchainFlag = enum(
43+
# Enable registering the precompilation toolchains using the hermetic toolchain.
44+
ENABLED = "enabled",
45+
# Disable registering the precompilation toolchains using the hermetic toolchain.
46+
DISABLED = "disabled",
47+
)
48+
4049
# Determines if Python source files should be compiled at build time.
4150
#
4251
# NOTE: The flag value is overridden by the target-level attribute, except

python/private/py_toolchain_suite.bzl

+7-2
Original file line numberDiff line numberDiff line change
@@ -100,14 +100,19 @@ def py_toolchain_suite(*, prefix, user_repository_name, python_version, set_pyth
100100
**kwargs
101101
)
102102

103+
is_precompile_enabled = Label("//python/config_settings:is_precompile_toolchain_enabled")
103104
native.toolchain(
104105
name = "{prefix}_py_exec_tools_toolchain".format(prefix = prefix),
105106
toolchain = "@{user_repository_name}//:py_exec_tools_toolchain".format(
106107
user_repository_name = user_repository_name,
107108
),
108109
toolchain_type = EXEC_TOOLS_TOOLCHAIN_TYPE,
109-
# The target settings capture the Python version
110-
target_settings = target_settings,
110+
# The target settings capture the Python version, the select works like a
111+
# (target_settings AND is_precompile_enabled)
112+
target_settings = select({
113+
is_precompile_enabled: target_settings,
114+
"//conditions:default": [is_precompile_enabled],
115+
}),
111116
exec_compatible_with = kwargs.get("target_compatible_with"),
112117
)
113118

0 commit comments

Comments
 (0)