You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Bump toolchains_llvm to 1.11.2, drop #791 archive_override - #423
Bumps toolchains_llvm from 1.8.0 to 1.11.2 in MODULE.bazel.
Drops the archive_override pinning an unreleased commit (merge of upstream #791, which dropped an unused -stdlib=libc++ flag that broke this project's Linux -Werror builds). That fix shipped in the 1.9.0 release — verified by diffing cc_toolchain_config.bzl at that tag against the pinned commit (identical) — so a plain bazel_dep pin replaces it.
Confirmed llvm_versions = "21.1.8" (what this project pins for all three platforms) is still a catalogued archive at 1.11.2 (toolchain/distributions/github.jsonc).
Deliberately not adopted here: 1.11.0 introduces a linker = {...} catalogue attribute (e.g. "darwin-aarch64": "auto") that's a more idiomatic way to express exactly the override this project hand-rolled with extra_link_flags — the release notes even call out "LLVM 23 on macOS still needs the native auto linker override for the known SDK/TAPI issue," which is our exact arm64e.x1 problem. Migrating to it is a worthwhile follow-up, but it's a mechanism change, not a side effect of a version bump, so I left it out of scope here.
Updated ci_msan_test's guard: it now checks the bazel_dep version directly and that no override targets toolchains_llvm, using the same full-call-body regex approach as the apple_support guard in Bump apple_support to 2.10.1, drop Xcode 27 crosstool patches #421 (avoids the "module_name must be the next line" fragility flagged there).
Test plan
Run on this macOS 27 / Xcode 27 host — exactly the scenario the original native-linker fix targets:
bazelisk test //python:ci_msan_test — red against the pre-bump 1.8.0 + override state (verified via git stash), green after
bazelisk test //... — 104/104 pass
bazelisk test --config=asan //library/tests/system/... — 22/22 pass
bazelisk test --config=tsan and --config=ubsan //library/tests/system:worker_context_reuse_test — pass
--config=msan is Linux-only and can't run on this host; ci_msan_test's config-wiring checks pass, and a --nobuild analysis probe of its toolchain fails identically before and after this bump (pre-existing macOS-host limitation, not a regression) — real msan verification happens on Linux CI for this PR
toolchains_llvm 1.8.0 emitted an unused -stdlib=libc++ under -nostdinc++,
breaking this project's Linux -Werror builds; the project carried an
archive_override pinned to the unreleased merge commit of upstream PR #791
to work around it. That fix shipped in the 1.9.0 release (verified by
diffing cc_toolchain_config.bzl at that tag against the pinned commit —
identical), so pin to 1.11.2 directly and drop the override.
Confirmed llvm_versions = "21.1.8" is still a catalogued archive at 1.11.2
(toolchain/distributions/github.jsonc), and that the extra_link_flags /
extra_link_libs mechanism this project relies on for the macOS 27 SDK /
Linux native-linker overrides is unchanged (cc_toolchain_config.bzl still
appends them after the toolchain-default --ld-path, so "last wins" still
holds). 1.11.0's new linker = {...} catalogue attribute is not adopted here
-- it's a more idiomatic way to express the same override going forward,
but switching to it is a separate, deliberate migration, not a side effect
of this version bump.
ci_msan_test's guard for the override is replaced with one that checks the
bazel_dep version and that no archive/single_version/git_override targets
toolchains_llvm, using the same full-call-body matching approach as the
apple_support guard (see PR #421) instead of a "next line" regex.
Verified on this macOS 27 / Xcode 27 host, which is exactly the scenario
the original fix targets:
- bazelisk test //... : 104/104 pass
- bazelisk test --config=asan //library/tests/system/... : 22/22 pass
- bazelisk test --config=tsan and --config=ubsan //library/tests/system:worker_context_reuse_test: pass
- msan is Linux-only and can't run on this host; confirmed the Bazel config
wiring test (ci_msan_test) passes, and that an unrelated
--nobuild analysis probe of its toolchain fails identically before and
after this bump (pre-existing macOS-host limitation, not a regression).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ains_llvm guard.
_has_toolchains_llvm_override()'s alternation only matched archive_override,
single_version_override, and git_override -- Bazel's other two module
override directives, local_path_override and multiple_version_override,
silently returned False, so either could reintroduce an override without
the guard noticing. Added both to the alternation and added a test for
each; confirmed both new tests fail against the pre-fix regex (verified
with a standalone repro) before adding the fix.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Addressed in 0c9ec92: added `local_path_override` and `multiple_version_override` to the alternation in `_has_toolchains_llvm_override()`, plus a test for each. Confirmed both new tests fail against the pre-fix regex (standalone repro) before adding the fix.
This same gap exists in the identical `_has_apple_support_override()` helper added in #421 — fixing that one too to avoid the same finding there.
Parse bazel_dep fields independently of argument order
python/tests/ci_msan_test.py:30
This parser only recognizes name immediately followed by version. Reordering or multiline formatting the valid bazel_dep arguments makes this guard fail even though the dependency remains correctly pinned; the analogous helper in ci_windows_cppopts_test.py:169-176 parses the whole call body to avoid this. Parse each full bazel_dep(...) body and find both fields independently (and add a reordered-arguments case).
…rder.
_toolchains_llvm_bazel_dep_version() only matched "name" immediately
followed by "version", so reordered or multiline bazel_dep(...) arguments
would fail the guard even with the dependency correctly pinned. Matches
the existing _rules_cc_bazel_dep_version() approach in
ci_windows_cppopts_test.py: parse the whole call body and find both
fields independently. Confirmed the new reordered-args test fails against
the old pattern (standalone repro) before the fix.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Addressed in ccf2a1f: `_toolchains_llvm_bazel_dep_version()` now parses the whole `bazel_dep(...)` call body and finds `name`/`version` independently, matching `_rules_cc_bazel_dep_version()` in `ci_windows_cppopts_test.py`. Added a reordered-args test; confirmed it fails against the old pattern (standalone repro) before the fix.
Same gap review caught on the toolchains_llvm guard in #423: the inline
regex only matched "name" immediately followed by "version", so reordered
or multiline bazel_dep(...) arguments would fail the guard even with the
dependency correctly pinned. Extracted _apple_support_bazel_dep_version(),
parsing the whole call body and finding both fields independently, matching
_rules_cc_bazel_dep_version() in ci_windows_cppopts_test.py. Confirmed the
new reordered-args test fails against the old inline pattern (standalone
repro) before the fix.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The [^)]*)\) regex stops at the first ")" even when it appears inside a
string literal, a "#" comment, or a nested call -- a leading comment like
"# see upstream fix (closes #791)" before the real args would truncate the
match and make _toolchains_llvm_bazel_dep_version()/
_has_toolchains_llvm_override() fail or return False despite the file being
correct. _iter_call_bodies() replaces both regexes with a character scanner
that tracks string/comment state and paren depth, so the body always spans
to its true matching ")". Added a test with a ")" in a leading comment for
each helper; confirmed both fail against the old regex (standalone repro)
before the fix.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Addressed in 1a817e8. Both `_toolchains_llvm_bazel_dep_version()` and `_has_toolchains_llvm_override()` now use `_iter_call_bodies()`, a character-by-character scanner that tracks string-literal/comment state and paren depth, instead of `[^)]*)\)`. Added a test for each with a `)` inside a leading comment (e.g. `# see upstream fix (closes #791)`) before the real args; confirmed both fail against the old regex (standalone repro) before the fix.
24/24 `//python/...` tests pass.
Note: the same `[^)]*)\)` pattern — including in the `_rules_cc_bazel_dep_version`/`_rules_cc_override_version` helpers in `ci_windows_cppopts_test.py` that earlier rounds pointed to as the model to match — has this identical truncation issue. That file is outside this PR's diff, so I haven't touched it; flagging in case you want it fixed too, either here or separately.
Same bug review found on the toolchains_llvm guard in #423: [^)]*)\)
stops at the first ")" even inside a string, comment, or nested call, so
a leading comment like "# fixes Xcode 27 crosstool warnings (see docs)"
before the real args would truncate the match. _iter_call_bodies()
replaces both regexes with a character scanner tracking string/comment
state and paren depth. Added a test with a ")" in a leading comment for
each helper; confirmed both fail against the old regex (standalone repro)
before the fix.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This pattern also matches call text inside comments, so the guard can inspect declarations that Bazel ignores. For example, a commented bazel_dep(... version = "9.9.9") before the real 1.8.0 dependency makes the minimum-version assertion pass, while a commented override makes _has_toolchains_llvm_override return true. Restrict matches to top-level, non-comment lines (and add a commented-call case) so this CI guard reflects the effective MODULE configuration.
_iter_call_bodies() located each call with a plain regex search for
"name(", which matches that text inside a "#" comment just as readily as
live code -- a commented-out "bazel_dep(... version = \"9.9.9\")" before
the real dependency made the version guard read the dead value, and a
commented-out override made _has_toolchains_llvm_override return a false
positive. Rewritten as a single linear scan that tracks string/comment
state continuously, so a call name is only recognized outside both.
Confirmed both failure modes against the old scanner (standalone repro)
before the fix, and added a dedicated commented-out-call test for each
helper.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Addressed in 58d3db7. `_iter_call_bodies()` previously located each call via a plain regex search for `name(`, which matches that text inside a `#` comment just as readily as live code — confirmed both failure modes with a standalone repro: a commented-out `bazel_dep(... version = "9.9.9")` before the real dependency made the version guard read the dead value, and a commented-out override made `_has_toolchains_llvm_override` return a false positive.
Rewrote it as a single linear scan that tracks string/comment state continuously across the whole text, so a call name is only recognized outside both. Added a dedicated commented-out-call test for each helper.
24/24 `//python/...` tests pass. Will mirror this to #424 as well.
Same bug fixed on the toolchains_llvm guard in #423: _iter_call_bodies()
located each call with a plain regex search for "name(", which matches
that text inside a "#" comment too -- a commented-out "bazel_dep(...
version = \"9.9.9\")" before the real dependency made the version guard
read the dead value, and a commented-out override made
_has_apple_support_override return a false positive. Rewritten as a
single linear scan that tracks string/comment state continuously.
Confirmed both failure modes against the old scanner (standalone repro)
before the fix, and added a dedicated commented-out-call test for each
helper.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The reason will be displayed to describe this comment to others. Learn more.
🔵 Needs a closer look
Collection-based positional expressions can bypass the new override guard.
0 open findings
Previously missed (1)
In code that hasn't changed since last review
Record unresolved top-level list positional expressions
python/tests/ci_msan_test.py:280
A list expression can be the first positional module_name and resolve to the guarded module, but this branch descends without recording an unresolved positional value. For example, archive_override(["toolchains_llvm"][0], strip_prefix = "x") currently makes _has_toolchains_llvm_override() return False, bypassing the guard. Mark a top-level list expression unresolved just as the ( branch does.
This issue also appears on line 285 of the same file.
Same gap as the parenthesized-positional fix, for the "[" and "{"
branches: a top-level list or dict expression opening the first
positional argument (e.g. ["toolchains_llvm"][0]) was descended into
without ever recording _POSITIONAL_KEY, so module_name read as absent
and _has_toolchains_llvm_override() missed the override.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Addressed the latest Copilot finding: list/dict positional expressions.
Same gap as the previous parenthesized-positional fix, for the "[" and "{" branches: a top-level list or dict expression opening the first positional argument (e.g. `["toolchains_llvm"][0]`) was descended into without ever recording `_POSITIONAL_KEY`, so `module_name` read as absent and `_has_toolchains_llvm_override()` missed the override. Reproduced directly against the Copilot-supplied example (returned `False`).
Fixed by applying the same "mark unresolved before descending" guard to both the `[` and `{` branches (the review noted the gap recurs at both), plus two regression tests — list and dict — and confirmed the sentinel actually fires in each case, and that a genuine literal positional value is unaffected (425e2fd).
Mirrors the same fix on #423: a top-level list or dict expression
opening the first positional argument (e.g. ["apple_support"][0]) was
descended into without ever recording _POSITIONAL_KEY, so module_name
read as absent and _has_apple_support_override() missed the override.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Mirrors the same fix on #424: the RHS lookahead after "ident =" only
skipped whitespace, so a comment on its own line between "=" and the
literal (valid Starlark formatting) made the RHS look non-literal:
module_name = # note\n "rules_cc" was marked _UNRESOLVED and falsely
tripped _has_toolchains_llvm_override() for an unrelated module's
override, and the same shape on bazel_dep's version returned the
sentinel instead of the actual version string.
Factored the comment-skipping loop already in _is_complete_literal()
out into _skip_ws_and_comments(), and used it for the RHS lookahead too.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Proactively mirrored a fix from #424's identical `_iter_call_kwargs()`: the RHS lookahead after `ident =` only skipped whitespace, so a comment on its own line between `=` and the literal — valid Starlark formatting — made the RHS look non-literal. `module_name =\n # pin past a fix\n "apple_support"` was marked `_UNRESOLVED`, falsely tripping `_has_toolchains_llvm_override()` for an unrelated module's override, and the same shape on `bazel_dep`'s `version =` returned the sentinel instead of the actual version string.
Factored the comment-skipping loop already in `_is_complete_literal()` out into a shared `_skip_ws_and_comments()`, and used it for the RHS lookahead too (ed28e60). Mirrored two regression tests.
Mirrors the same fix on #424: the outer call-name scan only recognized
a bare "name(" call, so a valid Starlark call through a parenthesized
callable reference -- "(archive_override)(module_name =
\"toolchains_llvm\", ...)", equivalent to the direct form since
grouping parens around any expression are legal and the result can be
called immediately -- didn't match textually and let the override
bypass _has_toolchains_llvm_override().
Added _match_parenthesized_call() to recognize "(" name ")(" as an
alternate way to find the same call, wired into the outer scan
alongside the existing direct-call match.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Proactively mirrored a fix from #424's identical `_iter_call_kwargs()`: the outer call-name scan only recognized a bare `name(` call, so a valid Starlark call through a parenthesized callable reference — `(archive_override)(module_name = "toolchains_llvm", ...)`, equivalent to the direct form since grouping parens around any expression are legal and the result can be called immediately — didn't match textually and let the override bypass `_has_toolchains_llvm_override()`.
Added `_match_parenthesized_call()` to recognize `"(" name ")("` as an alternate way to find the same call, wired into the outer scan alongside the existing direct-call match, plus two mirrored regression tests (29c5d11).
_decode_escape() had no case for a backslash immediately followed by
an actual LF/CRLF line break in the source (as opposed to the
two-character "\n" escape for a newline value), so it fell through to
the default "leave as literal backslash + next character" branch. A
module_name literal split across two source lines by a trailing
backslash -- valid Starlark, which drops the continuation entirely --
kept both the backslash and the newline character, producing a value
that never equals the real module name and letting the override
bypass the fail-closed guard.
Added LF and CRLF line-continuation decoding (both collapse to "").
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Addressed the latest Copilot finding: string line continuations.
`decode_escape()` had no case for a backslash immediately followed by an actual LF/CRLF line break in the source (as opposed to the two-character `\n` escape for a newline value), so it fell through to the default "leave as literal backslash + next character" branch. Reproduced the example directly: `archive_override(module_name = "toolchains` + backslash + newline + `llvm", ...)` returned `False` before the fix (should be `True`, since Starlark drops the continuation entirely and the literal resolves to `toolchains_llvm`).
Added LF and CRLF line-continuation decoding, both collapsing to `""` (3dc70b2). Verified both forms resolve correctly, confirmed the distinct two-character `\n` escape (an actual newline value, not a continuation) still behaves differently and correctly, and the unaffected plain-literal case is unchanged. Two regression tests (LF, CRLF).
Mirrors the same fix on #423: _decode_escape() had no case for a
backslash immediately followed by an actual LF/CRLF line break in the
source (as opposed to the two-character "\n" escape for a newline
value), so it fell through to the default "leave as literal backslash
+ next character" branch. A module_name literal split across two
source lines by a trailing backslash -- valid Starlark, which drops
the continuation entirely -- kept both the backslash and the newline
character, producing a value that never equals the real module name
and letting the override bypass the fail-closed guard.
Added LF and CRLF line-continuation decoding (both collapse to "").
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Handle comments when scanning grouped callable overrides
python/tests/ci_msan_test.py:223
A valid grouped call can still bypass this guard when the grouping contains a comment, e.g. (archive_override # comment\n)(module_name = "toolchains_llvm", ...). Starlark ignores that comment, but _skip_ws stops at #, so this scanner returns False and permits the override. Skip comments around the grouped callable tokens as well, and add this case to the grouped-call regression test.
Two fixes:
1. _match_parenthesized_call() used _skip_ws() around the grouped
callable name's tokens, so a comment inside the grouping -- e.g.
"(archive_override # note\n)(module_name = \"toolchains_llvm\",
...)", which Starlark ignores the comment in and treats identically
to the plain "(name)(" form -- made this scanner miss the call and
let the override bypass the guard. Switched to
_skip_ws_and_comments().
2. Mirrored from #424: module_name = r"rules_cc" (a raw string literal,
valid Starlark) was read as a bare identifier "r" followed by a
separate quoted string, falling through to the bare-identifier
"unresolved" path, so the guard incorrectly returned True (failed
closed) for an override on a completely unrelated module -- a
false-positive CI failure, not a guard bypass, but still wrong.
Added _is_raw_string_start()/_skip_raw_string()/_skip_any_string()
(raw strings only give "\<quote>" special meaning; every other
backslash, including one before a newline, is kept completely
literal) and wired _skip_any_string() into the keyword-RHS and
first-positional checks.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Addressed the latest Copilot finding, plus proactively mirrored #424's raw-string fix.
Finding (comment in grouped call): `_match_parenthesized_call()` used `_skip_ws()` around the grouped callable name's tokens, so a comment inside the grouping — `(archive_override # note\n)(module_name = "toolchains_llvm", ...)`, which Starlark ignores identically to the plain `(name)(` form — made this scanner miss the call and let the override bypass the guard. Reproduced directly (returned `False`, should be `True`). Switched to `_skip_ws_and_comments()`.
Mirrored from #424: `module_name = r"rules_cc"` (a raw string literal) was read as a bare identifier `r` + a separate quoted string, falling through to the "unresolved" path and incorrectly failing closed for an unrelated module's override. Added `_is_raw_string_start()`/`_skip_raw_string()`/`_skip_any_string()` and wired them into the keyword-RHS and first-positional checks (dedcc23).
Verified both fixes directly (including that neither false-triggers for an unrelated module), plus the escaped-quote-inside-a-raw-string edge case resolves to its true value rather than matching. Six regression tests added (one for the comment fix, five for the raw-string fix, mirroring #424).
Mirrors the same fix on #423: _match_parenthesized_call() used
_skip_ws() around the grouped callable name's tokens, so a comment
inside the grouping -- e.g. "(archive_override # note\n)(module_name
= \"apple_support\", ...)", which Starlark ignores the comment in and
treats identically to the plain "(name)(" form -- made this scanner
miss the call and let the override bypass the guard. Switched to
_skip_ws_and_comments().
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The reason will be displayed to describe this comment to others. Learn more.
🔵 Needs a closer look
The new scanner incorrectly rejects valid unrelated overrides using raw triple-quoted Starlark strings.
0 open findings
Previously missed (1)
In code that hasn't changed since last review
Handle raw triple-quoted strings in override scanner
python/tests/ci_msan_test.py:170
Starlark permits raw triple-quoted literals, but this scanner deliberately handles only single-quote delimiters. As a result, a valid unrelated override such as archive_override(module_name = r"""apple_support""", ...) is parsed as _UNRESOLVED, so _has_toolchains_llvm_override() returns true and fails this guard even though no LLVM override exists. Extend the raw-string scanner to recognize a three-quote delimiter (and add cases for both an unrelated override and the bazel_dep name).
Mirrors the same fix on #424: _skip_raw_string() only handled a
single-character delimiter, so module_name = r"""apple_support"""
stopped at the first lone quote inside the triple-quote run, leaving
the value unresolved. The fail-closed guard then incorrectly returned
True for an override on a completely unrelated module -- a
false-positive CI failure, same class of bug as the earlier
single-quote raw-string fix.
Extended _skip_raw_string() to match a triple-quote delimiter as the
3-character sequence, the same way _skip_string() already does for
ordinary strings, while keeping the raw "\<quote>" escape rule.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Addressed the latest Copilot finding (this is the same bug independently found on both PRs — the identical `_skip_raw_string()`): raw triple-quoted strings.
`module_name = r"""apple_support"""` stopped at the first lone quote inside the triple-quote run, leaving the value unresolved and making the fail-closed guard incorrectly return `True` for an override on a completely unrelated module. Extended `_skip_raw_string()` to match a triple-quote delimiter as the 3-character sequence, the same way `_skip_string()` already does for ordinary strings, keeping the raw `<quote>` escape rule (993d99c). Added both regression cases the finding asked for — an unrelated override and the `bazel_dep` name — plus one confirming `toolchains_llvm` via a raw triple-quote still matches.
The reason will be displayed to describe this comment to others. Learn more.
🔵 Needs a closer look
The override scanner misses valid nested callable grouping, allowing the prohibited override to bypass its guard.
0 open findings
Previously missed (1)
In code that hasn't changed since last review
Recursively unwrap grouped callables when detecting overrides
python/tests/ci_msan_test.py:353
This handles only one layer of callable grouping. Valid Starlark such as ((archive_override))(module_name = "toolchains_llvm", ...) therefore produces no match, so _has_toolchains_llvm_override() returns False and the new guard allows the override it is intended to reject. Recursively unwrap grouped callables (or use a Starlark parser) rather than special-casing exactly (name)(...).
🧠 Review effort: Balanced
This branch has not been deployed
No deployments
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
toolchains_llvmfrom 1.8.0 to 1.11.2 inMODULE.bazel.archive_overridepinning an unreleased commit (merge of upstream #791, which dropped an unused-stdlib=libc++flag that broke this project's Linux-Werrorbuilds). That fix shipped in the 1.9.0 release — verified by diffingcc_toolchain_config.bzlat that tag against the pinned commit (identical) — so a plainbazel_deppin replaces it.llvm_versions = "21.1.8"(what this project pins for all three platforms) is still a catalogued archive at 1.11.2 (toolchain/distributions/github.jsonc).extra_link_flags/extra_link_libsmechanism this project relies on for the macOS 27 SDK / Linux native-linker overrides (see Release v3.1.1: fix macOS 27 SDK / Xcode 27 build break #417/Guard and document the macOS/Linux native-linker override and ThinLTO #418) is unchanged incc_toolchain_config.bzl— still appended after the toolchain-default--ld-path, so "last flag wins" still holds.linker = {...}catalogue attribute (e.g."darwin-aarch64": "auto") that's a more idiomatic way to express exactly the override this project hand-rolled withextra_link_flags— the release notes even call out "LLVM 23 on macOS still needs the nativeautolinker override for the known SDK/TAPI issue," which is our exactarm64e.x1problem. Migrating to it is a worthwhile follow-up, but it's a mechanism change, not a side effect of a version bump, so I left it out of scope here.ci_msan_test's guard: it now checks thebazel_depversion directly and that no override targetstoolchains_llvm, using the same full-call-body regex approach as theapple_supportguard in Bump apple_support to 2.10.1, drop Xcode 27 crosstool patches #421 (avoids the "module_name must be the next line" fragility flagged there).Test plan
Run on this macOS 27 / Xcode 27 host — exactly the scenario the original native-linker fix targets:
bazelisk test //python:ci_msan_test— red against the pre-bump 1.8.0 + override state (verified viagit stash), green afterbazelisk test //...— 104/104 passbazelisk test --config=asan //library/tests/system/...— 22/22 passbazelisk test --config=tsanand--config=ubsan //library/tests/system:worker_context_reuse_test— pass--config=msanis Linux-only and can't run on this host;ci_msan_test's config-wiring checks pass, and a--nobuildanalysis probe of its toolchain fails identically before and after this bump (pre-existing macOS-host limitation, not a regression) — real msan verification happens on Linux CI for this PR🤖 Generated with Claude Code