From 71214129707ee718ba746618d7091372979d041d Mon Sep 17 00:00:00 2001 From: Richard Levasseur Date: Mon, 1 Jun 2026 00:37:12 +0000 Subject: [PATCH 1/3] feat: add //command_line_option:extra_toolchains pseudo-flag Add support for transitioning on the //command_line_option:extra_toolchains built-in flag using py_binary.config_settings. Note that, unlike the normal Bazel built-in flag, it must be specified as a simple comma-separated string when set using config_settings, which is then parsed as a CSV string. This is implemented by: - Adding an alias extra_toolchains in command_line_option/BUILD.bazel. - Adding //command_line_option:extra_toolchains to TRANSITION_LABELS so that it is inherited by all transition-using rules (py_wheel, py_zipapp, etc). - Updating apply_config_settings_attr in python/private/attributes.bzl to parse the extra_toolchains CSV string into a list of strings when set via config_settings. - Adding a test case and updating documentation. --- command_line_option/BUILD.bazel | 5 ++++ .../rules_python/command_line_option/index.md | 23 +++++++++++++++++++ python/features.bzl | 1 + python/private/attributes.bzl | 9 ++++++-- python/private/common_labels.bzl | 1 + python/private/transition_labels.bzl | 1 + tests/base_rules/py_executable_base_tests.bzl | 23 +++++++++++++++++++ .../bzlmod_lockfile/MODULE.bazel.lock | 2 +- 8 files changed, 62 insertions(+), 3 deletions(-) diff --git a/command_line_option/BUILD.bazel b/command_line_option/BUILD.bazel index a4d5f0f80d..15c22f360b 100644 --- a/command_line_option/BUILD.bazel +++ b/command_line_option/BUILD.bazel @@ -18,6 +18,11 @@ alias( actual = "//python:none", ) +alias( + name = "extra_toolchains", + actual = "//python:none", +) + filegroup( name = "distribution", srcs = glob(["**"]), diff --git a/docs/api/rules_python/command_line_option/index.md b/docs/api/rules_python/command_line_option/index.md index a7dfa340eb..02d29206f5 100644 --- a/docs/api/rules_python/command_line_option/index.md +++ b/docs/api/rules_python/command_line_option/index.md @@ -51,3 +51,26 @@ See the [Bazel documentation for --enable_runfiles](https://bazel.build/referenc The special value `INHERIT` can be specified to use the existing flag value. ::: + +## extra_toolchains + +:::{bzl:target} extra_toolchains + +Special target for the Bazel-builtin `//command_line_option:extra_toolchains` +flag. + +See the [Bazel documentation for --extra_toolchains](https://bazel.build/reference/command-line-reference#flag--extra_toolchains). + +The special value `INHERIT` can be specified to use the existing flag value. + +:::{note} +Unlike the normal Bazel built-in flag, which accepts a list of labels, this +pseudo-flag must be specified as a single, comma-separated string when set +using the `config_settings` attribute. For example: + +```python +"//command_line_option:extra_toolchains": "//my/tc1,//my/tc2" +``` +::: +::: + diff --git a/python/features.bzl b/python/features.bzl index 26acc8c5fe..a2cb95f1ee 100644 --- a/python/features.bzl +++ b/python/features.bzl @@ -86,6 +86,7 @@ def _features_typedef(): _TARGETS = { "//command_line_option:build_runfile_links": True, "//command_line_option:enable_runfiles": True, + "//command_line_option:extra_toolchains": True, "//python/cc:current_py_cc_headers_abi3": True, } diff --git a/python/private/attributes.bzl b/python/private/attributes.bzl index beaa7a6a73..ad741d078d 100644 --- a/python/private/attributes.bzl +++ b/python/private/attributes.bzl @@ -446,10 +446,15 @@ def apply_config_settings_attr(settings, attr): if key.package == "command_line_option": if value == "INHERIT": continue - else: - str_key = "//command_line_option:" + key.name + str_key = "//command_line_option:" + key.name + if key.name == "extra_toolchains": + if value == "": + value = [] + else: + value = [v.strip() for v in value.split(",") if v.strip()] else: str_key = str(key) + settings[str_key] = value return settings diff --git a/python/private/common_labels.bzl b/python/private/common_labels.bzl index ff4e7e1dad..a83ba2b462 100644 --- a/python/private/common_labels.bzl +++ b/python/private/common_labels.bzl @@ -14,6 +14,7 @@ labels = struct( # NOTE: Special target; see definition for details. ENABLE_RUNFILES = str(Label("//command_line_option:enable_runfiles")), EXEC_TOOLS_TOOLCHAIN = str(Label("//python/config_settings:exec_tools_toolchain")), + EXTRA_TOOLCHAINS = str(Label("//command_line_option:extra_toolchains")), NONE = str(Label("//python:none")), PIP_ENV_MARKER_CONFIG = str(Label("//python/config_settings:pip_env_marker_config")), PIP_WHL_OSX_VERSION = str(Label("//python/config_settings:pip_whl_osx_version")), diff --git a/python/private/transition_labels.bzl b/python/private/transition_labels.bzl index 5f0aa69056..7a6531ed0f 100644 --- a/python/private/transition_labels.bzl +++ b/python/private/transition_labels.bzl @@ -12,6 +12,7 @@ _BASE_TRANSITION_LABELS = [ labels.BOOTSTRAP_IMPL, labels.DEBUGGER, labels.EXEC_TOOLS_TOOLCHAIN, + "//command_line_option:extra_toolchains", labels.PIP_ENV_MARKER_CONFIG, labels.PIP_WHL_OSX_VERSION, labels.PRECOMPILE, diff --git a/tests/base_rules/py_executable_base_tests.bzl b/tests/base_rules/py_executable_base_tests.bzl index dff0399bc2..7531de4c30 100644 --- a/tests/base_rules/py_executable_base_tests.bzl +++ b/tests/base_rules/py_executable_base_tests.bzl @@ -109,6 +109,29 @@ def _test_basic_zip_impl(env, target): _tests.append(_test_basic_zip) +def _test_config_settings_extra_toolchains(name, config): + rt_util.helper_target( + config.rule, + name = name + "_subject", + srcs = ["main.py"], + main = "main.py", + config_settings = { + "//command_line_option:extra_toolchains": "{tc},{tc}".format(tc = CC_TOOLCHAIN), + }, + ) + analysis_test( + name = name, + impl = _test_config_settings_extra_toolchains_impl, + target = name + "_subject", + ) + +def _test_config_settings_extra_toolchains_impl(env, target): + # If we got here, it means analysis succeeded, which implies the transition + # successfully parsed the CSV string into a list. + env.expect.that_target(target).has_provider(PyInfo) + +_tests.append(_test_config_settings_extra_toolchains) + def _test_cross_compile_to_unix(name, config): rt_util.helper_target( config.rule, diff --git a/tests/integration/bzlmod_lockfile/MODULE.bazel.lock b/tests/integration/bzlmod_lockfile/MODULE.bazel.lock index 0dcc4b2a48..d21fec2d7d 100644 --- a/tests/integration/bzlmod_lockfile/MODULE.bazel.lock +++ b/tests/integration/bzlmod_lockfile/MODULE.bazel.lock @@ -250,7 +250,7 @@ }, "@@rules_python+//python/uv:uv.bzl%uv": { "general": { - "bzlTransitiveDigest": "yrEbeCJlv5gbdoRjwwR/EDEkc3pfuQy/FTYKMNoK5Wc=", + "bzlTransitiveDigest": "Z5ZPR9z4PkJRXSyJ4KQEqM4kwiqWBCn8Ajzxy9YlS/g=", "usagesDigest": "6yXGw7XDyXjOfqBL0SBu1YBEMMYPQzCE3jTzUCkxPgg=", "recordedInputs": [ "REPO_MAPPING:rules_python+,bazel_tools bazel_tools", From 9ec77709407dd02f8d52393d4eef3ab07cb729d1 Mon Sep 17 00:00:00 2001 From: Richard Levasseur Date: Sat, 6 Jun 2026 17:12:53 +0000 Subject: [PATCH 2/3] chore: add PR amend/rebase prohibition rule for AI agents Configure AI agents to never amend or rebase PRs after creation, and use new commits instead. --- .agents/AGENTS.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .agents/AGENTS.md diff --git a/.agents/AGENTS.md b/.agents/AGENTS.md new file mode 100644 index 0000000000..3ec96a6865 --- /dev/null +++ b/.agents/AGENTS.md @@ -0,0 +1,3 @@ +# Guidance for AI Agents + +* NEVER amend or rebase a PR once it has been created. Use new commits instead. From 9e83e24ad7d26a83713b68fa76f5e0450add42da Mon Sep 17 00:00:00 2001 From: Richard Levasseur Date: Sat, 6 Jun 2026 17:13:40 +0000 Subject: [PATCH 3/3] chore: remove .agents/AGENTS.md --- .agents/AGENTS.md | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 .agents/AGENTS.md diff --git a/.agents/AGENTS.md b/.agents/AGENTS.md deleted file mode 100644 index 3ec96a6865..0000000000 --- a/.agents/AGENTS.md +++ /dev/null @@ -1,3 +0,0 @@ -# Guidance for AI Agents - -* NEVER amend or rebase a PR once it has been created. Use new commits instead.