From 048b49517450bceea8d085abda78a32433546770 Mon Sep 17 00:00:00 2001 From: Ignas Anikevicius <240938+aignas@users.noreply.github.com> Date: Thu, 24 Jul 2025 20:38:30 +0900 Subject: [PATCH 1/6] feat(core): switch to script bootstrap as a default Work towards #2156 Work towards #2521 Relands #2858 and reverts #2968 Fixes #2983 --- CHANGELOG.md | 8 ++++++++ docs/api/rules_python/python/config_settings/index.md | 11 ++++++++++- python/config_settings/BUILD.bazel | 2 +- 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 382096f826..7886260ef7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -69,6 +69,14 @@ END_UNRELEASED_TEMPLATE * (bootstrap) For {obj}`--bootstrap_impl=system_python`, the sys.path order has changed from `[app paths, stdlib, runtime site-packages]` to `[stdlib, app paths, runtime site-packages]`. +* If using the (deprecated) autodetecting/runtime_env toolchain, then the Python + version specified at build-time *must* match the Python version used at + runtime (the {obj}`--@rules_python//python/config_settings:python_version` + flag and the {attr}`python_version` attribute control the build-time version + for a target). If they don't match, dependencies won't be importable. (Such a + misconfiguration was unlikely to work to begin with; this is called out as an + FYI). +* (rules) {obj}`--bootstrap_impl=script` is the default for non-Windows for bazel 8 and above. {#v0-0-0-fixed} ### Fixed diff --git a/docs/api/rules_python/python/config_settings/index.md b/docs/api/rules_python/python/config_settings/index.md index 989ebf1128..3ad4ae6705 100644 --- a/docs/api/rules_python/python/config_settings/index.md +++ b/docs/api/rules_python/python/config_settings/index.md @@ -245,8 +245,12 @@ Values: ::::{bzl:flag} bootstrap_impl Determine how programs implement their startup process. +The default for this depends on the platform: +* Windows: `system_python` (**always** used) +* Other: `script` + Values: -* `system_python`: (default) Use a bootstrap that requires a system Python available +* `system_python`: Use a bootstrap that requires a system Python available in order to start programs. This requires {obj}`PyRuntimeInfo.bootstrap_template` to be a Python program. * `script`: Use a bootstrap that uses an arbitrary executable script (usually a @@ -269,6 +273,11 @@ instead. :::{versionadded} 0.33.0 ::: +:::{versionchanged} VERSION_NEXT_FEATURE +* The default for non-Windows changed from `system_python` to `script`. +* On Windows, the value is forced to `system_python`. +::: + :::: ::::{bzl:flag} current_config diff --git a/python/config_settings/BUILD.bazel b/python/config_settings/BUILD.bazel index 82a73cee6c..b59feb4189 100644 --- a/python/config_settings/BUILD.bazel +++ b/python/config_settings/BUILD.bazel @@ -90,7 +90,7 @@ string_flag( rp_string_flag( name = "bootstrap_impl", - build_setting_default = BootstrapImplFlag.SYSTEM_PYTHON, + build_setting_default = BootstrapImplFlag.SCRIPT, override = select({ # Windows doesn't yet support bootstrap=script, so force disable it ":_is_windows": BootstrapImplFlag.SYSTEM_PYTHON, From 42dac206b661546632eda33ee1a8f039a2383064 Mon Sep 17 00:00:00 2001 From: Ignas Anikevicius <240938+aignas@users.noreply.github.com> Date: Sat, 20 Sep 2025 19:28:51 +0900 Subject: [PATCH 2/6] conditional support for the bootstrap=script --- python/config_settings/BUILD.bazel | 3 ++- python/private/util.bzl | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/python/config_settings/BUILD.bazel b/python/config_settings/BUILD.bazel index b59feb4189..8b9722ca5a 100644 --- a/python/config_settings/BUILD.bazel +++ b/python/config_settings/BUILD.bazel @@ -13,6 +13,7 @@ load( "VenvsUseDeclareSymlinkFlag", rp_string_flag = "string_flag", ) +load("//python/private:util.bzl", "IS_BAZEL_8_OR_HIGHER") load( "//python/private/pypi:flags.bzl", "UniversalWhlFlag", @@ -90,7 +91,7 @@ string_flag( rp_string_flag( name = "bootstrap_impl", - build_setting_default = BootstrapImplFlag.SCRIPT, + build_setting_default = BootstrapImplFlag.SCRIPT if IS_BAZEL_8_OR_HIGHER else BootstrapImplFlag.SYSTEM_PYTHON, override = select({ # Windows doesn't yet support bootstrap=script, so force disable it ":_is_windows": BootstrapImplFlag.SYSTEM_PYTHON, diff --git a/python/private/util.bzl b/python/private/util.bzl index 4d2da57760..1cc7a30b8a 100644 --- a/python/private/util.bzl +++ b/python/private/util.bzl @@ -99,6 +99,9 @@ def define_bazel_6_provider(doc, fields, **kwargs): return provider("Stub, not used", fields = []), None return provider(doc = doc, fields = fields, **kwargs) +# Only bazel 8 can distinguish symlinks within the file depsets. +IS_BAZEL_8_OR_HIGHER = hasattr(config, "none") + IS_BAZEL_7_4_OR_HIGHER = hasattr(native, "legacy_globals") IS_BAZEL_7_OR_HIGHER = hasattr(native, "starlark_doc_extract") From e1ff659054169baba50052b4849cd6a546f95615 Mon Sep 17 00:00:00 2001 From: Richard Levasseur Date: Sat, 20 Sep 2025 11:38:01 -0700 Subject: [PATCH 3/6] Apply suggestions from code review --- CHANGELOG.md | 2 +- docs/api/rules_python/python/config_settings/index.md | 9 +++++---- python/private/util.bzl | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7886260ef7..7337465901 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -76,7 +76,7 @@ END_UNRELEASED_TEMPLATE for a target). If they don't match, dependencies won't be importable. (Such a misconfiguration was unlikely to work to begin with; this is called out as an FYI). -* (rules) {obj}`--bootstrap_impl=script` is the default for non-Windows for bazel 8 and above. +* (rules) {obj}`--bootstrap_impl=script` is the default for non-Windows for Bazel 8 and above. {#v0-0-0-fixed} ### Fixed diff --git a/docs/api/rules_python/python/config_settings/index.md b/docs/api/rules_python/python/config_settings/index.md index 3ad4ae6705..b2d01f0607 100644 --- a/docs/api/rules_python/python/config_settings/index.md +++ b/docs/api/rules_python/python/config_settings/index.md @@ -245,9 +245,11 @@ Values: ::::{bzl:flag} bootstrap_impl Determine how programs implement their startup process. -The default for this depends on the platform: +The default for this depends on the platform and environment: * Windows: `system_python` (**always** used) -* Other: `script` +* Non-Windows with Bazel 8 or higher: `script` +* Other: `system_python` + Values: * `system_python`: Use a bootstrap that requires a system Python available @@ -274,8 +276,7 @@ instead. ::: :::{versionchanged} VERSION_NEXT_FEATURE -* The default for non-Windows changed from `system_python` to `script`. -* On Windows, the value is forced to `system_python`. +* The default changed from `system_python` to `script` for non-Windows with Bazel 8 or higher. ::: :::: diff --git a/python/private/util.bzl b/python/private/util.bzl index 1cc7a30b8a..362a2e16bc 100644 --- a/python/private/util.bzl +++ b/python/private/util.bzl @@ -99,7 +99,7 @@ def define_bazel_6_provider(doc, fields, **kwargs): return provider("Stub, not used", fields = []), None return provider(doc = doc, fields = fields, **kwargs) -# Only bazel 8 can distinguish symlinks within the file depsets. +# `config.none` was introduced in Bazel 8 IS_BAZEL_8_OR_HIGHER = hasattr(config, "none") IS_BAZEL_7_4_OR_HIGHER = hasattr(native, "legacy_globals") From f5ae2b41255a28db6f26b5202b305940edde50fe Mon Sep 17 00:00:00 2001 From: Ignas Anikevicius <240938+aignas@users.noreply.github.com> Date: Sun, 28 Sep 2025 11:25:45 +0900 Subject: [PATCH 4/6] use internal config repo instead --- python/config_settings/BUILD.bazel | 4 ++-- python/private/internal_config_repo.bzl | 14 ++++++++------ python/private/util.bzl | 3 --- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/python/config_settings/BUILD.bazel b/python/config_settings/BUILD.bazel index 7f01de8f28..42c64c5311 100644 --- a/python/config_settings/BUILD.bazel +++ b/python/config_settings/BUILD.bazel @@ -1,5 +1,6 @@ load("@bazel_skylib//rules:common_settings.bzl", "bool_flag", "string_flag") load("@pythons_hub//:versions.bzl", "DEFAULT_PYTHON_VERSION", "MINOR_MAPPING", "PYTHON_VERSIONS") +load("@rules_python_internal//:rules_python_config.bzl", rp_config = "config") load( "//python/private:flags.bzl", "AddSrcsToRunfilesFlag", @@ -13,7 +14,6 @@ load( "VenvsUseDeclareSymlinkFlag", rp_string_flag = "string_flag", ) -load("//python/private:util.bzl", "IS_BAZEL_8_OR_HIGHER") load( "//python/private/pypi:flags.bzl", "UniversalWhlFlag", @@ -91,7 +91,7 @@ string_flag( rp_string_flag( name = "bootstrap_impl", - build_setting_default = BootstrapImplFlag.SCRIPT if IS_BAZEL_8_OR_HIGHER else BootstrapImplFlag.SYSTEM_PYTHON, + build_setting_default = rp_config.bootstrap_impl_default, override = select({ # Windows doesn't yet support bootstrap=script, so force disable it ":_is_windows": BootstrapImplFlag.SYSTEM_PYTHON, diff --git a/python/private/internal_config_repo.bzl b/python/private/internal_config_repo.bzl index 109e68a8a1..352ebaf297 100644 --- a/python/private/internal_config_repo.bzl +++ b/python/private/internal_config_repo.bzl @@ -18,6 +18,7 @@ such as globals available to Bazel versions, or propagating user environment settings for rules to later use. """ +load("//python/private:flags.bzl", "BootstrapImplFlag") load("//python/private:text_util.bzl", "render") load(":repo_utils.bzl", "repo_utils") @@ -30,6 +31,7 @@ _CONFIG_TEMPLATE = """ config = struct( enable_pystar = True, enable_pipstar = {enable_pipstar}, + bootstrap_impl_default = "{bootstrap_impl_default}", enable_deprecation_warnings = {enable_deprecation_warnings}, BuiltinPyInfo = getattr(getattr(native, "legacy_globals", None), "PyInfo", {builtin_py_info_symbol}), BuiltinPyRuntimeInfo = getattr(getattr(native, "legacy_globals", None), "PyRuntimeInfo", {builtin_py_runtime_info_symbol}), @@ -86,32 +88,32 @@ _TRANSITION_SETTINGS_DEBUG_TEMPLATE = """ """ def _internal_config_repo_impl(rctx): + # TODO: remove the conditional once bazel 7 is no longer supported if not native.bazel_version or int(native.bazel_version.split(".")[0]) >= 8: builtin_py_info_symbol = "None" builtin_py_runtime_info_symbol = "None" builtin_py_cc_link_params_provider = "None" + bootstrap_impl_default = BootstrapImplFlag.SCRIPT else: builtin_py_info_symbol = "PyInfo" builtin_py_runtime_info_symbol = "PyRuntimeInfo" builtin_py_cc_link_params_provider = "PyCcLinkParamsProvider" + bootstrap_impl_default = BootstrapImplFlag.SYSTEM_PYTHON rctx.file("rules_python_config.bzl", _CONFIG_TEMPLATE.format( enable_pipstar = _bool_from_environ(rctx, _ENABLE_PIPSTAR_ENVVAR_NAME, _ENABLE_PIPSTAR_DEFAULT), + bootstrap_impl_default = bootstrap_impl_default, enable_deprecation_warnings = _bool_from_environ(rctx, _ENABLE_DEPRECATION_WARNINGS_ENVVAR_NAME, _ENABLE_DEPRECATION_WARNINGS_DEFAULT), builtin_py_info_symbol = builtin_py_info_symbol, builtin_py_runtime_info_symbol = builtin_py_runtime_info_symbol, builtin_py_cc_link_params_provider = builtin_py_cc_link_params_provider, )) - shim_content = _PY_INTERNAL_SHIM - py_internal_dep = '"@rules_python//tools/build_defs/python/private:py_internal_renamed_bzl"' - rctx.file("BUILD", ROOT_BUILD_TEMPLATE.format( - py_internal_dep = py_internal_dep, + py_internal_dep = '"@rules_python//tools/build_defs/python/private:py_internal_renamed_bzl"', visibility = "@rules_python//:__subpackages__", )) - rctx.file("py_internal.bzl", shim_content) - + rctx.file("py_internal.bzl", _PY_INTERNAL_SHIM) rctx.file( "extra_transition_settings.bzl", _EXTRA_TRANSITIONS_TEMPLATE.format( diff --git a/python/private/util.bzl b/python/private/util.bzl index 724b5feeb7..d3053fe626 100644 --- a/python/private/util.bzl +++ b/python/private/util.bzl @@ -69,6 +69,3 @@ def add_tag(attrs, tag): attrs["tags"] = tags + [tag] else: attrs["tags"] = [tag] - -# `config.none` was introduced in Bazel 8 -IS_BAZEL_8_OR_HIGHER = hasattr(config, "none") From 1d72e092211aeb80714ec45ca707da07f682024b Mon Sep 17 00:00:00 2001 From: Ignas Anikevicius <240938+aignas@users.noreply.github.com> Date: Sun, 28 Sep 2025 11:35:15 +0900 Subject: [PATCH 5/6] add a missing bzl_library dep --- python/private/BUILD.bazel | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/python/private/BUILD.bazel b/python/private/BUILD.bazel index 1bcd0f678f..fc85efa6c6 100644 --- a/python/private/BUILD.bazel +++ b/python/private/BUILD.bazel @@ -197,7 +197,10 @@ bzl_library( bzl_library( name = "internal_config_repo_bzl", srcs = ["internal_config_repo.bzl"], - deps = [":bzlmod_enabled_bzl"], + deps = [ + ":bzlmod_enabled_bzl", + ":flags_bzl", + ], ) bzl_library( From 1b61108abfbb8749f21fd31951c341f28968c213 Mon Sep 17 00:00:00 2001 From: Ignas Anikevicius <240938+aignas@users.noreply.github.com> Date: Sun, 28 Sep 2025 11:39:59 +0900 Subject: [PATCH 6/6] use the string constant --- python/private/BUILD.bazel | 5 +---- python/private/internal_config_repo.bzl | 11 ++++++++--- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/python/private/BUILD.bazel b/python/private/BUILD.bazel index fc85efa6c6..1bcd0f678f 100644 --- a/python/private/BUILD.bazel +++ b/python/private/BUILD.bazel @@ -197,10 +197,7 @@ bzl_library( bzl_library( name = "internal_config_repo_bzl", srcs = ["internal_config_repo.bzl"], - deps = [ - ":bzlmod_enabled_bzl", - ":flags_bzl", - ], + deps = [":bzlmod_enabled_bzl"], ) bzl_library( diff --git a/python/private/internal_config_repo.bzl b/python/private/internal_config_repo.bzl index 352ebaf297..d6fcd88734 100644 --- a/python/private/internal_config_repo.bzl +++ b/python/private/internal_config_repo.bzl @@ -18,7 +18,6 @@ such as globals available to Bazel versions, or propagating user environment settings for rules to later use. """ -load("//python/private:flags.bzl", "BootstrapImplFlag") load("//python/private:text_util.bzl", "render") load(":repo_utils.bzl", "repo_utils") @@ -93,12 +92,18 @@ def _internal_config_repo_impl(rctx): builtin_py_info_symbol = "None" builtin_py_runtime_info_symbol = "None" builtin_py_cc_link_params_provider = "None" - bootstrap_impl_default = BootstrapImplFlag.SCRIPT + + # NOTE @aignas 2025-09-28: we are not using flag constants due to circular + # declarations in the WORKSPACE case + bootstrap_impl_default = "script" else: builtin_py_info_symbol = "PyInfo" builtin_py_runtime_info_symbol = "PyRuntimeInfo" builtin_py_cc_link_params_provider = "PyCcLinkParamsProvider" - bootstrap_impl_default = BootstrapImplFlag.SYSTEM_PYTHON + + # NOTE @aignas 2025-09-28: we are not using flag constants due to circular + # declarations in the WORKSPACE case + bootstrap_impl_default = "system_python" rctx.file("rules_python_config.bzl", _CONFIG_TEMPLATE.format( enable_pipstar = _bool_from_environ(rctx, _ENABLE_PIPSTAR_ENVVAR_NAME, _ENABLE_PIPSTAR_DEFAULT),