Skip to content

Commit 9f3512f

Browse files
authored
feat: default to bootstrap script for non-windows (#2858)
This makes non-Windows use the script bootstrap by default. It's been a couple releases without any reported issues, so it seems ready to become the default. Work towards #2156
1 parent 0b3d845 commit 9f3512f

File tree

10 files changed

+90
-6
lines changed

10 files changed

+90
-6
lines changed

CHANGELOG.md

+8
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,14 @@ END_UNRELEASED_TEMPLATE
5555
{#v0-0-0-changed}
5656
### Changed
5757

58+
* If using the (deprecated) autodetecting/runtime_env toolchain, then the Python
59+
version specified at build-time *must* match the Python version used at
60+
runtime (the {obj}`--@rules_python//python/config_settings:python_version`
61+
flag and the {attr}`python_version` attribute control the build-time version
62+
for a target). If they don't match, dependencies won't be importable. (Such a
63+
misconfiguration was unlikely to work to begin with; this is called out as an
64+
FYI).
65+
* (rules) {obj}`--bootstrap_impl=script` is the default for non-Windows.
5866
* (rules) On Windows, {obj}`--bootstrap_impl=system_python` is forced. This
5967
allows setting `--bootstrap_impl=script` in bazelrc for mixed-platform
6068
environments.

MODULE.bazel

+6-1
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,12 @@ internal_dev_deps = use_extension(
9898
"internal_dev_deps",
9999
dev_dependency = True,
100100
)
101-
use_repo(internal_dev_deps, "buildkite_config", "wheel_for_testing")
101+
use_repo(
102+
internal_dev_deps,
103+
"buildkite_config",
104+
"rules_python_runtime_env_tc_info",
105+
"wheel_for_testing",
106+
)
102107

103108
# Add gazelle plugin so that we can run the gazelle example as an e2e integration
104109
# test and include the distribution files.

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

+9
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,10 @@ Values:
245245
::::{bzl:flag} bootstrap_impl
246246
Determine how programs implement their startup process.
247247

248+
The default for this depends on the platform:
249+
* Windows: `system_python` (**always** used)
250+
* Other: `script`
251+
248252
Values:
249253
* `system_python`: Use a bootstrap that requires a system Python available
250254
in order to start programs. This requires
@@ -269,6 +273,11 @@ instead.
269273
:::{versionadded} 0.33.0
270274
:::
271275

276+
:::{versionchanged} VERSION_NEXT_FEATURE
277+
* The default for non-Windows changed from `system_python` to `script`.
278+
* On Windows, the value is forced to `system_python`.
279+
:::
280+
272281
::::
273282

274283
::::{bzl:flag} current_config

internal_dev_setup.bzl

+3
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ load("@rules_shell//shell:repositories.bzl", "rules_shell_dependencies", "rules_
2424
load("//:version.bzl", "SUPPORTED_BAZEL_VERSIONS")
2525
load("//python:versions.bzl", "MINOR_MAPPING", "TOOL_VERSIONS")
2626
load("//python/private:pythons_hub.bzl", "hub_repo") # buildifier: disable=bzl-visibility
27+
load("//python/private:runtime_env_repo.bzl", "runtime_env_repo") # buildifier: disable=bzl-visibility
2728
load("//python/private/pypi:deps.bzl", "pypi_deps") # buildifier: disable=bzl-visibility
2829

2930
def rules_python_internal_setup():
@@ -40,6 +41,8 @@ def rules_python_internal_setup():
4041
python_versions = sorted(TOOL_VERSIONS.keys()),
4142
)
4243

44+
runtime_env_repo(name = "rules_python_runtime_env_tc_info")
45+
4346
pypi_deps()
4447

4548
bazel_skylib_workspace()

python/config_settings/BUILD.bazel

+1-1
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ string_flag(
9090

9191
rp_string_flag(
9292
name = "bootstrap_impl",
93-
build_setting_default = BootstrapImplFlag.SYSTEM_PYTHON,
93+
build_setting_default = BootstrapImplFlag.SCRIPT,
9494
override = select({
9595
# Windows doesn't yet support bootstrap=script, so force disable it
9696
":_is_windows": BootstrapImplFlag.SYSTEM_PYTHON,

python/private/config_settings.bzl

+13-4
Original file line numberDiff line numberDiff line change
@@ -225,10 +225,19 @@ def is_python_version_at_least(name, **kwargs):
225225
)
226226

227227
def _python_version_at_least_impl(ctx):
228-
at_least = tuple(ctx.attr.at_least.split("."))
229-
current = tuple(
230-
ctx.attr._major_minor[config_common.FeatureFlagInfo].value.split("."),
231-
)
228+
flag_value = ctx.attr._major_minor[config_common.FeatureFlagInfo].value
229+
230+
# CI is, somehow, getting an empty string for the current flag value.
231+
# How isn't clear.
232+
if not flag_value:
233+
return [config_common.FeatureFlagInfo(value = "no")]
234+
235+
current = tuple([
236+
int(x)
237+
for x in flag_value.split(".")
238+
])
239+
at_least = tuple([int(x) for x in ctx.attr.at_least.split(".")])
240+
232241
value = "yes" if current >= at_least else "no"
233242
return [config_common.FeatureFlagInfo(value = value)]
234243

python/private/internal_dev_deps.bzl

+2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
load("@bazel_ci_rules//:rbe_repo.bzl", "rbe_preconfig")
1717
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_file")
18+
load(":runtime_env_repo.bzl", "runtime_env_repo")
1819

1920
def _internal_dev_deps_impl(mctx):
2021
_ = mctx # @unused
@@ -37,6 +38,7 @@ def _internal_dev_deps_impl(mctx):
3738
name = "buildkite_config",
3839
toolchain = "ubuntu1804-bazel-java11",
3940
)
41+
runtime_env_repo(name = "rules_python_runtime_env_tc_info")
4042

4143
internal_dev_deps = module_extension(
4244
implementation = _internal_dev_deps_impl,

python/private/runtime_env_repo.bzl

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
"""Internal setup to help the runtime_env toolchain."""
2+
3+
load("//python/private:repo_utils.bzl", "repo_utils")
4+
5+
def _runtime_env_repo_impl(rctx):
6+
pyenv = repo_utils.which_unchecked(rctx, "pyenv").binary
7+
if pyenv != None:
8+
pyenv_version_file = repo_utils.execute_checked(
9+
rctx,
10+
op = "GetPyenvVersionFile",
11+
arguments = [pyenv, "version-file"],
12+
).stdout.strip()
13+
14+
# When pyenv is used, the version file is what decided the
15+
# version used. Watch it so we compute the correct value if the
16+
# user changes it.
17+
rctx.watch(pyenv_version_file)
18+
19+
version = repo_utils.execute_checked(
20+
rctx,
21+
op = "GetPythonVersion",
22+
arguments = [
23+
"python3",
24+
"-I",
25+
"-c",
26+
"""import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")""",
27+
],
28+
environment = {
29+
# Prevent the user's current shell from influencing the result.
30+
# This envvar won't be present when a test is run.
31+
# NOTE: This should be None, but Bazel 7 doesn't support None
32+
# values. Thankfully, pyenv treats empty string the same as missing.
33+
"PYENV_VERSION": "",
34+
},
35+
).stdout.strip()
36+
rctx.file("info.bzl", "PYTHON_VERSION = '{}'\n".format(version))
37+
rctx.file("BUILD.bazel", "")
38+
39+
runtime_env_repo = repository_rule(
40+
implementation = _runtime_env_repo_impl,
41+
)

python/private/runtime_env_toolchain_interpreter.sh

+3
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,9 @@ if [ -e "$self_dir/pyvenv.cfg" ] || [ -e "$self_dir/../pyvenv.cfg" ]; then
6868
;;
6969
esac
7070

71+
if [ ! -e "$PYTHON_BIN" ]; then
72+
die "ERROR: Python interpreter does not exist: $PYTHON_BIN"
73+
fi
7174
# PYTHONEXECUTABLE is also used because `exec -a` doesn't fully trick the
7275
# pyenv wrappers.
7376
# NOTE: The PYTHONEXECUTABLE envvar only works for non-Mac starting in Python 3.11

tests/runtime_env_toolchain/BUILD.bazel

+4
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15+
load("@rules_python_runtime_env_tc_info//:info.bzl", "PYTHON_VERSION")
1516
load("//tests/support:sh_py_run_test.bzl", "py_reconfig_test")
1617
load("//tests/support:support.bzl", "CC_TOOLCHAIN")
1718
load(":runtime_env_toolchain_tests.bzl", "runtime_env_toolchain_test_suite")
@@ -30,6 +31,9 @@ py_reconfig_test(
3031
CC_TOOLCHAIN,
3132
],
3233
main = "toolchain_runs_test.py",
34+
# With bootstrap=script, the build version must match the runtime version
35+
# because the venv has the version in the lib/site-packages dir name.
36+
python_version = PYTHON_VERSION,
3337
# Our RBE has Python 3.6, which is too old for the language features
3438
# we use now. Using the runtime-env toolchain on RBE is pretty
3539
# questionable anyways.

0 commit comments

Comments
 (0)