Repository navigation
Conversation
Adds an optional `sysroot` tag to the `toolchains` module extension,
configuring an external sysroot (e.g. a macOS SDK) for the zig cc
toolchains targeting a given OS ("linux"/"windows"/"macos"). Entirely
optional and backward-compatible: with no `sysroot` tag, toolchains
behave exactly as before.
sysroot(os, path, include_dirs, copts, linkopts, files):
- path/include_dirs are registered as builtin_sysroot/
cxx_builtin_include_directories, so Bazel's header-inclusion
validation accepts headers found under the sysroot without
forcing them onto the compiler's -I search path ahead of the
toolchain's own libc++ headers (include_dirs are searched with
-idirafter, after the toolchain's own headers, not -I).
- Bazel's implicit `--sysroot=<path>` (normally auto-appended once
builtin_sysroot is set) is suppressed by overriding the built-in
"sysroot" feature with an empty one; callers instead pass
--sysroot/-isysroot to the *compiler* explicitly via copts, and
SDK search paths (-F/-L) to the *linker* via linkopts. This keeps
consumers that invoke a raw linker directly (rules_rust's
rust-lld, which never goes through zig cc) unaffected by a
--sysroot= flag their linker doesn't understand.
- files is a label (string) of a filegroup that stages the
sysroot's contents into every compile/link action that needs it
but doesn't otherwise depend on it (e.g. a BCR module's own
compile actions) — Bazel does not create the external repo's
symlink in the sandbox otherwise, and the -I/-isysroot paths
would dangle.
Per README's "OSX: sysroot" section, the sysroot itself must come
from an http_archive (or another repo rule producing an equivalent
filegroup) — this does not fetch or redistribute Apple's SDK.
Documents both a prebuilt-mirror-tarball source and an Apple-CDN
.pkg-download source in the README, since http_archive's `type =
"pkg"` handles the latter the same way it handles a .tar.gz.
Known limitation: pure zig-cc `-framework` linking of a cross target
(darwin from a non-macOS host) is still limited — zig resolves the
top-level .tbd but its absolute /usr/lib reexports aren't re-rooted
at the sysroot (ziglang/zig#10299). Consumers with a raw non-zig-cc
linker in the loop (rust-lld, or a cmake-driven rules_foreign_cc
build) aren't affected.
Verified end-to-end in a real downstream project building a
cgo-enabled Go binary that needs macOS's <resolv.h> (not in zig's own
curated header subset) alongside Rust binaries linked via rust-lld.
ci/lint runs buildifier -mode fix then asserts a clean git diff. The sysroot changes had two formatting violations: unsorted kwargs in the declare_cc_toolchains() call in BUILD.sdk.bazel, and a missing blank line separating the isysroot block from the following comment in cc_toolchains.bzl.
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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
Implements configurable external sysroot support for the zig cc toolchains, as invited by the README's "OSX: sysroot" section:
Adds an optional
sysroottag to thetoolchainsmodule extension. Fully backward-compatible — with nosysroottag, toolchains behave exactly as before.Design notes
path/include_dirsare registered asbuiltin_sysroot/cxx_builtin_include_directories, so Bazel's header-inclusion validation accepts headers found under the sysroot without putting the whole SDK ahead of the toolchain's own libc++ headers on the-Isearch path.include_dirsare searched via-idirafter(lowest priority, after the toolchain's own headers) — a plain-Iwould shadow libc++'s own<cstdio>etc. with the SDK's C headers and break C++.--sysroot=<path>Bazel normally auto-appends oncebuiltin_sysrootis set gets suppressed (via an empty override of the built-in"sysroot"feature). Consumers with a raw, non-zig-cc linker in their link step (e.g.rules_rust'srust-lld, invoked directly to work around zig's own-oso_prefixgap) would otherwise choke on a--sysroot=flag their linker doesn't understand. Instead,copts/linkoptspass--sysroot/-isysroot/-F/-Lexplicitly, only to actions that actually go through zig cc.filesstages the sysroot into actions that need it but don't otherwise declare a dependency on it (e.g. a BCR module's own compile action) — Bazel won't create the external repo's sandbox symlink otherwise, and the-I/-isysrootpaths would dangle.Two usage examples
Both fetch the SDK via
http_archive, per the README's constraint — they differ only in where the archive comes from.1. A prebuilt redistributable mirror (
joseluisq/macosx-sdks):2. Apple's own CDN, downloading the Command Line Tools
.pkgdirectly — the pattern openai/codex uses for its own (unrelated, LLVM-based) toolchain.http_archive'stype = "pkg"extracts a.pkgpayload the same way it extracts a.tar.gz:(Note:
openai/codexitself doesn't usehermetic_cc_toolchain— it depends on a separate bzlmod module namedllvm(hermeticbuild/hermetic-llvm) with its ownosx.from_archiveextension for the same "pull the SDK from Apple's CDN into a Bazel repo" idea. Cited here only as prior art for the download source, not as an existinghermetic_cc_toolchainconsumer.)Known limitation
Pure zig-cc
-frameworklinking of a cross target (e.g.aarch64-macos-nonefrom a non-macOS host) is still limited — zig resolves the top-level.tbdbut its absolute/usr/libreexports aren't re-rooted at the sysroot (ziglang/zig#10299). This doesn't affect consumers with a raw non-zig-cc linker in the loop (rust-lld, or a cmake-drivenrules_foreign_ccbuild).Testing
Verified end-to-end in a real downstream project: a cgo-enabled Go binary needing macOS's
<resolv.h>(not in zig's own curated header subset) built alongside Rust binaries that link viarust-lld— both consuming the same registered toolchain, with and without thesysroottag set, confirming the feature is a strict opt-in with no effect on existing (non-macOS, no-sysroot) targets.