feat: support aarch64 hosts via a host_arch attribute - #236
Open
janickm wants to merge 1 commit into
Open
Conversation
Owner
|
Thanks for the contribution, can you rebase onto main, please? |
Every toolchain this module generates hardcodes
`exec_compatible_with = [linux, x86_64]` -- it is a string literal in the hub's
BUILD template, while target_compatible_with beside it is a format field. So on
an aarch64 host Bazel matches no cc toolchain at all and every C/C++ action fails
resolution, not just cross-compiles.
The binaries to fix that already exist: gcc-builds has published `-host-aarch64`
archives since 08072026, covering aarch64, armv7 and x86_64 targets for every GCC
version pinned to 08072026 or later (14.3.0, 15.2.0, 16.1.0 and 16.2.0). Only the
Starlark wiring was missing.
`host_arch` names the architecture the toolchain binaries RUN on. It defaults to
`rctx.os.arch`, so a native build on either architecture needs no configuration,
and it drives three things:
- which archive is fetched, via a host dimension on AVAILABLE_GCC_VERSIONS;
- `exec_compatible_with`, now a templated hub attribute defaulting to
`[linux, {host_arch}]`, mirroring target_compatible_with;
- the builtin include layout.
That last one was a latent bug. A NATIVE build lays libstdc++ out flat
(`include/c++/<version>`) while a CROSS build nests it under the target triple,
and the existing code keyed that on `target_arch == x86_64` -- correct only
because every published build was x86_64-hosted. It is now keyed on
`host_arch == target_arch`, which is what the archives actually do: the
aarch64-hosted aarch64 build is flat, and the aarch64-hosted x86_64 one is
nested. Getting this wrong is quiet, because a nonexistent -isystem directory is
ignored and only surfaces later as a missing <string>.
Backwards compatible. Existing entries keep their exact URLs and digests, and the
binary prefix needs no host handling because _detect_binary_prefix already probes
the extracted archive. A hand-written `gcc_versions` in the old
`{version: {target: {url, sha256}}}` shape still works and is read as
x86_64-hosted; combining it with a non-x86_64 host fails with a message saying
what to write instead.
Verified all four host/target combinations (plus aarch64-hosted armv7) resolve,
fetch the archive whose ELF machine matches their host_arch, and declare only
include directories that exist -- and that the x86_64-hosted paths are unchanged.
//tests/host_arch asserts the aarch64-hosted compiler is an ARM ELF by reading
e_machine, so it runs anywhere; it fails if pointed at the x86_64-hosted cross
toolchain. It is skipped for 12.5.0 and 13.4.0, whose releases publish no
aarch64-hosted build, as //tests/lld is for the versions built without lld.
janickm
force-pushed
the
feat/aarch64-host-toolchains
branch
from
August 12, 2026 09:18
d3ee3f7 to
3176328
Compare
Author
|
Rebased onto
Re-verified everything the workflow runs on the rebase: |
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.
Problem
Every toolchain this module generates hardcodes
exec_compatible_with = [linux, x86_64]--it is a string literal in the hub's BUILD template, while
target_compatible_withrightbeside it is a format field:
So on an aarch64 host Bazel matches no cc toolchain at all -- every C/C++/Fortran action
fails with
No matching toolchains found for @rules_cc//cc:toolchain_type, not justcross-compiles.
The binaries to fix it already exist. Since
08072026, gcc-buildspublishes a
-host-aarch64archive for every target it builds, so all four GCC versionscurrently pinned to
08072026or later (14.3.0, 15.2.0, 16.1.0, 16.2.0) have aarch64-hostedbuilds for aarch64, armv7 and x86_64 targets. Only the Starlark wiring was missing.
Change
A
host_archattribute names the architecture the toolchain binaries run on. Itdefaults to
rctx.os.arch, so a native build on either architecture needs no configuration,and it drives:
AVAILABLE_GCC_VERSIONSgains a host dimension:{version: {target_arch: {host_arch: {url, sha256}}}}.exec_compatible_with-- now a templated hub attribute defaulting to["@platforms//os:linux", "@platforms//cpu:{host_arch}"], mirroringtarget_compatible_with.The include layout was a latent bug
A native build lays libstdc++ out flat (
include/c++/<version>) while a cross buildnests it under the target triple (
<triple>/include/c++/<version>). The existing code keyedthat on
target_arch == ARCHS.x86_64, which was correct only because every published buildwas x86_64-hosted. It is now keyed on
host_arch == target_arch, which is what the archivesactually do -- verified by listing all five tarballs:
Getting this wrong is quiet: a nonexistent
-isystemdirectory is ignored, so it surfacesmuch later as a missing
<string>naming no path at all.Note this needs no
binary_prefixhandling:_detect_binary_prefix(added in #238) probesthe extracted archive, and every aarch64-hosted archive ships a prefixed
bin/<triple>-as,so detection already gets it right. Confirmed for all five combinations.
Backwards compatibility
Existing entries keep their exact URLs and digests -- asserted mechanically: all 18
(url, sha256)pairs onmainappear verbatim, and the 12 added ones are all-host-aarch64archives.A hand-written
gcc_versionsin the old{version: {target: {url, sha256}}}shape stillworks and is read as x86_64-hosted. Combining it with a non-x86_64 host fails with a message
saying what to write instead:
and asking for a host that has no published build:
Verification
Rebased onto
main(ed8c2ab), so this now sits on top of the hub/per-version split from#239 and the prefix detection from #238.
Everything the CI workflow runs passes:
bazel test //...under both--config bzlmodand--config workspace(14 tests).gcc_versionsmatrix:12.5.0 13.4.0 14.3.0 15.2.0 16.1.0 16.2.0.--config lld, andbazel coverage.USE_BAZEL_VERSION=9.1.0 bazel test -- //... -//docs/....aarch64_linux,armv7_linuxandx86_64_linux.All host/target combinations were checked to fetch, resolve and declare the right
constraints -- that the compiler binary's ELF machine type matches its
host_arch, thatthe binary prefix is detected correctly, and that every declared builtin include
directory actually exists on disk:
exec_compatible_withtarget_compatible_withx86_64-linux-aarch64-linux-aarch64-linux-x86_64-linux-arm-linux-gnueabihf-The two x86_64-hosted rows are unchanged from before this PR.
//tests/host_archasserts the aarch64-hosted compiler is an ARM ELF by readinge_machineat offset 18, so it needs no ARM hardware and runs on any host. Confirmed it fails when
pointed at the x86_64-hosted cross toolchain (
e_machine 0x3e00, want 0xb7), so it is not atest that cannot fail. The toolchain is declared but deliberately not registered, since
its binaries cannot execute on x86_64 CI. It is marked incompatible for 12.5.0 and 13.4.0,
whose releases publish no aarch64-hosted build, the same way
//tests/lldhandles theversions built without lld -- being unanalyzed, the archive that does not exist is never
fetched.
Notes
bazel run //docs:update;//docs:update_testpasses.docs/updating-gcc-builds.mdsaid the-host-aarch64variants "are ignored. Filter themout" -- no longer true, so it now documents the host dimension, and the native-vs-cross
include layout under "Handling tarball layout changes".
docs/README.mdgains a short "Choosing the host architecture" section.host_archisvalues = ["", "aarch64", "x86_64"]; armv7 is a target only./ GB10). I validated it against that repo by pointing it at this branch: with
host_archthe local workaround -- a
use_repo_rulewrapper re-declaringtoolchain()with theright exec constraint, plus hand-written
gcc_versions,binary_prefixandincludes--deletes entirely and becomes one
gcc.toolchain(host_arch = "aarch64", ...)call. Itsfull test suite passes,
--config=arm64still resolves the x86_64-hosted cross toolchain,and with an aarch64 execution platform registered resolution picks the ARM-hosted one.