From dc30a37477e3b53b075552b8e90720ef3c9128c6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 25 Oct 2026 15:02:26 +0000 Subject: [PATCH 1/2] Initial plan From 9dd5e937b33947224e54afbb0d23cf35dbe8edb5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 25 Oct 2026 15:16:38 +0000 Subject: [PATCH 2/2] Use hermetic GCC with shared glibc 2.31 sysroots and enforce artifact ABI floor Co-authored-by: phlax <454682+phlax@users.noreply.github.com> --- .github/verify/artifacts/wee8.sh | 18 ++- .github/workflows/_release.yml | 15 +- .github/workflows/bazel.yml | 18 ++- bazel/MODULE.bazel | 29 +++- bazel/compile/test/BUILD.bazel | 48 +++++- bazel/compile/test/check_glibc.sh | 54 +++++++ bazel/compile/test/check_glibc_test.sh | 46 ++++++ bazel/compile/test/glibc_tool_fixture.sh | 24 +++ bazel/sysroot/BUILD | 25 +-- bazel/sysroot/README.md | 121 +++++++++------ bazel/sysroot/build_sysroot.sh | 70 +-------- bazel/sysroot/extensions.bzl | 7 +- bazel/sysroot/fs.bzl | 86 +++-------- bazel/sysroot/sysroot.bzl | 58 ++----- bazel/sysroot/test/BUILD | 15 +- .../test/build_sysroot_options_test.sh | 15 ++ bazel/sysroot/test/sysroot_test.bzl | 19 ++- bazel/toolchains/gcc/BUILD.bazel | 61 +++----- bazel/toolchains/gcc/extensions.bzl | 114 ++++++++++++++ bazel/toolchains/gcc/toolchain.bzl | 143 +++++++++--------- bazel/toolchains/gcc/toolchain_test.bzl | 29 ++++ bazel/v8/BUILD | 3 +- bazel/v8/extensions.bzl | 10 +- bazel/v8/package/BUILD | 6 +- bazel/v8/wee8_package.bzl | 14 +- bazel/v8/wee8_prebuilt.bzl | 14 +- bazel/v8/wee8_prebuilt_test.bzl | 1 + bazel/versions.bzl | 27 +--- 28 files changed, 677 insertions(+), 413 deletions(-) create mode 100755 bazel/compile/test/check_glibc.sh create mode 100755 bazel/compile/test/check_glibc_test.sh create mode 100755 bazel/compile/test/glibc_tool_fixture.sh create mode 100755 bazel/sysroot/test/build_sysroot_options_test.sh create mode 100644 bazel/toolchains/gcc/extensions.bzl create mode 100644 bazel/toolchains/gcc/toolchain_test.bzl diff --git a/.github/verify/artifacts/wee8.sh b/.github/verify/artifacts/wee8.sh index 12e1940c5e..28a5c85655 100644 --- a/.github/verify/artifacts/wee8.sh +++ b/.github/verify/artifacts/wee8.sh @@ -23,12 +23,12 @@ set -euo pipefail ARTIFACT_DIR="${1:?usage: wee8.sh }" -CHECK_STDLIB="$(dirname "$0")/../../../bazel/compile/test/check_stdlib.sh" +CHECK_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../../bazel/compile/test" && pwd)" +CHECK_STDLIB="${CHECK_DIR}/check_stdlib.sh" +CHECK_GLIBC="${CHECK_DIR}/check_glibc.sh" -# Keep in sync with WEE8_VARIANTS in bazel/v8/package/BUILD. aarch64+libstdcxx -# is deliberately absent: the gcc toolchain invokes /usr/bin/gcc directly and -# has no cross-compiler, so that combination cannot be built. -EXPECTED_COUNT=3 +# Keep in sync with WEE8_VARIANTS in bazel/v8/package/BUILD. +EXPECTED_COUNT=4 if [[ ! -d "${ARTIFACT_DIR}" ]]; then echo "FAIL: artifact dir '${ARTIFACT_DIR}' does not exist" @@ -37,7 +37,9 @@ fi shopt -s nullglob globstar -WORKDIR="$(mktemp -d)" +ARTIFACT_DIR="$(cd "${ARTIFACT_DIR}" && pwd)" +WORKDIR="${ARTIFACT_DIR}/.wee8-verify-$$" +mkdir "${WORKDIR}" trap 'rm -rf "${WORKDIR}"' EXIT found=0 @@ -101,6 +103,10 @@ for tarball in "${ARTIFACT_DIR}"/**/v8-wee8-*.tar.xz; do rc=1 fi + if ! BINARY="${lib}" bash "${CHECK_GLIBC}"; then + rc=1 + fi + rm -rf "${objdir}" "${lib}" done diff --git a/.github/workflows/_release.yml b/.github/workflows/_release.yml index 65aa7889b8..92c3cebcf5 100644 --- a/.github/workflows/_release.yml +++ b/.github/workflows/_release.yml @@ -63,10 +63,6 @@ on: fi done OUTPUT=$(printf '%s\n' "${_OUTPUT[@]}") - stdcc-versions: - type: string - default: | - ["base", "13"] template-version-update: type: string default: | @@ -197,7 +193,6 @@ jobs: current: ${{ steps.bins-deps.outputs.output }} shas: ${{ steps.bins-shas.outputs.shas }} glibc_versions: ${{ inputs.glibc-versions }} - stdcc_versions: ${{ inputs.stdcc-versions }} arches: ${{ inputs.arches }} glint_version: ${{ inputs.glint-version }} versions_file: ${{ inputs.bazel-versions-file }} @@ -212,7 +207,6 @@ jobs: | .current as $current | .glibc_versions as $glibc_versions | .arches as $arches - | .stdcc_versions as $stdccs | .san as $san | .glint_version as $glint_version | .versions_file as $versions_file @@ -250,16 +244,11 @@ jobs: else "" end] as $glint_updates | [$glibc_versions[] | . as $glibc - | $stdccs[] - | . as $stdcc - | (if $stdcc == "base" then "" - else "-libstdc++\($stdcc)" - end) as $stdcc_extra - | "sysroot-glibc\($glibc)\($stdcc_extra)-\($arch).tar.xz" as $sysroot + | "sysroot-glibc\($glibc)-\($arch).tar.xz" as $sysroot | ($shas[$sysroot] | split(":") | .[1]) as $new_sha - | $current.sysroot_hashes[$glibc][$stdcc][$arch] as $current_sha + | $current.sysroot_hashes[$glibc][$arch] as $current_sha | if $current_sha != $new_sha then "sed -i s/\($current_sha)/\($new_sha)/g \($versions_file)" else "" end] as $sysroot_updates diff --git a/.github/workflows/bazel.yml b/.github/workflows/bazel.yml index 6456046533..6ff5ab9645 100644 --- a/.github/workflows/bazel.yml +++ b/.github/workflows/bazel.yml @@ -148,8 +148,8 @@ jobs: verify-artifacts: # Asserts that uploaded artifacts actually contain what their filenames # claim. The build succeeding is not evidence of this: toolchain - # resolution can silently fall back to LLVM, and a gcc "cross" toolchain - # with no cross-compiler emits host-arch objects under a target-arch name. + # resolution can silently fall back to LLVM, and a misconfigured cross + # toolchain can emit host-arch objects under a target-arch name. # Both produce a green build and a plausible-looking tarball. # # Wee8, darwin libcxx, and macOS sysroot are verified below. @@ -209,6 +209,20 @@ jobs: @envoy_toolshed_jq//... //sysroot:sysroots //compile/test:libunwind_shared_test + - name: gcc + action: test + bazel_args: >- + --config=ci + --config=gcc + privileged: false + rbe: true + runner: ubuntu-24.04 + targets: >- + //compile/test:check_glibc_test + //compile/test:stdlib_libstdcxx_test + //compile/test:gcc_runtime_test + //toolchains/gcc:linux_x64_paths_test + //toolchains/gcc:linux_arm64_paths_test - name: x86-to-arm action: test bazel_args: >- diff --git a/bazel/MODULE.bazel b/bazel/MODULE.bazel index 82c049cf8f..97befdbe2c 100644 --- a/bazel/MODULE.bazel +++ b/bazel/MODULE.bazel @@ -133,7 +133,7 @@ use_repo(macos_sysroot_build_ext, "macos_sdk_pkg", "pkgutil_linux_amd64") # stays a dev dependency. wee8_prebuilt_ext = use_extension("//v8:extensions.bzl", "wee8_prebuilt_extension") wee8_prebuilt_ext.setup() -use_repo(wee8_prebuilt_ext, "wee8_prebuilt_aarch64", "wee8_prebuilt_x86_64", "wee8_prebuilt_x86_64_libstdcxx", "wee8_source") +use_repo(wee8_prebuilt_ext, "wee8_prebuilt_aarch64", "wee8_prebuilt_aarch64_libstdcxx", "wee8_prebuilt_x86_64", "wee8_prebuilt_x86_64_libstdcxx", "wee8_source") wee8_source_ext = use_extension("//v8:extensions.bzl", "wee8_prebuilt_extension", dev_dependency = True) wee8_source_ext.setup(source = "@v8//:wee8") @@ -168,7 +168,20 @@ use_repo(grcov_ext, "grcov") # glint_ext.setup(bins_release_version = "0.1.21") # use_repo(glint_ext, "glint") -# This needs to be before llvm to win in transitionsj +gcc = use_extension("//toolchains/gcc:extensions.bzl", "gcc_extension", dev_dependency = True) +gcc.toolchain( + name = "gcc_linux_x86_64", + arch = "x86_64", + sysroot = "@sysroot_linux_amd64//sysroot", +) +gcc.toolchain( + name = "gcc_linux_aarch64", + arch = "aarch64", + sysroot = "@sysroot_linux_arm64//sysroot", +) +use_repo(gcc, "gcc_linux_aarch64", "gcc_linux_x86_64") + +# This needs to be before llvm to win in transitions. register_toolchains( "//toolchains/gcc:linux_x64_toolchain", "//toolchains/gcc:linux_arm64_toolchain", @@ -195,11 +208,17 @@ llvm.cxx_cross_lib( # libgcc_s NEEDED entry. llvm.toolchain( name = "llvm_toolchain", - llvm_version = "22.1.8", extra_link_flags = { - "linux-aarch64": ["-rtlib=compiler-rt", "-unwindlib=libgcc"], - "linux-x86_64": ["-rtlib=compiler-rt", "-unwindlib=libgcc"], + "linux-aarch64": [ + "-rtlib=compiler-rt", + "-unwindlib=libgcc", + ], + "linux-x86_64": [ + "-rtlib=compiler-rt", + "-unwindlib=libgcc", + ], }, + llvm_version = "22.1.8", ) llvm.toolchain_root( name = "llvm_toolchain", diff --git a/bazel/compile/test/BUILD.bazel b/bazel/compile/test/BUILD.bazel index ccfc555ae6..fe5ffecf4f 100644 --- a/bazel/compile/test/BUILD.bazel +++ b/bazel/compile/test/BUILD.bazel @@ -23,6 +23,16 @@ clang_version_test( name = "clang_version_test", ) +sh_test( + name = "check_glibc_test", + size = "small", + srcs = ["check_glibc_test.sh"], + data = [ + "check_glibc.sh", + "glibc_tool_fixture.sh", + ], +) + sh_test( name = "libunwind_shared_test", size = "small", @@ -246,8 +256,7 @@ cc_binary( # # Note these are gated the *inverse* way from the unwind tests above: the # libstdcxx variant only runs when :gcc_build is set, and vice versa. Every -# other binary-inspecting test in this package is disabled under gcc, which is -# why the gcc leg had no output verification at all. +# other unwind-inspecting test in this package is disabled under gcc. # # Run with: # bazel test //compile/test:stdlib_libstdcxx_test --config=gcc @@ -255,10 +264,14 @@ sh_test( name = "stdlib_libstdcxx_test", size = "small", srcs = ["check_stdlib.sh"], - data = [":test_stdlib"], + data = [ + ":test_stdlib", + "@llvm_toolchain_llvm//:nm", + ], env = { "BINARY": "$(rootpath :test_stdlib)", "EXPECTED_STDLIB": "libstdcxx", + "NM": "$(rootpath @llvm_toolchain_llvm//:nm)", }, tags = ["manual"], target_compatible_with = select({ @@ -273,10 +286,14 @@ sh_test( name = "stdlib_libcxx_test", size = "small", srcs = ["check_stdlib.sh"], - data = [":test_stdlib"], + data = [ + ":test_stdlib", + "@llvm_toolchain_llvm//:nm", + ], env = { "BINARY": "$(rootpath :test_stdlib)", "EXPECTED_STDLIB": "libcxx", + "NM": "$(rootpath @llvm_toolchain_llvm//:nm)", }, tags = ["manual"], target_compatible_with = select({ @@ -285,3 +302,26 @@ sh_test( "//conditions:default": [], }), ) + +# Inspect the linked binary without executing it, including on cross builds. +sh_test( + name = "gcc_runtime_test", + size = "small", + srcs = ["check_glibc.sh"], + data = [ + ":test_stdlib", + "@llvm_toolchain_llvm//:nm", + "@llvm_toolchain_llvm//:readelf", + ], + env = { + "BINARY": "$(rootpath :test_stdlib)", + "CHECK_STATIC_RUNTIME": "true", + "NM": "$(rootpath @llvm_toolchain_llvm//:nm)", + "READELF": "$(rootpath @llvm_toolchain_llvm//:readelf)", + }, + tags = ["manual"], + target_compatible_with = select({ + "//compile:gcc_build": [], + "//conditions:default": ["@platforms//:incompatible"], + }), +) diff --git a/bazel/compile/test/check_glibc.sh b/bazel/compile/test/check_glibc.sh new file mode 100755 index 0000000000..f1ff0ae270 --- /dev/null +++ b/bazel/compile/test/check_glibc.sh @@ -0,0 +1,54 @@ +#!/bin/bash +# Inspect every archive member (or a linked ELF binary) for glibc > 2.31. +# Unversioned newer entry points must also be rejected in relocatable objects. +set -euo pipefail + +: "${BINARY:?BINARY must be set}" +NM="${NM:-nm}" +READELF="${READELF:-readelf}" + +# Capture complete output before matching: grep -q pipelines can SIGPIPE nm, +# and inspecting only one archive member misses incompatible references. +undefined="$("${NM}" -u "${BINARY}")" +if grep -E '(^|[[:space:]])(__isoc23_[^[:space:]@]*|__libc_single_threaded)(@[^[:space:]]*)?([[:space:]]|$)' <<< "${undefined}"; then + echo "FAIL: ${BINARY} references glibc entry points newer than 2.31" + exit 1 +fi + +versions="$("${READELF}" --version-info "${BINARY}")" +if ! awk ' + { + line = $0 + while (match(line, /GLIBC_[0-9]+(\.[0-9]+)+/)) { + version = substr(line, RSTART + 6, RLENGTH - 6) + count = split(version, parts, ".") + # Compare numeric components, not strings (2.9 < 2.31 < 2.100). + for (i = 1; i <= count; i++) { + limit = (i == 1 ? 2 : (i == 2 ? 31 : 0)) + if (parts[i] + 0 > limit) { + print "FAIL: GLIBC_" version " exceeds GLIBC_2.31" + failed = 1 + break + } + if (parts[i] + 0 < limit) { + break + } + } + line = substr(line, RSTART + RLENGTH) + } + } + END { exit failed } +' <<< "${undefined} +${versions}"; then + exit 1 +fi +echo "PASS: ${BINARY} requires no glibc newer than 2.31" + +if [[ "${CHECK_STATIC_RUNTIME:-false}" == "true" ]]; then + dynamic="$("${READELF}" -d "${BINARY}")" + if grep -E '\(NEEDED\).*(libstdc\+\+|libgcc_s)' <<< "${dynamic}"; then + echo "FAIL: ${BINARY} dynamically links the GCC C++ runtime" + exit 1 + fi + echo "PASS: no dynamic libstdc++ or libgcc_s dependencies" +fi diff --git a/bazel/compile/test/check_glibc_test.sh b/bazel/compile/test/check_glibc_test.sh new file mode 100755 index 0000000000..6f321c735b --- /dev/null +++ b/bazel/compile/test/check_glibc_test.sh @@ -0,0 +1,46 @@ +#!/bin/bash +set -euo pipefail +cd "$(dirname "${BASH_SOURCE[0]}")" +export BINARY=fixture.a +export NM="${PWD}/glibc_tool_fixture.sh" +export READELF="${NM}" +export CHECK_STATIC_RUNTIME=true + +assert_check() { + local expected="$1" + shift + local output status=0 + output="$(env "$@" bash ./check_glibc.sh 2>&1)" || status=$? + if [[ "${expected}" == "pass" && "${status}" -ne 0 ]] || + [[ "${expected}" == "fail" && "${status}" -eq 0 ]]; then + printf 'FAIL: expected %s for %s\n%s\n' "${expected}" "$*" "${output}" + exit 1 + fi + echo "PASS: expected ${expected} for $*" +} + +assert_check pass +assert_check pass FIXTURE_UNDEFINED='U memcpy@GLIBC_2.9' +assert_check pass FIXTURE_UNDEFINED='U memcpy@GLIBC_2.31.0' +assert_check pass FIXTURE_UNDEFINED='U memcpy@GLIBC_2.3.4' +assert_check pass FIXTURE_UNDEFINED='U ordinary_symbol' +assert_check pass FIXTURE_UNDEFINED='U prefixed__isoc23_strtol' +assert_check pass FIXTURE_UNDEFINED='U prefixed__libc_single_threaded' +assert_check pass FIXTURE_VERSIONS='Name: GLIBCXX_3.4.32 Name: GLIBC_2.31' +assert_check fail FIXTURE_UNDEFINED='U memcpy@GLIBC_2.32' +assert_check fail FIXTURE_UNDEFINED='U memcpy@GLIBC_2.100' +assert_check fail FIXTURE_UNDEFINED='U memcpy@GLIBC_2.31.1' +assert_check fail FIXTURE_UNDEFINED='U memcpy@GLIBC_3.0' +assert_check fail FIXTURE_VERSIONS='Name: GLIBC_2.9 Name: GLIBC_2.34' +assert_check fail FIXTURE_UNDEFINED='U __isoc23_strtol' +assert_check fail FIXTURE_UNDEFINED='U __isoc23_sscanf@GLIBC_2.38' +assert_check fail FIXTURE_UNDEFINED='U __libc_single_threaded' +assert_check fail FIXTURE_UNDEFINED='w __libc_single_threaded@GLIBC_2.32' +assert_check fail FIXTURE_UNDEFINED='U __libc_single_threaded@@GLIBC_2.32' +assert_check fail FIXTURE_LARGE=true FIXTURE_UNDEFINED='U __isoc23_strtoul' +assert_check pass FIXTURE_LARGE=true +assert_check fail FIXTURE_DYNAMIC='0x00000001 (NEEDED) Shared library: [libstdc++.so.6]' +assert_check fail FIXTURE_DYNAMIC='0x00000001 (NEEDED) Shared library: [libgcc_s.so.1]' +assert_check pass FIXTURE_DYNAMIC='0x00000001 (NEEDED) Shared library: [libc.so.6]' +assert_check fail FIXTURE_NM_FAIL=true +assert_check fail FIXTURE_READELF_FAIL=true diff --git a/bazel/compile/test/glibc_tool_fixture.sh b/bazel/compile/test/glibc_tool_fixture.sh new file mode 100755 index 0000000000..0ead7f64fa --- /dev/null +++ b/bazel/compile/test/glibc_tool_fixture.sh @@ -0,0 +1,24 @@ +#!/bin/bash +# Deliberately accept only the arguments used by the checker. +set -euo pipefail +[[ "$#" -eq 2 && "$2" == "fixture.a" ]] || exit 90 +case "$1" in + -u) + [[ "${FIXTURE_NM_FAIL:-false}" != "true" ]] || exit 91 + printf 'first.o:\n U memcpy\n' + if [[ "${FIXTURE_LARGE:-false}" == "true" ]]; then + for ((i = 0; i < 5000; i++)); do + printf ' U harmless_symbol_%s\n' "${i}" + done + fi + printf 'last.o:\n %s\n' "${FIXTURE_UNDEFINED:-U memcpy@GLIBC_2.31}" + ;; + --version-info) + [[ "${FIXTURE_READELF_FAIL:-false}" != "true" ]] || exit 92 + printf '%s\n' "${FIXTURE_VERSIONS:-No version information found.}" + ;; + -d) + printf '%s\n' "${FIXTURE_DYNAMIC:-There is no dynamic section in this file.}" + ;; + *) exit 93 ;; +esac diff --git a/bazel/sysroot/BUILD b/bazel/sysroot/BUILD index 0ffd05985a..f4b9ace6b3 100644 --- a/bazel/sysroot/BUILD +++ b/bazel/sysroot/BUILD @@ -17,8 +17,8 @@ so they must be explicitly requested. load("@aspect_bazel_lib//lib:tar.bzl", "mtree_mutate", "mtree_spec", "tar") load("@rules_shell//shell:sh_binary.bzl", "sh_binary") load("//:versions.bzl", "VERSIONS") -load(":macos_sysroot.bzl", "macos_sysroot_extract") load(":fs.bzl", "sysroot_daily_stamp", "sysroots") +load(":macos_sysroot.bzl", "macos_sysroot_extract") exports_files([ "build_sysroot.sh", @@ -29,9 +29,15 @@ exports_files([ "sysroot.bzl", ]) -ARCHES = ["amd64", "arm64"] -GLIBC = ["2.28", "2.31"] -STDCC = ["13", ""] +ARCHES = [ + "amd64", + "arm64", +] + +GLIBC = [ + "2.28", + "2.31", +] sh_binary( name = "build_sysroot", @@ -44,14 +50,13 @@ sysroot_daily_stamp() sysroots( arches = ARCHES, glibc = GLIBC, - stdcc = STDCC, ) macos_sysroot_extract( name = "sysroot_macos_arm64_src", - sdk_pkg = "@macos_sdk_pkg//:sdk_pkg", - pkgutil = "@pkgutil_linux_amd64//:pkgutil_bin", manifest = "manifests/sysroot-macos.txt", + pkgutil = "@pkgutil_linux_amd64//:pkgutil_bin", + sdk_pkg = "@macos_sdk_pkg//:sdk_pkg", sdk_prefix = VERSIONS["macos_sdk_pkg"]["sdk_prefix"], tags = ["manual"], ) @@ -64,18 +69,18 @@ mtree_spec( mtree_mutate( name = "sysroot_macos_arm64_mtree", - mtree = ":sysroot_macos_arm64_mtree_src", srcs = [":sysroot_macos_arm64_src"], + mtree = ":sysroot_macos_arm64_mtree_src", strip_prefix = "sysroot/sysroot_macos_arm64_src", tags = ["manual"], ) tar( name = "sysroot_macos_arm64", + srcs = [":sysroot_macos_arm64_src"], + out = "sysroot-macos-arm64.tar.xz", compress = "xz", mtree = ":sysroot_macos_arm64_mtree", - out = "sysroot-macos-arm64.tar.xz", - srcs = [":sysroot_macos_arm64_src"], tags = ["manual"], visibility = ["//visibility:public"], ) diff --git a/bazel/sysroot/README.md b/bazel/sysroot/README.md index 0ab6685f9e..2bea8ce41e 100644 --- a/bazel/sysroot/README.md +++ b/bazel/sysroot/README.md @@ -10,24 +10,53 @@ The workflow builds sysroots with the following configurations: - **Base:** Debian bullseye - **Compatibility:** Modern Linux distributions - **Kernel Headers:** 5.10+ (from bullseye-backports) -- **Variants:** - - Base: `sysroot-glibc2.31-{arch}.tar.xz` - - With libstdc++13: `sysroot-glibc2.31-libstdc++13-{arch}.tar.xz` +- **Archive:** `sysroot-glibc2.31-{arch}.tar.xz` ### glibc 2.28 (Older) - **Base:** Debian buster - **Compatibility:** Ubuntu 18.04, RHEL 8, and older distributions - **Kernel Headers:** 5.10+ (from buster-backports) -- **Variants:** - - Base: `sysroot-glibc2.28-{arch}.tar.xz` - - With libstdc++13: `sysroot-glibc2.28-libstdc++13-{arch}.tar.xz` +- **Archive:** `sysroot-glibc2.28-{arch}.tar.xz` -The base variant includes the `libgcc_s.so.1` runtime and an unversioned +Each sysroot includes the `libgcc_s.so.1` runtime and an unversioned `usr/lib//libgcc_s.so` linker script so literal `-lgcc_s` links resolve (needed by, for example, rustc). It does not include `libgcc.a` or libstdc++; -consumers should use `-rtlib=compiler-rt`. The libstdc++ variant does not get this -script; it uses the development linker script supplied by Debian's `libgcc-N-dev` -package instead. +Clang consumers should use `-rtlib=compiler-rt`. C++ standard-library headers and +libraries must come from the selected toolchain, not the sysroot. + +### GCC and LLVM share the base sysroot + +`--config=gcc` selects hermetic GCC 13.4.0; `--config=rbe-gcc` retains the +existing remote execution platforms. Both GCC target architectures execute on +Linux x86_64 (including aarch64 cross-compilation). GCC supplies its own +libstdc++, libgcc, libgcc_eh, and crtbegin/crtend objects; glibc supplies +crt1/crti/crtn from this sysroot. GCC links its C++ runtime statically. +LLVM continues to supply compiler-rt and libc++ from its own toolchain. + +The pinned archives come from +[f0rmiga/gcc-builds release 18082025](https://github.com/f0rmiga/gcc-builds/releases/tag/18082025), +the same source used by envoyproxy/envoy#39632. Its +[build recipe](https://github.com/f0rmiga/gcc-builds/blob/3fcca92fd993788a88af150cd4c885e4860e0055/Dockerfile) +builds the target runtime against glibc 2.26. The repository rule removes the +archive's bundled libc sysroot and explicitly uses toolshed's glibc 2.31 sysroot. +Replacement GCC archives **must build their target runtimes against glibc +<= 2.31**; changing `--sysroot` cannot lower the glibc requirement of an +already-built libstdc++. + +Downstreams can instantiate the downloads with `gcc_extension` from +`//toolchains/gcc:extensions.bzl`, using a `toolchain(name = ..., arch = +"x86_64" | "aarch64", sysroot = "@sysroot_linux_...//sysroot")` tag per target. +Each generated repository exports `:cc_toolchain`, `:config`, and `:files`. +The sysroot label must point directly into the `sysroot` package, not its +root-package alias. + +**Release TODO:** the next `bins-v*` release must regenerate both wee8 +libstdcxx archives and refresh `VERSIONS["wee8_sha256"][arch]["libstdcxx"]` +before downstream consumption (including envoyproxy/envoy#39632). Existing +x86_64 libstdcxx artifacts were built against host glibc 2.39 and are not +compatible with this floor; aarch64 libstdcxx remains an incompatible prebuilt +stub until its first archive/hash is published. `//v8:wee8_packages` builds +all four arch/stdlib combinations without consuming these prebuilts. ## Architecture Support @@ -80,26 +109,21 @@ To use these sysroots via a direct `.bzl` load: ```starlark load("@toolshed//bazel/sysroot:sysroot.bzl", "setup_sysroots") -# Use default glibc 2.31 base sysroot (without libstdc++) +# Use default glibc 2.31 sysroot setup_sysroots() -# Or opt in to libstdc++13 -setup_sysroots(stdcc_version = "13") - # Or use older glibc 2.28 for broader compatibility setup_sysroots( glibc_version = "2.28", ) -# Or use multiple sysroot configurations with name prefixes and variants +# Or use multiple sysroot configurations with name prefixes setup_sysroots( glibc_version = "2.31", - stdcc_version = "13", name_prefix = "new", ) setup_sysroots( glibc_version = "2.28", - stdcc_version = "13", name_prefix = "old", ) # This creates @new_sysroot_linux_amd64, @new_sysroot_linux_arm64, @@ -117,15 +141,10 @@ bazel_dep(name = "envoy_toolshed", version = "0.3.12") # Setup sysroots using the extension sysroot_ext = use_extension("@envoy_toolshed//bazel/sysroot:extensions.bzl", "sysroot_extension") -# Use default glibc 2.31 base sysroot (without libstdc++) +# Use default glibc 2.31 sysroot sysroot_ext.setup() -# Or opt in to libstdc++13: -# sysroot_ext.setup( -# stdcc_version = "13", -# ) - -# Or configure an older glibc base sysroot: +# Or configure an older glibc sysroot: # sysroot_ext.setup( # glibc_version = "2.28", # ) @@ -133,12 +152,10 @@ sysroot_ext.setup() # Or use multiple sysroot configurations with name prefixes: # sysroot_ext.setup( # glibc_version = "2.31", -# stdcc_version = "13", # name_prefix = "new", # ) # sysroot_ext.setup( # glibc_version = "2.28", -# stdcc_version = "13", # name_prefix = "old", # ) @@ -154,10 +171,20 @@ use_repo(sysroot_ext, "sysroot_linux_amd64", "sysroot_linux_arm64") The setup will automatically validate your configuration: - **Unsupported glibc versions** will fail with a clear error message -- **Incompatible combinations** (e.g., requesting a variant that doesn't exist) will fail +- **Unsupported architectures** will fail with a clear error message - **Missing hashes** (e.g., for unreleased configurations) will fail with a helpful message -All SHA256 hashes are centrally managed in `versions.bzl` for ease of maintenance. +All SHA256 hashes are centrally managed in `versions.bzl` as +`sysroot_hashes[glibc_version][arch]`. + +### Migrating existing configurations + +Sysroots no longer bundle libstdc++. Remove `stdcc_version` from repository-rule, +`setup_sysroots`, and module-extension calls, and remove `variant`, `ppa_toolchain`, +and `stdcc_version` arguments from `sysrootfs` calls. The script no longer accepts +`--variant`, `--ppa-toolchain`, or `--stdcc`. Use the unsuffixed sysroot build +targets below and supply any C++ standard library through the toolchain. +Existing unsuffixed archives and their SHA256 hashes are unchanged. ## Building Sysroots with Bazel @@ -165,22 +192,18 @@ You can build sysroots locally using Bazel. The builds are marked as `manual` so ### Available Build Targets -All sysroot build targets are in the `//bazel/sysroot` package: +All sysroot build targets are in the `//sysroot` package (from the `bazel/` directory): ```bash # Build ALL sysroots at once (from the bazel/ directory): cd bazel bazel build //sysroot:sysroots -# Or build specific sysroot variants: -bazel build //sysroot:sysroot_glibc2.31_amd64 -bazel build //sysroot:sysroot_glibc2.31_arm64 -bazel build //sysroot:sysroot_glibc2.31_libstdcxx_amd64 -bazel build //sysroot:sysroot_glibc2.31_libstdcxx_arm64 -bazel build //sysroot:sysroot_glibc2.28_amd64 -bazel build //sysroot:sysroot_glibc2.28_arm64 -bazel build //sysroot:sysroot_glibc2.28_libstdcxx_amd64 -bazel build //sysroot:sysroot_glibc2.28_libstdcxx_arm64 +# Or build specific sysroots: +bazel build //sysroot:sysroot_glibc231_amd64 +bazel build //sysroot:sysroot_glibc231_arm64 +bazel build //sysroot:sysroot_glibc228_amd64 +bazel build //sysroot:sysroot_glibc228_arm64 ``` The built sysroots will be in `bazel-bin/sysroot/` directory. @@ -196,14 +219,16 @@ bazel run //sysroot:build_sysroot -- \ --arch amd64 \ --glibc 2.31 \ --debian bullseye \ - --variant base \ - --output /tmp/mysysroot + --workdir "$PWD/sysroot-build" \ + --output "$PWD/sysroot-glibc2.31-amd64.tar.xz" # Keep specific directories (e.g., keep bin and sbin for debugging) bazel run //sysroot:build_sysroot -- \ --arch amd64 \ --glibc 2.31 \ --debian bullseye \ + --workdir "$PWD/sysroot-build" \ + --output "$PWD/sysroot-glibc2.31-amd64.tar.xz" \ --keep-dirs bin,sbin # Remove additional directories beyond the defaults @@ -211,6 +236,8 @@ bazel run //sysroot:build_sysroot -- \ --arch amd64 \ --glibc 2.31 \ --debian bullseye \ + --workdir "$PWD/sysroot-build" \ + --output "$PWD/sysroot-glibc2.31-amd64.tar.xz" \ --remove-dirs usr/games,usr/local # Skip cleanup entirely (keep everything) @@ -218,6 +245,8 @@ bazel run //sysroot:build_sysroot -- \ --arch amd64 \ --glibc 2.31 \ --debian bullseye \ + --workdir "$PWD/sysroot-build" \ + --output "$PWD/sysroot-glibc2.31-amd64.tar.xz" \ --skip-cleanup ``` @@ -253,7 +282,7 @@ The artifacts are uploaded to the release assets. ### Building for Release -To build all sysroot variants for a release, use the convenience target: +To build all sysroots for a release, use the convenience target: ```bash cd bazel @@ -264,11 +293,9 @@ bazel build //sysroot:sysroots Or build specific glibc versions: ```bash -# Build all glibc 2.31 variants -bazel build //sysroot:sysroot_glibc2.31_amd64 //sysroot:sysroot_glibc2.31_arm64 \ - //sysroot:sysroot_glibc2.31_libstdcxx_amd64 //sysroot:sysroot_glibc2.31_libstdcxx_arm64 +# Build all glibc 2.31 sysroots +bazel build //sysroot:sysroot_glibc231_amd64 //sysroot:sysroot_glibc231_arm64 -# Build all glibc 2.28 variants -bazel build //sysroot:sysroot_glibc2.28_amd64 //sysroot:sysroot_glibc2.28_arm64 \ - //sysroot:sysroot_glibc2.28_libstdcxx_amd64 //sysroot:sysroot_glibc2.28_libstdcxx_arm64 +# Build all glibc 2.28 sysroots +bazel build //sysroot:sysroot_glibc228_amd64 //sysroot:sysroot_glibc228_arm64 ``` diff --git a/bazel/sysroot/build_sysroot.sh b/bazel/sysroot/build_sysroot.sh index d3abfce395..0ca7ff515e 100755 --- a/bazel/sysroot/build_sysroot.sh +++ b/bazel/sysroot/build_sysroot.sh @@ -68,9 +68,6 @@ DEFAULT_REMOVE_DIRS=( ARCH="" GLIBC_VERSION="" DEBIAN_VERSION="" -VARIANT="base" -PPA_TOOLCHAIN="" -STDCC_VERSION="13" KEEP_DIRS="" REMOVE_DIRS="" SKIP_CLEANUP="false" @@ -83,11 +80,6 @@ usage () { echo " --glibc glibc version (e.g., 2.31 or 2.28)" echo " --debian Debian version (e.g., bullseye or buster)" echo "" - echo "Variant Options:" - echo " --variant Sysroot variant: base or libstdcxx (default: base)" - echo " --ppa-toolchain Ubuntu PPA toolchain version (required for libstdcxx variant)" - echo " --stdcc libstdc++ version (default: 13)" - echo "" echo "Output Options:" echo " --output Output directory name" echo " --workdir Directory to build in" @@ -126,18 +118,6 @@ while [[ $# -gt 0 ]]; do DEBIAN_VERSION="$2" shift 2 ;; - --variant) - VARIANT="$2" - shift 2 - ;; - --ppa-toolchain) - PPA_TOOLCHAIN="$2" - shift 2 - ;; - --stdcc) - STDCC_VERSION="$2" - shift 2 - ;; --output) OUTPUT="$2" shift 2 @@ -170,11 +150,6 @@ if [[ -z "$ARCH" ]] || [[ -z "$GLIBC_VERSION" ]] || [[ -z "$DEBIAN_VERSION" ]]; usage fi -if [[ "$VARIANT" == "libstdcxx" ]] && [[ -z "$PPA_TOOLCHAIN" ]]; then - echo "Error: --ppa-toolchain is required for libstdcxx variant" - usage -fi - case "$ARCH" in amd64) TRIPLE="x86_64-linux-gnu" ;; arm64) TRIPLE="aarch64-linux-gnu" ;; @@ -186,7 +161,6 @@ echo " Architecture: $ARCH" echo " Target triple: $TRIPLE" echo " glibc version: $GLIBC_VERSION" echo " Debian version: $DEBIAN_VERSION" -echo " Variant: $VARIANT" echo " Output directory: $WORK_DIR" # Determine Debian mirror and libgcc package based on Debian version @@ -250,44 +224,12 @@ install_base_packages () { -t "$DEBIAN_VERSION-backports" linux-libc-dev } -install_libstdcc () { - if [[ "$VARIANT" != "libstdcxx" ]]; then - return - fi - echo "" - echo "Step 4: Installing libstdc++..." - # Fetch the ubuntu-toolchain-r PPA signing key using a temporary GNUPGHOME - # so we don't pollute the host keyring, then install it into the sysroot's - # trusted.gpg.d directory for apt's signed-by mechanism. - local ppa_key_id='1E9377A2BA9EF27F' - local tmp_gnupghome - tmp_gnupghome=$(mktemp -d) - # shellcheck disable=SC2064 - trap "rm -rf '$tmp_gnupghome'" EXIT - sudo mkdir -p "$WORK_DIR/etc/apt/trusted.gpg.d" - GNUPGHOME="$tmp_gnupghome" retry 3 10 gpg \ - --keyserver keyserver.ubuntu.com \ - --recv-keys "$ppa_key_id" - GNUPGHOME="$tmp_gnupghome" gpg --export "$ppa_key_id" \ - | sudo install -m 0644 -o root -g root /dev/stdin \ - "$WORK_DIR/etc/apt/trusted.gpg.d/ubuntu-toolchain-r.gpg" - rm -rf "$tmp_gnupghome" - trap - EXIT - echo "deb [signed-by=/etc/apt/trusted.gpg.d/ubuntu-toolchain-r.gpg] http://ppa.launchpad.net/ubuntu-toolchain-r/test/ubuntu $PPA_TOOLCHAIN main" \ - | sudo tee "$WORK_DIR/etc/apt/sources.list.d/toolchain.list" > /dev/null - retry 3 10 sudo chroot "$WORK_DIR" apt-get -qq update - retry 3 10 sudo chroot "$WORK_DIR" apt-get -qq install -y "libstdc++-${STDCC_VERSION}-dev" -} - install_libgcc_dev_link () { - if [[ "$VARIANT" != "base" ]]; then - return - fi # The runtime package omits the unversioned dev link from libgcc-N-dev. # Provide it for literal -lgcc_s users (notably rustc), without -lgcc: # base sysroots use compiler-rt and do not include libgcc.a. echo "" - echo "Step 5: Ensuring unversioned libgcc_s.so link..." + echo "Step 4: Ensuring unversioned libgcc_s.so link..." local libdir for libdir in "lib/$TRIPLE" "usr/lib/$TRIPLE"; do if [[ -e "$WORK_DIR/$libdir/libgcc_s.so.1" ]]; then @@ -313,7 +255,7 @@ INPUT ( libgcc_s.so.1 )" \ cleanup_sysroot () { echo "" - echo "Step 6: Cleaning up sysroot..." + echo "Step 5: Cleaning up sysroot..." if [[ "$CROSS_COMPILE" == "false" ]]; then sudo chroot "$WORK_DIR" apt-get clean fi @@ -349,17 +291,16 @@ cleanup_sysroot () { sudo rm -rf "$WORK_DIR/$dir" fi done - # Clean up apt sources and PPA keyring (unless etc is in keep list) + # Clean up apt sources (unless etc is in keep list) if [[ -z "${KEEP_SET[etc]}" ]]; then sudo rm -rf "$WORK_DIR/etc/apt/sources.list.d/"* - sudo rm -f "$WORK_DIR/etc/apt/trusted.gpg.d/ubuntu-toolchain-r.gpg" fi fi } fix_absolute_symlinks () { echo "" - echo "Step 7: Fixing absolute symlinks..." + echo "Step 6: Fixing absolute symlinks..." find "$WORK_DIR" -type l | while read -r symlink; do # Get the current target current_target=$(readlink "$symlink") @@ -383,7 +324,7 @@ fix_absolute_symlinks () { package_sysroot () { echo "" - echo "Step 8: Packaging sysroot..." + echo "Step 7: Packaging sysroot..." OUTPUT_FILE="$(realpath "${OUTPUT}")" sudo tar -cJf "$OUTPUT_FILE" -C "$WORK_DIR" . echo "" @@ -399,7 +340,6 @@ build_sysroot () { create_base_sysroot configure_package_sources install_base_packages - install_libstdcc install_libgcc_dev_link cleanup_sysroot fix_absolute_symlinks diff --git a/bazel/sysroot/extensions.bzl b/bazel/sysroot/extensions.bzl index e9e919348a..5524ddc224 100644 --- a/bazel/sysroot/extensions.bzl +++ b/bazel/sysroot/extensions.bzl @@ -1,7 +1,7 @@ """Module extension for sysroot configuration in bzlmod.""" load(":macos_sysroot.bzl", "setup_macos_sysroot_build") -load(":sysroot.bzl", "sysroot", "setup_sysroots") +load(":sysroot.bzl", "setup_sysroots", "sysroot") def _sysroot_impl(module_ctx): """Implementation of the sysroot module extension. @@ -27,7 +27,6 @@ def _sysroot_impl(module_ctx): setup_sysroots( version = setup_tag.version if setup_tag.version else None, glibc_version = setup_tag.glibc_version, - stdcc_version = setup_tag.stdcc_version if setup_tag.stdcc_version else None, name_prefix = setup_tag.name_prefix, ) @@ -40,10 +39,6 @@ _setup = tag_class( default = "2.31", doc = "glibc version to use (default: '2.31', also available: '2.28')", ), - "stdcc_version": attr.string( - default = "", - doc = "libstdc++ version to use (default: '' for base sysroot without libstdc++; set to e.g. '13' for the libstdc++ variant)", - ), "name_prefix": attr.string( default = "", doc = """Optional prefix for sysroot repository names (default: ''). diff --git a/bazel/sysroot/fs.bzl b/bazel/sysroot/fs.bzl index 737e5bc8cd..8f8b54e7fd 100644 --- a/bazel/sysroot/fs.bzl +++ b/bazel/sysroot/fs.bzl @@ -25,16 +25,12 @@ def sysrootfs( arch, glibc_version, debian_version, - variant = "base", - ppa_toolchain = None, - stdcc_version = "13", stamp = ":sysroot_daily_stamp", tags = [ "manual", ], extra_tags = [], - visibility = ["//visibility:public"], -): + visibility = ["//visibility:public"]): """Create a genrule to build a sysroot. Args: @@ -42,39 +38,19 @@ def sysrootfs( arch: Architecture (amd64 or arm64) glibc_version: glibc version (e.g., "2.31" or "2.28") debian_version: Debian version (e.g., "bullseye" or "buster") - variant: Sysroot variant ("base" or "libstdcxx") - ppa_toolchain: Ubuntu PPA toolchain version (required for libstdcxx variant) - stdcc_version: libstdc++ version (default: "13") stamp: Label of a daily-stamp target whose content changes once per UTC day. Pass None to disable daily cache expiry. """ - # Construct output filename - if variant == "libstdcxx": - output_file = "sysroot-glibc{}-libstdc++{}-{}.tar.xz".format( - glibc_version, - stdcc_version, - arch, - ) - build_args = "--arch {} --glibc {} --debian {} --variant {} --ppa-toolchain {} --stdcc {}".format( - arch, - glibc_version, - debian_version, - variant, - ppa_toolchain, - stdcc_version, - ) - else: - output_file = "sysroot-glibc{}-{}.tar.xz".format( - glibc_version, - arch, - ) - build_args = "--arch {} --glibc {} --debian {} --variant {}".format( - arch, - glibc_version, - debian_version, - variant, - ) + output_file = "sysroot-glibc{}-{}.tar.xz".format( + glibc_version, + arch, + ) + build_args = "--arch {} --glibc {} --debian {}".format( + arch, + glibc_version, + debian_version, + ) native.genrule( name = name, @@ -95,15 +71,12 @@ def sysrootfs( visibility = visibility, ) -def sysroots(arches, glibc, stdcc): +def sysroots(arches, glibc): """Generates matrix of sysroot targets. Args: arches: List of architectures (e.g. ["amd64", "arm64"]) glibc: List of glibc versions (e.g. ["2.28", "2.31"]) - stdcc: List of stdcc versions (e.g. ["13", ""]). - "" (empty string) implies variant="base". - "13" implies variant="libstdcxx". """ target_names = [] @@ -116,32 +89,17 @@ def sysroots(arches, glibc, stdcc): debian_version = "buster" else: fail("Unsupported glibc version: {}".format(glibc_version)) - for cc_ver in stdcc: - if cc_ver: - variant = "libstdcxx" - stdcc_version = cc_ver - ppa_toolchain = "focal" if debian_version == "bullseye" else "bionic" - name_suffix = "_libstdcxx" - else: - variant = "base" - stdcc_version = None - ppa_toolchain = None - name_suffix = "" - name = "sysroot_glibc{v}{s}_{a}".format( - v = glibc_version.replace(".", ""), - s = name_suffix, - a = arch, - ) - sysrootfs( - name = name, - arch = arch, - glibc_version = glibc_version, - debian_version = debian_version, - variant = variant, - ppa_toolchain = ppa_toolchain, - stdcc_version = stdcc_version, - ) - target_names.append(":" + name) + name = "sysroot_glibc{v}_{a}".format( + v = glibc_version.replace(".", ""), + a = arch, + ) + sysrootfs( + name = name, + arch = arch, + glibc_version = glibc_version, + debian_version = debian_version, + ) + target_names.append(":" + name) native.filegroup( name = "sysroots", diff --git a/bazel/sysroot/sysroot.bzl b/bazel/sysroot/sysroot.bzl index 7c0d16772e..e6e898b5c6 100644 --- a/bazel/sysroot/sysroot.bzl +++ b/bazel/sysroot/sysroot.bzl @@ -31,22 +31,11 @@ def _sysroot_impl(ctx): """Download a sysroot with one sandbox symlink and one merkle-tree node.""" arch = ctx.attr.arch or _get_platform_arch(ctx) glibc_version = ctx.attr.glibc_version - stdcc_version = ctx.attr.stdcc_version - - # Construct URL based on whether stdcc_version is specified - if stdcc_version: - url = "https://github.com/envoyproxy/toolshed/releases/download/bins-v{version}/sysroot-glibc{glibc_version}-libstdc++{stdcc_version}-{arch}.tar.xz".format( - version = ctx.attr.version, - arch = arch, - glibc_version = glibc_version, - stdcc_version = stdcc_version, - ) - else: - url = "https://github.com/envoyproxy/toolshed/releases/download/bins-v{version}/sysroot-glibc{glibc_version}-{arch}.tar.xz".format( - version = ctx.attr.version, - arch = arch, - glibc_version = glibc_version, - ) + url = "https://github.com/envoyproxy/toolshed/releases/download/bins-v{version}/sysroot-glibc{glibc_version}-{arch}.tar.xz".format( + version = ctx.attr.version, + arch = arch, + glibc_version = glibc_version, + ) ctx.download_and_extract( url = url, @@ -122,19 +111,15 @@ sysroot = repository_rule( mandatory = True, doc = "glibc version (e.g., '2.31' or '2.28')", ), - "stdcc_version": attr.string( - doc = "libstdc++ version (e.g., '13'). If not specified, base sysroot without libstdc++ is used", - ), }, doc = "Downloads sysroot for the specified or host architecture", ) -def _get_sysroot_hash(glibc_version, stdcc_version, arch): +def _get_sysroot_hash(glibc_version, arch): """Get the SHA256 hash for a specific sysroot configuration. Args: glibc_version: glibc version (e.g., "2.31" or "2.28") - stdcc_version: libstdc++ version (e.g., "13") or None for base sysroot arch: Architecture (e.g., "amd64" or "arm64") Returns: @@ -148,34 +133,21 @@ def _get_sysroot_hash(glibc_version, stdcc_version, arch): ", ".join(VERSIONS["sysroot_hashes"].keys()), )) - # Determine stdlib variant key - stdlib_variant = stdcc_version if stdcc_version else "base" - - # Validate stdlib variant - if stdlib_variant not in VERSIONS["sysroot_hashes"][glibc_version]: - fail("Unsupported libstdc++ version '{}' for glibc {}. Supported variants: {}".format( - stdcc_version or "base", - glibc_version, - ", ".join(VERSIONS["sysroot_hashes"][glibc_version].keys()), - )) - # Validate architecture - if arch not in VERSIONS["sysroot_hashes"][glibc_version][stdlib_variant]: - fail("Unsupported architecture '{}' for glibc {} with libstdc++ {}. Supported architectures: {}".format( + if arch not in VERSIONS["sysroot_hashes"][glibc_version]: + fail("Unsupported architecture '{}' for glibc {}. Supported architectures: {}".format( arch, glibc_version, - stdcc_version or "base", - ", ".join(VERSIONS["sysroot_hashes"][glibc_version][stdlib_variant].keys()), + ", ".join(VERSIONS["sysroot_hashes"][glibc_version].keys()), )) # Get the hash - sha256 = VERSIONS["sysroot_hashes"][glibc_version][stdlib_variant][arch] + sha256 = VERSIONS["sysroot_hashes"][glibc_version][arch] # Validate hash is not empty if not sha256: - fail("SHA256 hash not yet available for glibc {} with libstdc++ {} on {}. This configuration may not be released yet.".format( + fail("SHA256 hash not yet available for glibc {} on {}. This configuration may not be released yet.".format( glibc_version, - stdcc_version or "base", arch, )) @@ -250,22 +222,20 @@ def setup_macos_sysroot(version = None): def setup_sysroots( version = None, glibc_version = "2.31", - stdcc_version = None, name_prefix = ""): """Setup function to configure sysroots, shared by module extensions and direct callers. Args: version: Version of sysroot release to use (default: uses VERSIONS["bins_release"]) glibc_version: glibc version to use (default: "2.31", also available: "2.28") - stdcc_version: libstdc++ version to use (default: None for base sysroot without libstdc++; set to e.g. "13" for the libstdc++ variant) name_prefix: Optional prefix for sysroot repository names (default: "") Allows multiple sysroot setups, e.g., name_prefix="old" creates @old_sysroot_linux_amd64 and @old_sysroot_linux_arm64 """ # Get hashes from versions.bzl based on configuration - amd64_sha256 = _get_sysroot_hash(glibc_version, stdcc_version, "amd64") - arm64_sha256 = _get_sysroot_hash(glibc_version, stdcc_version, "arm64") + amd64_sha256 = _get_sysroot_hash(glibc_version, "amd64") + arm64_sha256 = _get_sysroot_hash(glibc_version, "arm64") # Construct repository names with optional prefix if name_prefix: @@ -282,7 +252,6 @@ def setup_sysroots( sha256 = amd64_sha256, arch = "amd64", glibc_version = glibc_version, - stdcc_version = stdcc_version, ) # ARM64 sysroot @@ -292,5 +261,4 @@ def setup_sysroots( sha256 = arm64_sha256, arch = "arm64", glibc_version = glibc_version, - stdcc_version = stdcc_version, ) diff --git a/bazel/sysroot/test/BUILD b/bazel/sysroot/test/BUILD index c29809ff1b..a43a52eea9 100644 --- a/bazel/sysroot/test/BUILD +++ b/bazel/sysroot/test/BUILD @@ -1,4 +1,17 @@ -load(":sysroot_test.bzl", "sysroot_test") +load("@rules_shell//shell:sh_test.bzl", "sh_test") +load(":sysroot_test.bzl", "sysroot_build_test", "sysroot_test") + +sysroot_build_test( + name = "sysroot_build_test", + target_under_test = "//sysroot:sysroots", +) + +sh_test( + name = "build_sysroot_options_test", + srcs = ["build_sysroot_options_test.sh"], + args = ["$(location //sysroot:build_sysroot.sh)"], + data = ["//sysroot:build_sysroot.sh"], +) [ sysroot_test( diff --git a/bazel/sysroot/test/build_sysroot_options_test.sh b/bazel/sysroot/test/build_sysroot_options_test.sh new file mode 100755 index 0000000000..4bc527fb32 --- /dev/null +++ b/bazel/sysroot/test/build_sysroot_options_test.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +set -euo pipefail + +script="$1" +for option in --variant --ppa-toolchain --stdcc; do + if output=$(bash "$script" "$option" obsolete 2>&1); then + echo "Expected removed option $option to fail" >&2 + exit 1 + fi + if [[ "$output" != "Unknown option: $option"$'\n'* ]]; then + echo "Expected an unknown-option error for $option, got: $output" >&2 + exit 1 + fi +done diff --git a/bazel/sysroot/test/sysroot_test.bzl b/bazel/sysroot/test/sysroot_test.bzl index 32525bc873..e43b80ce33 100644 --- a/bazel/sysroot/test/sysroot_test.bzl +++ b/bazel/sysroot/test/sysroot_test.bzl @@ -1,6 +1,23 @@ """Regression tests for directory sysroots and their file-level targets.""" -load("@bazel_skylib//lib:unittest.bzl", "asserts", "unittest") +load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts", "unittest") + +def _sysroot_build_test_impl(ctx): + env = analysistest.begin(ctx) + target = analysistest.target_under_test(env) + asserts.equals( + env, + [ + "sysroot-glibc2.28-amd64.tar.xz", + "sysroot-glibc2.28-arm64.tar.xz", + "sysroot-glibc2.31-amd64.tar.xz", + "sysroot-glibc2.31-arm64.tar.xz", + ], + sorted([file.basename for file in target[DefaultInfo].files.to_list()]), + ) + return analysistest.end(env) + +sysroot_build_test = analysistest.make(_sysroot_build_test_impl) def _sysroot_test_impl(ctx): env = unittest.begin(ctx) diff --git a/bazel/toolchains/gcc/BUILD.bazel b/bazel/toolchains/gcc/BUILD.bazel index 26fa109a1b..c59b800d5e 100644 --- a/bazel/toolchains/gcc/BUILD.bazel +++ b/bazel/toolchains/gcc/BUILD.bazel @@ -1,28 +1,15 @@ -load("@rules_cc//cc/toolchains:cc_toolchain.bzl", "cc_toolchain") -load(":toolchain.bzl", "gcc_linux_cc_toolchain_config") +load(":toolchain_test.bzl", "gcc_paths_test") package(default_visibility = ["//visibility:public"]) -filegroup( - name = "empty", - srcs = [], -) - -gcc_linux_cc_toolchain_config( - name = "linux_x64_config", - arch = "x86_64", -) +exports_files([ + "extensions.bzl", + "toolchain.bzl", +]) -cc_toolchain( +alias( name = "linux_x64", - all_files = ":empty", - ar_files = ":empty", - compiler_files = ":empty", - dwp_files = ":empty", - linker_files = ":empty", - objcopy_files = ":empty", - strip_files = ":empty", - toolchain_config = ":linux_x64_config", + actual = "@gcc_linux_x86_64//:cc_toolchain", ) # Selection is driven by the target platform: target_compatible_with @@ -42,9 +29,7 @@ cc_toolchain( # //compile:llvm_worker is still required by the llvm toolchains, which is what # prevents clang being scheduled into the gcc container. # -# NB: the cc_toolchain has empty filegroups and invokes /usr/bin/gcc from the -# exec machine, so it only works where gcc is actually installed - on RBE that -# is guaranteed by the ordering above rather than by a constraint. +# Both archives execute on x86_64, including the aarch64 cross compiler. toolchain( name = "linux_x64_toolchain", exec_compatible_with = [ @@ -60,28 +45,30 @@ toolchain( toolchain_type = "@bazel_tools//tools/cpp:toolchain_type", ) -gcc_linux_cc_toolchain_config( - name = "linux_arm64_config", - arch = "aarch64", +alias( + name = "linux_arm64", + actual = "@gcc_linux_aarch64//:cc_toolchain", ) -cc_toolchain( - name = "linux_arm64", - all_files = ":empty", - ar_files = ":empty", - compiler_files = ":empty", - dwp_files = ":empty", - linker_files = ":empty", - objcopy_files = ":empty", - strip_files = ":empty", - toolchain_config = ":linux_arm64_config", +gcc_paths_test( + name = "linux_x64_paths_test", + compiler = "@gcc_linux_x86_64//:xbin/gcc", + sysroot = "@sysroot_linux_amd64//sysroot", + target_under_test = ":linux_x64", +) + +gcc_paths_test( + name = "linux_arm64_paths_test", + compiler = "@gcc_linux_aarch64//:xbin/gcc", + sysroot = "@sysroot_linux_arm64//sysroot", + target_under_test = ":linux_arm64", ) toolchain( name = "linux_arm64_toolchain", exec_compatible_with = [ "@platforms//os:linux", - "@platforms//cpu:aarch64", + "@platforms//cpu:x86_64", ], target_compatible_with = [ "@platforms//os:linux", diff --git a/bazel/toolchains/gcc/extensions.bzl b/bazel/toolchains/gcc/extensions.bzl new file mode 100644 index 0000000000..4ab73f666f --- /dev/null +++ b/bazel/toolchains/gcc/extensions.bzl @@ -0,0 +1,114 @@ +"""Pinned x86_64-hosted GCC cross compilers using the shared base sysroot.""" + +_VERSION = "13.4.0" +_RELEASE = "18082025" +_SHA256 = { + "x86_64": "d96071c1b98499afd7b7b56ebd69ad414020edf66e982004acffe7df8aaf7e02", + "aarch64": "770cf6bf62bdf78763de526d3a9f5cae4c19f1a3aca0ef8f18b05f1a46d1ffaf", +} + +def _gcc_repository_impl(ctx): + arch = ctx.attr.arch + triple = arch + "-linux" + ctx.download_and_extract( + url = "https://github.com/f0rmiga/gcc-builds/releases/download/{}/gcc-toolchain-{}-{}.tar.xz".format(_RELEASE, _VERSION, arch), + sha256 = _SHA256[arch], + ) + + # Never expose the archive's libc to compilation or linking. + ctx.delete("sysroot") + prefix = triple + "-" if ctx.path("bin/" + triple + "-as").exists else "" + + # These archives do not ship dwp; never fall back to a host executable. + ctx.file("xbin/dwp", "#!/bin/bash\necho 'GCC toolchain does not support dwp' >&2\nexit 1\n", executable = True) + for tool in ["ar", "as", "cpp", "gcc", "gcov", "ld", "nm", "objcopy", "objdump", "readelf", "strip"]: + binary = "bin/" + prefix + tool + if not ctx.path(binary).exists: + fail("GCC archive is missing " + binary) + ctx.file( + "xbin/" + tool, + """#!/bin/bash +set -euo pipefail +ROOT="${PWD}/external/%s" +export PATH="${ROOT}/bin" +unset CPATH C_INCLUDE_PATH CPLUS_INCLUDE_PATH OBJC_INCLUDE_PATH LIBRARY_PATH GCC_EXEC_PREFIX COMPILER_PATH +exec "${ROOT}/%s" "$@" +""" % (ctx.name, binary), + executable = True, + ) + cxx_prefix = "aarch64-linux/" if arch == "aarch64" else "" + for path in [ + "lib/gcc/" + triple + "/" + _VERSION + "/" + filename + for filename in ["crtbegin.o", "crtend.o", "libgcc.a", "libgcc_eh.a", "include", "include-fixed"] + ] + [ + cxx_prefix + "include/c++/" + _VERSION, + cxx_prefix + "lib64/libstdc++.a", + cxx_prefix + "lib64/libstdc++.so", + ]: + if not ctx.path(path).exists: + fail("GCC archive is missing compiler-owned runtime input " + path) + ctx.file("BUILD.bazel", """ +load("@rules_cc//cc/toolchains:cc_toolchain.bzl", "cc_toolchain") +load(%r, "gcc_linux_cc_toolchain_config") + +package(default_visibility = ["//visibility:public"]) + +gcc_linux_cc_toolchain_config( + name = "config", + arch = %r, + triple = %r, + version = %r, + sysroot = %r, +) + +filegroup( + name = "files", + srcs = glob(["bin/**", "xbin/**", "lib/**", "lib64/**", "libexec/**", "include/**", %r]) + [%r], +) + +cc_toolchain( + name = "cc_toolchain", + all_files = ":files", + ar_files = ":files", + as_files = ":files", + compiler_files = ":files", + dwp_files = ":files", + linker_files = ":files", + objcopy_files = ":files", + strip_files = ":files", + supports_param_files = True, + toolchain_config = ":config", +) + +exports_files(glob(["xbin/*"])) +""" % (str(ctx.attr._config), arch, triple, _VERSION, str(ctx.attr.sysroot), triple + "/**", str(ctx.attr.sysroot))) + +_gcc_repository = repository_rule( + implementation = _gcc_repository_impl, + attrs = { + "arch": attr.string(mandatory = True, values = ["x86_64", "aarch64"]), + "sysroot": attr.label(mandatory = True), + "_config": attr.label(default = Label("//toolchains/gcc:toolchain.bzl")), + }, +) + +def _gcc_extension_impl(ctx): + for mod in ctx.modules: + for tag in mod.tags.toolchain: + _gcc_repository( + name = tag.name, + arch = tag.arch, + sysroot = tag.sysroot, + ) + return ctx.extension_metadata(reproducible = True) + +gcc_extension = module_extension( + implementation = _gcc_extension_impl, + tag_classes = { + "toolchain": tag_class(attrs = { + "name": attr.string(mandatory = True), + "arch": attr.string(mandatory = True, values = ["x86_64", "aarch64"]), + "sysroot": attr.label(mandatory = True), + }), + }, +) diff --git a/bazel/toolchains/gcc/toolchain.bzl b/bazel/toolchains/gcc/toolchain.bzl index f6a1cab495..3010941322 100644 --- a/bazel/toolchains/gcc/toolchain.bzl +++ b/bazel/toolchains/gcc/toolchain.bzl @@ -1,93 +1,86 @@ +"""Configure GCC with its own C++ runtime and toolshed's shared libc sysroot.""" + # buildifier: disable=bzl-visibility load( "@rules_cc//cc/private/toolchain:unix_cc_toolchain_config.bzl", gcc_cc_toolchain_config = "cc_toolchain_config", ) -_GCC_VERSIONS = [ - "13", - "12", - "11", - "10", -] - -def _builtin_include_directories(triple): - return ( - ["/usr/include/{}/c++/{}".format(triple, version) for version in _GCC_VERSIONS] + - ["/usr/lib/gcc/{}/{}/include".format(triple, version) for version in _GCC_VERSIONS] + - ["/usr/include/c++/{}".format(version) for version in _GCC_VERSIONS] + - ["/usr/include/c++/{}/backward".format(version) for version in _GCC_VERSIONS] + - [ - "/usr/local/include", - "/usr/include/{}".format(triple), - "/usr/include", - "/usr/lib/linux/uapi", - ] - ) - -_TOOL_PATHS = { - "ar": "/usr/bin/ar", - "cpp": "/usr/bin/cpp", - "dwp": "/usr/bin/dwp", - "gcc": "/usr/bin/gcc", - "gcov": "/usr/bin/gcov", - "ld": "/usr/bin/ld", - "nm": "/usr/bin/nm", - "objcopy": "/usr/bin/objcopy", - "objdump": "/usr/bin/objdump", - "strip": "/usr/bin/strip", -} - -_TOOLCHAIN_CONFIGS = { - "x86_64": { - "abi_libc_version": "glibc_2.39", - "abi_version": "gcc-13", - "cpu": "k8", - "cxx_builtin_include_directories": _builtin_include_directories("x86_64-linux-gnu"), - "target_system_name": "x86_64-linux-gnu", - "toolchain_identifier": "linux-x86_64-gcc-13", - }, - "aarch64": { - "abi_libc_version": "glibc_2.39", - "abi_version": "gcc-13", - "cpu": "aarch64", - "cxx_builtin_include_directories": _builtin_include_directories("aarch64-linux-gnu"), - "target_system_name": "aarch64-linux-gnu", - "toolchain_identifier": "linux-aarch64-gcc-13", - }, -} - -def gcc_linux_cc_toolchain_config(name, arch): - config = _TOOLCHAIN_CONFIGS[arch] +def gcc_linux_cc_toolchain_config(name, arch, triple, version, sysroot): + """Configure an extracted Linux cross compiler, never the host compiler. + Args: + name: Configuration target name. + arch: Target CPU. + triple: GCC's configured target triple. + version: GCC version. + sysroot: Label exporting the base glibc sysroot. + """ + root = native.package_relative_label(":BUILD.bazel").workspace_root + sysroot = Label(sysroot) + sysroot_path = sysroot.workspace_root + "/" + sysroot.package + gcc_lib = root + "/lib/gcc/" + triple + "/" + version + cxx_include = root + ("/aarch64-linux" if arch == "aarch64" else "") + "/include/c++/" + version + c_includes = [ + gcc_lib + "/include", + gcc_lib + "/include-fixed", + sysroot_path + "/usr/include", + sysroot_path + "/usr/include/" + arch + "-linux-gnu", + ] + cxx_includes = [ + cxx_include, + cxx_include + "/" + triple, + cxx_include + "/backward", + ] + lib_dirs = [ + gcc_lib, + root + "/lib", + root + "/lib64", + root + "/" + triple + "/lib", + root + "/" + triple + "/lib64", + sysroot_path + "/usr/lib/" + arch + "-linux-gnu", + sysroot_path + "/lib/" + arch + "-linux-gnu", + ] + search_flags = ["--sysroot=" + sysroot_path, "-B" + root + "/bin/"] + search_flags += ["-B" + directory + "/" for directory in lib_dirs] gcc_cc_toolchain_config( name = name, - abi_libc_version = config["abi_libc_version"], - abi_version = config["abi_version"], + abi_libc_version = "glibc_2.31", + abi_version = "gcc-" + version, + builtin_sysroot = sysroot_path, compiler = "gcc", - cpu = config["cpu"], - cxx_builtin_include_directories = config["cxx_builtin_include_directories"], + compile_flags = search_flags + ["-nostdinc"] + ["-idirafter" + directory for directory in c_includes], + cpu = "k8" if arch == "x86_64" else arch, + cxx_builtin_include_directories = ["%workspace%/" + directory for directory in cxx_includes + c_includes], + cxx_flags = ["-nostdinc++"] + ["-isystem" + directory for directory in cxx_includes], dbg_compile_flags = ["-g"], - host_system_name = arch, - link_flags = [ + host_system_name = "x86_64-linux", + link_flags = search_flags + ["-L" + directory for directory in lib_dirs] + [ + "-static-libstdc++", + "-static-libgcc", "-Wl,--build-id=md5", "-Wl,--hash-style=gnu", "-Wl,-z,relro,-z,now", ], - link_libs = [ - "-lstdc++", - "-lm", - ], - opt_compile_flags = [ - "-O2", - "-DNDEBUG", - ], - # `--start-lib`/`--end-lib` are gold/lld-only options. This toolchain - # links with GNU BFD `/usr/bin/ld`, which rejects them, so Bazel must - # fall back to building static archives for cc_library deps. + # The C driver does not interpret -static-libstdc++ for an explicit + # -lstdc++; select the archive explicitly as well. + link_libs = ["-l:libstdc++.a", "-lm"], + opt_compile_flags = ["-O2", "-DNDEBUG"], + # The bundled GNU BFD linker does not support --start-lib/--end-lib. supports_start_end_lib = False, target_libc = "glibc", - target_system_name = config["target_system_name"], - tool_paths = _TOOL_PATHS, - toolchain_identifier = config["toolchain_identifier"], + target_system_name = triple, + tool_paths = {tool: "xbin/" + tool for tool in [ + "ar", + "cpp", + "dwp", + "gcc", + "gcov", + "ld", + "nm", + "objcopy", + "objdump", + "strip", + ]}, + toolchain_identifier = "linux-" + arch + "-gcc-" + version, ) diff --git a/bazel/toolchains/gcc/toolchain_test.bzl b/bazel/toolchains/gcc/toolchain_test.bzl new file mode 100644 index 0000000000..93532a8b88 --- /dev/null +++ b/bazel/toolchains/gcc/toolchain_test.bzl @@ -0,0 +1,29 @@ +"""Analysis regressions for repository-relative compiler and header paths.""" + +load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts") +load("@rules_cc//cc/common:cc_common.bzl", "cc_common") + +def _gcc_paths_test_impl(ctx): + env = analysistest.begin(ctx) + toolchain = analysistest.target_under_test(env)[cc_common.CcToolchainInfo] + compiler = ctx.file.compiler.path + root = compiler[:-len("/xbin/gcc")] + sysroot = ctx.file.sysroot.path + asserts.equals(env, compiler, toolchain.compiler_executable) + asserts.equals(env, root + "/xbin/ar", toolchain.ar_executable) + for directory in toolchain.built_in_include_directories: + asserts.true( + env, + directory.startswith(root + "/") or directory.startswith(sysroot + "/"), + "Unexpected builtin include directory: " + directory, + ) + asserts.false(env, directory.count("external/") > 1, "Repository prefix duplicated: " + directory) + return analysistest.end(env) + +gcc_paths_test = analysistest.make( + _gcc_paths_test_impl, + attrs = { + "compiler": attr.label(allow_single_file = True), + "sysroot": attr.label(allow_single_file = True), + }, +) diff --git a/bazel/v8/BUILD b/bazel/v8/BUILD index 1973370093..7c239a1778 100644 --- a/bazel/v8/BUILD +++ b/bazel/v8/BUILD @@ -66,8 +66,7 @@ alias( actual = select({ ":linux_x86_64_gcc": "@%s//:wee8" % wee8_prebuilt_repo_name("x86_64", "libstdcxx"), ":linux_x86_64": "@%s//:wee8" % wee8_prebuilt_repo_name("x86_64"), - # This does not currently work as it would require x-libs similar to how we provision llvm - # ":linux_aarch64_gcc": "@%s//:wee8" % wee8_prebuilt_repo_name("aarch64", "libstdcxx"), + ":linux_aarch64_gcc": "@%s//:wee8" % wee8_prebuilt_repo_name("aarch64", "libstdcxx"), ":linux_aarch64": "@%s//:wee8" % wee8_prebuilt_repo_name("aarch64"), "//conditions:default": "@wee8_source//:wee8", }), diff --git a/bazel/v8/extensions.bzl b/bazel/v8/extensions.bzl index c6ff6dcdee..70ce91784e 100644 --- a/bazel/v8/extensions.bzl +++ b/bazel/v8/extensions.bzl @@ -9,9 +9,11 @@ _SHA_ATTRS = [ "x86_64_libstdcxx_sha256", "aarch64_version", "aarch64_sha256", + "aarch64_libstdcxx_version", + "aarch64_libstdcxx_sha256", ] -_REPOS = "@wee8_prebuilt_x86_64, @wee8_prebuilt_x86_64_libstdcxx, @wee8_prebuilt_aarch64" +_REPOS = "@wee8_prebuilt_x86_64, @wee8_prebuilt_x86_64_libstdcxx, @wee8_prebuilt_aarch64, @wee8_prebuilt_aarch64_libstdcxx" def _module_id(mod): if mod.version: @@ -102,6 +104,12 @@ _setup = tag_class( "aarch64_sha256": attr.string( doc = "SHA256 of the aarch64 libcxx wee8 archive", ), + "aarch64_libstdcxx_version": attr.string( + doc = "Version of the aarch64 libstdcxx wee8 release to use", + ), + "aarch64_libstdcxx_sha256": attr.string( + doc = "SHA256 of the aarch64 libstdcxx wee8 archive", + ), "source": attr.label( doc = "Target to build wee8 from source when no prebuilt matches the " + "target platform (eg `@v8//:wee8`). Unset: //v8:wee8 is " + diff --git a/bazel/v8/package/BUILD b/bazel/v8/package/BUILD index 5f09197598..2fa383df9a 100644 --- a/bazel/v8/package/BUILD +++ b/bazel/v8/package/BUILD @@ -6,10 +6,14 @@ WEE8_VARIANTS = [ ("x86_64", "libcxx"), ("aarch64", "libcxx"), ("x86_64", "libstdcxx"), + ("aarch64", "libstdcxx"), ] [ - wee8_package(arch = arch, stdlib = stdlib) + wee8_package( + arch = arch, + stdlib = stdlib, + ) for arch, stdlib in WEE8_VARIANTS ] diff --git a/bazel/v8/wee8_package.bzl b/bazel/v8/wee8_package.bzl index f15f1b7f76..46a8e6c1fc 100644 --- a/bazel/v8/wee8_package.bzl +++ b/bazel/v8/wee8_package.bzl @@ -27,8 +27,7 @@ _ARCH_PLATFORMS = { ("x86_64", "libcxx"): "@toolchains_llvm//platforms:linux-x86_64", ("aarch64", "libcxx"): "@toolchains_llvm//platforms:linux-aarch64", ("x86_64", "libstdcxx"): "//platforms:linux_x86_64_libstdcxx", - # This does not currently work as it would require x-libs similar to how we provision llvm - # ("aarch64", "libstdcxx"): "//platforms:linux_aarch64_libstdcxx", + ("aarch64", "libstdcxx"): "//platforms:linux_aarch64_libstdcxx", } # V8's mksnapshot/torque run as exec (build-host) tools but must emit code for @@ -43,12 +42,10 @@ _V8_TARGET_CPU = { # The transition sets the target platform only. Execution platforms are supplied # by config, not here: # -# --config=gcc registers //platforms:linux_x86_64_gcc_worker, which -# carries //compile:gcc_worker so the gcc toolchain resolves -# locally. -# --config=rbe-gcc overrides that with the //platforms/rbe gcc platforms, -# which also carry the `container-image` exec property that -# EngFlow matches on. +# --config=gcc selects the libstdcxx target platform. The hermetic gcc +# toolchain can execute locally on Linux x86_64. +# --config=rbe-gcc supplies the //platforms/rbe gcc platforms, which carry the +# `container-image` exec property that EngFlow matches on. # # Setting --extra_execution_platforms from the transition would clobber the RBE # platforms, and dispatched actions would fail with `No matching action runner @@ -189,6 +186,7 @@ def _wee8_fat_archive_impl(ctx): ) params = ctx.actions.declare_file("%s/libwee8.objects.params" % ctx.label.name) + # Trailing newline: llvm-ar and GNU ar both tolerate its absence, but it is # free insurance against an archiver that expects newline-terminated entries. ctx.actions.write(params, "\n".join([o.path for o in objects]) + "\n") diff --git a/bazel/v8/wee8_prebuilt.bzl b/bazel/v8/wee8_prebuilt.bzl index 9100cd25a6..84e05d7c81 100644 --- a/bazel/v8/wee8_prebuilt.bzl +++ b/bazel/v8/wee8_prebuilt.bzl @@ -262,7 +262,9 @@ def setup_wee8_prebuilt( x86_64_libstdcxx_version = None, x86_64_libstdcxx_sha256 = None, aarch64_version = None, - aarch64_sha256 = None): + aarch64_sha256 = None, + aarch64_libstdcxx_version = None, + aarch64_libstdcxx_sha256 = None): """Setup function shared by module extensions and direct callers.""" variants = [ ("x86_64", WEE8_DEFAULT_STDLIB, x86_64_version, x86_64_sha256), @@ -277,3 +279,13 @@ def setup_wee8_prebuilt( arch = arch, stdlib = stdlib, ) + + # Until the first cross-GCC bins release, expose the existing incompatible + # stub rather than trying to fetch an unpublished archive. + wee8_prebuilt( + name = wee8_prebuilt_repo_name("aarch64", "libstdcxx"), + version = aarch64_libstdcxx_version or aarch64_version or VERSIONS["bins_release"], + sha256 = aarch64_libstdcxx_sha256 or wee8_sha256(VERSIONS, "aarch64", "libstdcxx"), + arch = "aarch64", + stdlib = "libstdcxx", + ) diff --git a/bazel/v8/wee8_prebuilt_test.bzl b/bazel/v8/wee8_prebuilt_test.bzl index 7ce98f5dad..5715aeab6c 100644 --- a/bazel/v8/wee8_prebuilt_test.bzl +++ b/bazel/v8/wee8_prebuilt_test.bzl @@ -27,6 +27,7 @@ def _wee8_prebuilt_helpers_test_impl(ctx): asserts.equals(env, "wee8_prebuilt_x86_64", wee8_prebuilt_repo_name("x86_64")) asserts.equals(env, "wee8_prebuilt_x86_64_libstdcxx", wee8_prebuilt_repo_name("x86_64", "libstdcxx")) asserts.equals(env, "wee8_prebuilt_aarch64", wee8_prebuilt_repo_name("aarch64")) + asserts.equals(env, "wee8_prebuilt_aarch64_libstdcxx", wee8_prebuilt_repo_name("aarch64", "libstdcxx")) asserts.equals( env, "abc", diff --git a/bazel/versions.bzl b/bazel/versions.bzl index 1fd7f9bcd8..87015cdaf2 100644 --- a/bazel/versions.bzl +++ b/bazel/versions.bzl @@ -83,6 +83,8 @@ VERSIONS = { # Wee8 prebuilt hashes by architecture and stdlib ABI flavour. # libcxx keeps the legacy unsuffixed artifact name; libstdcxx is suffixed. + # TODO: refresh both libstdcxx hashes in the next bins-v* release, built + # with hermetic GCC and the base glibc 2.31 sysroot, before downstream use. "wee8_sha256": { "x86_64": { "libcxx": "ce217d16544fb3fd2cecce3cf872a6ad82902117297b88a223aec5c81bc521df", @@ -94,29 +96,16 @@ VERSIONS = { }, }, - # Sysroot hashes organized by glibc version, stdlib variant, and architecture - # Format: sysroot_hashes[glibc_version][stdlib_variant][arch] - # stdlib_variant is either "base" (no libstdc++) or the libstdc++ version (e.g., "13") + # Sysroot hashes organized by glibc version and architecture. + # Format: sysroot_hashes[glibc_version][arch] "sysroot_hashes": { "2.31": { - "base": { - "amd64": "c027659e4ed93c2f53ca29cc611962790cde21289cbedcfd3419354d6a50767e", - "arm64": "33fb571b3b9b5edb9854fa4444719fae01c0c08825b3051357fcd4ab3721749a", - }, - "13": { - "amd64": "0562bde13b68aa1c49ab286c5bb765158a9f17fb69f3f1d190672ef171502dbf", - "arm64": "db9c5b96cd4ecc9b5ec4ac865d5e91eacf2020ef583aa262c6a906741f46ca11", - }, + "amd64": "c027659e4ed93c2f53ca29cc611962790cde21289cbedcfd3419354d6a50767e", + "arm64": "33fb571b3b9b5edb9854fa4444719fae01c0c08825b3051357fcd4ab3721749a", }, "2.28": { - "base": { - "amd64": "d7ea7bc466377b2294127875216a701e400a57445b1c8daca223c71445681fc1", - "arm64": "ae47a5b829fa354d1936e97c3c01aca3b3fa49546717809f1618a2c20d9ff5f2", - }, - "13": { - "amd64": "b0a230b3875f36dc50739fb4711e8745a0b65fd1b1e4d0c4961c6832980c0510", - "arm64": "8fd6257c1a6ea3048d03d46e3a452873f885fd17ced5640deb3b3994c8dda4bf", - }, + "amd64": "d7ea7bc466377b2294127875216a701e400a57445b1c8daca223c71445681fc1", + "arm64": "ae47a5b829fa354d1936e97c3c01aca3b3fa49546717809f1618a2c20d9ff5f2", }, },