diff --git a/.github/workflows/job.build.yml b/.github/workflows/job.build.yml index f539a1f..4bf435e 100644 --- a/.github/workflows/job.build.yml +++ b/.github/workflows/job.build.yml @@ -56,32 +56,14 @@ jobs: fetch-depth: 1 persist-credentials: false - name: "Setup: Submodules" - # glibc's gitlink is the tip of release/2.34/master on sourceware.org (canonical, kept in - # .gitmodules). sourceware returns HTTP 403 to some CI IPs, so the order is: sourceware by SHA, - # GitHub mirror by SHA, then a mirror branch fetch. The final HEAD == gitlink assertion (and - # stage 00's scripts/check-versions.sh) keeps the mirror honest. Must stay bash 3.2-safe. + # Must stay bash 3.2-safe. run: | # Self-hosted runners keep .git/modules across jobs; a git process killed by a cancelled run # leaves *.lock files that make every later fetch fail. This job owns the workspace. if [ -d .git/modules ]; then find .git/modules -name '*.lock' -type f -print -delete; fi - subs="$(git config -f .gitmodules --get-regexp '^submodule\..*\.path$' | awk '$2 != "glibc" {print $2}')" - # shellcheck disable=SC2086 # submodule paths contain no spaces - git submodule update --quiet --init --depth=1 --recursive --jobs 8 -- $subs - rev="$(git ls-tree HEAD glibc | awk '{print $3}')" - branch="$(git config -f .gitmodules submodule.glibc.branch)" - mirror="https://github.com/bminor/glibc.git" - if ! git submodule update --quiet --init --depth=1 glibc; then - echo "::warning::glibc fetch from sourceware failed; trying $mirror" - rm -rf glibc ".git/modules/glibc" - mkdir glibc - git -C glibc init -q - if ! { git -C glibc fetch --quiet --depth=1 "$mirror" "$rev" && git -C glibc checkout -q --detach FETCH_HEAD; }; then - echo "::warning::glibc fetch by SHA from mirror failed; fetching $branch from mirror" - git -C glibc fetch --quiet --depth=50 "$mirror" "$branch" - git -C glibc checkout -q --detach "$rev" - fi - fi - test "$(git -C glibc rev-parse HEAD)" = "$rev" + # Persistent runners may still hold the retired glibc submodule's work tree. + rm -rf glibc .git/modules/glibc + git submodule update --quiet --init --depth=1 --recursive --jobs 8 # Persistent runners may hold submodule work trees damaged by earlier jobs (tracked files # deleted or modified); `submodule update` does not repair them when HEAD already matches. git submodule foreach --recursive --quiet 'git reset -q --hard && git clean -qffdx' diff --git a/.gitmodules b/.gitmodules index 729c107..45e5329 100644 --- a/.gitmodules +++ b/.gitmodules @@ -90,9 +90,3 @@ [submodule "cflags"] path = cflags url = https://github.com/elide-dev/cflags.git -[submodule "glibc"] - path = glibc - url = https://sourceware.org/git/glibc.git - branch = release/2.34/master - shallow = true - ignore = dirty diff --git a/README.md b/README.md index 6e2fec7..2b0cf5f 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Elide Toolchain -A self-contained native toolchain: LLVM 23 (clang, lld, BOLT, Polly), libc++ / libc++abi / libunwind, compiler-rt, and a full tree of pre-built static libraries (zlib-ng, zstd, brotli, snappy, lz4, crc32c, AWS-LC, mimalloc, libsqlite3elide, and optionally OpenSSL, zlib, SQLite, SQLCipher, Cap'n Proto, hiredis, LevelDB), all compiled with one consistent flags profile. Linux bundles carry two sysroots, fully static **musl** (with mimalloc built into `libc.a`) and **glibc 2.34**; macOS bundles carry a component overlay on top of the system SDK. It is built from source, one bundle per host OS/arch, and is used by Elide, Komodo, Bali (crema-jit) and GraalVM `native-image` builds (`--libc=musl`). +A self-contained native toolchain: LLVM 23 (clang, lld, BOLT, Polly), libc++ / libc++abi / libunwind, compiler-rt, and a full tree of pre-built static libraries (zlib-ng, zstd, brotli, snappy, lz4, crc32c, AWS-LC, mimalloc, libsqlite3elide, and optionally OpenSSL, zlib, SQLite, SQLCipher, Cap'n Proto, hiredis, LevelDB), all compiled with one consistent flags profile. Linux bundles carry two sysroots, fully static **musl** (with mimalloc built into `libc.a`) and **glibc 2.17**; macOS bundles carry a component overlay on top of the system SDK. It is built from source, one bundle per host OS/arch, and is used by Elide, Komodo, Bali (crema-jit) and GraalVM `native-image` builds (`--libc=musl`). Releases are `elide-toolchain---.tar.xz`, each with a `.sha256` and a CycloneDX SBOM, on [GitHub Releases](https://github.com/elide-dev/toolchain/releases) (tags `vYYYY.M.N`; the month is not zero-padded, e.g. `v2026.9.0`), mirrored to `https://static.elideusercontent.com/toolchain//`. @@ -16,7 +16,7 @@ Each bundle targets its own OS and architecture (no cross-OS or cross-arch targe Floors: -- **glibc 2.34.** Every glibc-targeted binary, including the bundled clang and lld, references no symbol version newer than `GLIBC_2.34` (RHEL 9, AL2023, Ubuntu 22.04, Debian 12 and newer). Older systems are served by static musl. +- **glibc 2.17.** Every glibc-targeted binary, including the bundled clang and lld, references no symbol version newer than `GLIBC_2.17` (RHEL/CentOS 7, Amazon Linux 2, Ubuntu 14.04, Debian 8 and newer). The gnu sysroot is CentOS 7.9's final glibc 2.17 build (prebuilt RPMs pinned by SHA256 in `versions.env`) over current Linux UAPI headers. Code built against it sees glibc 2.17 headers, so newer interfaces (`getrandom`, `getentropy`, `statx`, …) are absent and libraries fall back to their syscall or `/dev/urandom` paths. - **macOS 12.0** (`minos` <= 12.0). - **Host ISA:** x86-64-v3 (AVX2) on amd64, `armv8.2-a+crypto+crc+dotprod` on arm64. The shipped tools are built with the same `-march` as the code they produce, so they need such a host. @@ -68,7 +68,7 @@ export ELIDE_TOOLCHAIN_HOME=$PWD/elide-toolchain PATH=$PWD/elide-toolchain/bin:$ ## Use -Invoke `-clang` / `-clang++`; clang loads `bin/.cfg`, which supplies `--target`, `--sysroot`, `-rtlib=compiler-rt`, `-unwindlib=libunwind`, `-stdlib=libc++` and `-fuse-ld=lld`. Plain `bin/clang` (and `clang --target=`) auto-loads the cfg too: plain `clang` loads the host's default-triple cfg, which is the gnu triple on Linux and the darwin triple on macOS. Pass `--no-default-config` for a bare clang. The bundle is relocatable. For fully static output use the musl triple with `-static`; static linking of the gnu triple is unsupported. +Invoke `-clang` / `-clang++`; clang loads `bin/.cfg`, which supplies `--target`, `--sysroot`, `-rtlib=compiler-rt`, `-unwindlib=libunwind`, `-stdlib=libc++` and `-fuse-ld=lld`. glibc 2.17 keeps `libpthread`, `libdl` and `librt` out of `libc`; the gnu sysroot's `libc.so` linker script pulls in `libpthread` and `libdl` as needed (as glibc 2.34+ does by merging them), so only `librt` users (`shm_open`, `timer_create`, …) must add `-lrt`. Plain `bin/clang` (and `clang --target=`) auto-loads the cfg too: plain `clang` loads the host's default-triple cfg, which is the gnu triple on Linux and the darwin triple on macOS. Pass `--no-default-config` for a bare clang. The bundle is relocatable. For fully static output use the musl triple with `-static`; static linking of the gnu triple is unsupported. ```sh x86_64-unknown-linux-musl-clang hello.c -static -o hello @@ -197,7 +197,7 @@ elide-toolchain/ /c++/v1/__config_site sysroot/ -unknown-linux-musl/usr/{include,lib} # musl+mimalloc, kernel headers, components - -unknown-linux-gnu/usr/{include,lib} # glibc 2.34, kernel headers, components, libmimalloc.a + -unknown-linux-gnu/usr/{include,lib} # glibc 2.17, kernel headers, components, libmimalloc.a /usr/lib/libelidealloc-shim.a, usr/include/elidealloc-shim.h -apple-darwin/usr/{include,lib} # macOS component overlay (no SDK) share/elide-toolchain/ @@ -228,9 +228,9 @@ A sanitizer add-on adds `lib///` (instrumented libc++), `sysroot/-clang`, installing `.pc` files | | 60 | `sanitizer-addons` | With `BUILD_SANITIZER_VARIANTS=yes`: per sanitizer (asan/tsan/msan, gnu), instrumented libc++ and components and the `sysroot/+` farm | @@ -329,12 +329,12 @@ Stage 95 (`scripts/verify/checks.sh`) runs against a fresh extraction of the pac - **components:** a program links against every enabled component. On Linux, a `-shared` object also links `libssl.a`/`libcrypto.a` cleanly under `-z defs` (the ACCP/JNI case), and for gnu it stays within the glibc floor. - **bitcode:** every member of every sysroot archive and of the libc++ runtimes is LLVM bitcode (raw or the Mach-O wrapper) or an object with a `.llvm.lto` section, produced by the bundle's LLVM major. Each occurrence of a duplicated member name is checked. Exempt: compiler-rt, glibc's own archives (gnu only), musl's empty stub archives, and hand-written assembly. A member counts as assembly only if it is a native object with no `.llvm.lto` and no compiler `.comment`, and its source is assembly (a CMake `*.S.o`/`*.s.o`/`*.asm.o` object, or a musl `src/*//*.s` source). - **rust:** when `rustc` and the target's std are installed, a hello world with a caught panic links through `-clang` and runs (musl: `+crt-static`; gnu: within the glibc floor, no `libgcc_s`). Otherwise it is skipped with a warning. -- **glibc floor (gnu):** no `GLIBC_x.y` above 2.34 and no `GLIBC_ABI_DT_RELR` in outputs or bundled ELFs; no `libstdc++`/`libgcc_s` in `NEEDED`. +- **glibc floor (gnu):** no `GLIBC_x.y` above 2.17 and no `GLIBC_ABI_DT_RELR` in outputs or bundled ELFs; no `libstdc++`/`libgcc_s` in `NEEDED`. - **interp (gnu):** `PT_INTERP` is the canonical loader path. - **musl libc (musl):** a `libc.a` member carries bitcode for the musl triple and native code, and a `-fno-lto` link works. - **gcc shims (musl):** `-linux-musl-gcc hello.c -static` links and runs. - **macOS minos / dylibs (macOS):** `minos` <= 12.0 and no unexpected dylib dependencies. -- **containers (Linux):** gnu smoke binaries and `clang --version` run inside `almalinux:9` and `ubuntu:22.04` (skipped without docker unless `REQUIRE_CONTAINER_CHECKS=yes`). +- **containers (Linux):** gnu smoke binaries and `clang --version` run inside `centos:7` (glibc 2.17), `amazonlinux:2` and `ubuntu:20.04` (skipped without docker unless `REQUIRE_CONTAINER_CHECKS=yes`). - **propeller (Linux):** the shipped tool reproduces upstream's golden profile from checked-in perf data; a relink of upstream's fixture with the generated profiles shows functions in profile order, `.text.hot`/`.text.split`, and cold parts in `.text.split`. A live check runs only on hosts with LBR/SPE (otherwise a warned skip; `REQUIRE_LBR=yes` makes it fail). - **dedubb (Linux):** directives from a labelled binary; a relink with them folds the duplicate into a branch to `DeduBB.master.0` and the program still works. Without directives, the compiler's output is deterministic and has no DeduBB trace. - **elidealloc shim:** the shim test (hot/cold/default mapping, all eight overloads, alignment, OOM, cross-thread frees, C API, stats, env tuning) links through the shipped `.pc` and passes. @@ -349,4 +349,4 @@ Unit tests and shellcheck: `tests/run.sh`. Per-stage checks: `tests/stages/*.che Component and consumer flags come from the `cflags/` submodule profiles: `cflags/cli/cflags.sh `, then the `cflags.local/` overlay, then `-march`/`-mtune` from `versions.env`. Compile profiles (`base`, `linux`, `linux-amd64`, ...) apply to every compilation unit and intermediate link; binary profiles (`*-bin`) apply only to a consumer's final link. Both Linux libcs use the `linux-` profile. The toolchain layer (libc, runtimes, LLVM, mimalloc) keeps its own tuned flags. -**glibc and DT_RELR.** `cflags/linux.txt` carries `-Wl,-z,pack-relative-relocs`, which makes lld emit a `GLIBC_ABI_DT_RELR` version need (glibc 2.36+). The build removes that flag for gnu triples whenever the glibc floor is below 2.36. Consumers applying the cflags profile themselves to gnu targets must drop it too, or their binaries will not load on glibc 2.34. +**glibc and DT_RELR.** `cflags/linux.txt` carries `-Wl,-z,pack-relative-relocs`, which makes lld emit a `GLIBC_ABI_DT_RELR` version need (glibc 2.36+). The build removes that flag for gnu triples whenever the glibc floor is below 2.36. Consumers applying the cflags profile themselves to gnu targets must drop it too, or their binaries will not load on older glibc. diff --git a/docs/notes/glibc-2.34-gcc15.md b/docs/notes/glibc-2.34-gcc15.md deleted file mode 100644 index e706e90..0000000 --- a/docs/notes/glibc-2.34-gcc15.md +++ /dev/null @@ -1,87 +0,0 @@ -# glibc 2.34 with host GCC 15 (spike) - -Result: glibc `release/2.34/master` builds with host GCC 15.2 with no source -changes, but needs two configure-level adjustments (see "Deviations"). -**No source patches are needed** (`src/patches/glibc/` is not created). -Two configure-level adjustments were needed, both caused by the host environment -rather than glibc source (see below). - -- Host: Ubuntu 25.10, `gcc (Ubuntu 15.2.0-4ubuntu4) 15.2.0`, `GNU ld (GNU Binutils for Ubuntu) 2.45` -- glibc: `release/2.34/master` @ `2b656ff94d` (posix: Reset wordexp_t fields with WRDE_REUSE) -- Build time: `make -j32` about 31-36 s wall (about 310 s user), 32 cores - -## Final configure line (run from an empty build dir; reuse verbatim in stage 20) - -Note: `../../../glibc/configure` below is spike-relative; Task 8 should use an -absolute path to `glibc/configure`. - -```bash -env -u CFLAGS -u CXXFLAGS -u LDFLAGS ../../../glibc/configure \ - CC=gcc CXX=false CFLAGS="-O2 -std=gnu11" \ - --prefix=/usr --libdir=/usr/lib --libexecdir=/usr/lib libc_cv_slibdir=/usr/lib \ - --with-headers="$SYSROOT/usr/include" \ - --enable-kernel=4.18 --enable-stack-protector=strong --enable-bind-now \ - --disable-werror --disable-profile --without-selinux -make -j"$(nproc)" -make install DESTDIR="$SYSROOT" -``` - -## Deviations from the spec's line (no patch required) - -1. `CXX=false` instead of `CXX=g++`. With a C++ compiler configured, glibc builds - the test-support helper `support/links-dso-program` against the host - `libstdc++`/`libgcc_s`, which reference symbols newer than 2.34 - (`_dl_find_object@GLIBC_2.35`, `arc4random@GLIBC_2.36`, - `__isoc23_strtoul@GLIBC_2.38`) -> link failure. `CXX=false` makes configure's - C++ link check fail, so `CXX=` is empty and glibc uses `links-dso-program-c`. - (`CXX=` alone does not work; configure falls back to g++.) glibc itself needs no C++. -2. `--without-selinux`. configure auto-detects host libselinux, then the build uses - `-nostdinc` and cannot find `selinux/selinux.h` in `links-dso-program-c.c`. - Disabling it is also desirable for a portable sysroot. - -## Patches - -None. - -## Verification - -- `readelf -V usr/lib/libc.so.6`: max symbol version `GLIBC_2.34` -- `usr/lib/ld-linux-x86-64.so.2` exists (238448 bytes) -- `lib64/ld-linux-x86-64.so.2` is NOT created by glibc with `--libdir=/usr/lib - libc_cv_slibdir=/usr/lib`; **Task 8 must create the `lib64/ld-linux-x86-64.so.2 -> - ../usr/lib/ld-linux-x86-64.so.2` link**. A test program linked with `--sysroot` - has interpreter `/lib64/ld-linux-x86-64.so.2`. -- `gcc --sysroot=... t.c` links; `LINK-OK` (ran via the host loader because the - sysroot lacks the lib64 link); also ran via the new loader with `--library-path`. - -## Floor / RELR verification (all glibc shared objects) - -Run in `out/spike/sysroot/usr/lib` over all 23 real (non-symlink) ELF `*.so*` -files, including `ld-linux-x86-64.so.2` and `libc.so.6`: - -```bash -for f in *.so*; do [ -L "$f" ] && continue; file -b "$f" | grep -q '^ELF' && readelf -V "$f"; done \ - | grep -oE 'GLIBC_[0-9.]+' | sort -uV | tail -1 # -> GLIBC_2.34 -for f in *.so*; do [ -L "$f" ] && continue; file -b "$f" | grep -q '^ELF' && readelf -d "$f"; done \ - | grep -E 'RELR|RELRSZ|RELRENT' # -> none found -for f in *.so*; do [ -L "$f" ] && continue; readelf -V "$f" | grep GLIBC_ABI_DT_RELR; done # -> none found -``` - -- Highest numeric version needed/defined anywhere: `GLIBC_2.34` (nothing above). -- `GLIBC_ABI_DT_RELR`: none found. -- `RELR` / `RELRSZ` / `RELRENT` dynamic entries: none found. -- Other non-numeric version tags present (expected): `GLIBC_PRIVATE` and - `GLIBC_ABI_DT_X86_64_PLT` (in libc.so.6; an x86_64 PLT ABI tag, unrelated to RELR). - -## Kernel headers (for Task 7) - -- Longterm kernel: `6.18.55` (picked as newest `longterm` in kernel.org releases.json) -- URL: `https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.18.55.tar.xz` -- sha256: `f410638061a165c12f42ab871d2f3fcd525515359b5faeee80969cff84524df9` -- `make ARCH=x86 INSTALL_HDR_PATH=/usr headers_install` - -## Submodule notes - -`git submodule add --depth 1 -b release/2.34/master` fails (the shallow clone -fetches only the default branch). The submodule was added without `--depth` -(full clone) and `shallow = true` / `ignore = dirty` set in `.gitmodules`. diff --git a/glibc b/glibc deleted file mode 160000 index 2b656ff..0000000 --- a/glibc +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 2b656ff94d72f93c84d8da2e7c76456c1994f02e diff --git a/scripts/bump-submodules.sh b/scripts/bump-submodules.sh index 8fad670..434e082 100755 --- a/scripts/bump-submodules.sh +++ b/scripts/bump-submodules.sh @@ -20,7 +20,6 @@ brotli|tag|v[0-9]+\.[0-9]+\.[0-9]+ capnp|tag|v1\.[0-9]+\.[0-9]+ cflags|branch|main crc32c|tag|[0-9]+\.[0-9]+\.[0-9]+ -glibc|branch|release/2.34/master hiredis|tag|v[0-9]+\.[0-9]+\.[0-9]+ leveldb|tag|[0-9]+\.[0-9]+ llvm|tag|llvmorg-23\.[0-9]+\.[0-9]+ diff --git a/scripts/gen-manifest.py b/scripts/gen-manifest.py index c159fb4..fd89ecc 100755 --- a/scripts/gen-manifest.py +++ b/scripts/gen-manifest.py @@ -56,6 +56,13 @@ def component_info(env, path): return {"version": env.get(v + "_VERSION") or env.get(v + "_REF", ""), "revision": env.get(v + "_REV", "")} +def components(env, host_os): + comps = {p: component_info(env, p) for p in submodules()} + if host_os == "linux": + comps["glibc"] = {"version": env["GLIBC_VERSION"], "revision": env["GLIBC_RPM_RELEASE"]} + return dict(sorted(comps.items())) + + def libc_of(triple): if triple.endswith("-linux-musl"): return "musl" @@ -70,7 +77,7 @@ def target_entry(env, triple): if libc == "musl": entry.update(libcVersion=env["MUSL_VERSION"], libcRevision=env.get("MUSL_REV", "")) elif libc == "glibc": - entry.update(libcVersion=env["GLIBC_FLOOR"], libcRevision=env.get("GLIBC_REV", "")) + entry.update(libcVersion=env["GLIBC_FLOOR"], libcRevision=env.get("GLIBC_RPM_RELEASE", "")) else: entry["macosMin"] = env["MACOS_MIN"] if libc != "darwin": @@ -145,7 +152,7 @@ def manifest(env): "llvmMajor": env["LLVM_VERSION"].split(".")[0], "targets": [target_entry(env, t) for t in triples], "enabledComponents": os.environ.get("ENABLED_COMPONENTS", "").split(), - "components": {p: component_info(env, p) for p in sorted(submodules())}, + "components": components(env, host_os), "cflagsProfile": f"{host_os}-{host_arch}", "features": features(env, host_os, triples), **sanitizer_info(), @@ -160,6 +167,8 @@ def sanitizer_info(): def purl(url, name, version, rev): + if name == "glibc": + return f"pkg:rpm/centos/glibc@{version}-{rev}?distro=centos-7.9.2009" m = re.match(r"https://github\.com/([^/]+)/([^/.]+)(\.git)?$", url) if m: return f"pkg:github/{m.group(1)}/{m.group(2)}@{rev or version}" diff --git a/scripts/lib/cmake.sh b/scripts/lib/cmake.sh index 46afe4c..5054e49 100644 --- a/scripts/lib/cmake.sh +++ b/scripts/lib/cmake.sh @@ -52,6 +52,16 @@ cmake_link_pool_args() { printf '%s\n' "-DCMAKE_JOB_POOLS=link=${LINK_JOBS:-2}" -DCMAKE_JOB_POOL_LINK=link } +# libcxxabi_libc_args TRIPLE — STATIC_LIBRARY try-compiles make check_library_exists always pass, +# so state what the libc lacks: __cxa_thread_atexit_impl (musl; glibc < 2.18). Without this, +# libc++abi references it strongly and thread_local objects with destructors fail to link. +libcxxabi_libc_args() { + case "$(triple_libc "$1")" in + musl) echo -DLIBCXXABI_HAS_CXA_THREAD_ATEXIT_IMPL=OFF ;; + gnu) if version_lt "$GLIBC_FLOOR" 2.18; then echo -DLIBCXXABI_HAS_CXA_THREAD_ATEXIT_IMPL=OFF; fi ;; + esac +} + # cmake_target TRIPLE SRC BUILD PREFIX [ARGS...] — configure, build and install. cmake_target() { local t="$1" src="$2" build="$3" prefix="$4" diff --git a/scripts/lib/sanitizers.sh b/scripts/lib/sanitizers.sh index d5beb98..d14d1a1 100644 --- a/scripts/lib/sanitizers.sh +++ b/scripts/lib/sanitizers.sh @@ -261,6 +261,7 @@ san_cxx_args() { -DLIBCXX_INSTALL_LIBRARY_DIR="lib/$t" \ -DLIBCXXABI_INSTALL_LIBRARY_DIR="lib/$t" \ -DLIBUNWIND_INSTALL_LIBRARY_DIR="lib/$t" + libcxxabi_libc_args "$t" } # prune_sanitizer_runtimes PREFIX TRIPLE — keep only the runtimes the matrix ships (compiler-rt diff --git a/scripts/rpm-extract.py b/scripts/rpm-extract.py new file mode 100755 index 0000000..e9996de --- /dev/null +++ b/scripts/rpm-extract.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python3 +"""Extract an RPM's payload (gzip or xz cpio newc) into DEST. Stdlib only. + +Usage: rpm-extract.py RPM DEST +Only regular files, directories and symlinks are written; paths are confined to DEST. +""" + +import gzip +import lzma +import os +import struct +import sys + + +def skip_header(f, pad): + magic = f.read(8) + if magic[:3] != b"\x8e\xad\xe8": + sys.exit("rpm-extract: bad header magic") + nindex, hsize = struct.unpack(">II", f.read(8)) + size = nindex * 16 + hsize + if pad: + size += (8 - size % 8) % 8 + f.seek(size, 1) + + +def payload(f): + head = f.read(6) + f.seek(-6, 1) + if head.startswith(b"\x1f\x8b"): + return gzip.GzipFile(fileobj=f) + if head.startswith(b"\xfd7zXZ"): + return lzma.LZMAFile(f) + sys.exit("rpm-extract: unsupported payload compression") + + +def main(rpm, dest): + dest = os.path.realpath(dest) + with open(rpm, "rb") as f: + if f.read(4) != b"\xed\xab\xee\xdb": + sys.exit("rpm-extract: not an RPM") + f.seek(96) + skip_header(f, pad=True) + skip_header(f, pad=False) + cpio = payload(f) + while True: + hdr = cpio.read(110) + if hdr[:6] != b"070701": + sys.exit("rpm-extract: bad cpio header") + fields = [int(hdr[6 + i * 8:14 + i * 8], 16) for i in range(13)] + mode, filesize, namesize = fields[1], fields[6], fields[11] + name = cpio.read(namesize)[:-1].decode() + cpio.read((4 - (110 + namesize) % 4) % 4) + data = cpio.read(filesize) + cpio.read((4 - filesize % 4) % 4) + if name == "TRAILER!!!": + break + rel = name[2:] if name.startswith("./") else name.lstrip("/") + out = os.path.join(os.path.realpath(os.path.join(dest, os.path.dirname(rel))), os.path.basename(rel)) + if not out.startswith(dest + os.sep): + sys.exit(f"rpm-extract: path escapes destination: {name}") + kind = mode & 0o170000 + if kind == 0o040000: + os.makedirs(out, exist_ok=True) + continue + os.makedirs(os.path.dirname(out), exist_ok=True) + if os.path.lexists(out): + os.unlink(out) + if kind == 0o120000: + os.symlink(data.decode(), out) + elif kind == 0o100000: + with open(out, "wb") as o: + o.write(data) + os.chmod(out, mode & 0o755) + + +if __name__ == "__main__": + if len(sys.argv) != 3: + sys.exit(__doc__) + main(sys.argv[1], sys.argv[2]) diff --git a/scripts/stages/00-sources.sh b/scripts/stages/00-sources.sh index e46162c..7809c0a 100644 --- a/scripts/stages/00-sources.sh +++ b/scripts/stages/00-sources.sh @@ -18,10 +18,10 @@ check_submodules() { local missing missing="$(git -C "$ROOT_DIR" submodule status | awk '/^-/{print $2}' | xargs)" [ -z "$missing" ] || die "uninitialized submodules: $missing (run: git submodule update --init --depth=1 --recursive)" - # Our own src/patches series are applied in place by later stages (glibc: 20; llvm: 10/30/40; + # Our own src/patches series are applied in place by later stages (llvm: 10/30/40; # llvm-propeller: 45); take them back out first so only foreign modifications count as dirty. local c - for c in glibc llvm llvm-propeller; do + for c in llvm llvm-propeller; do if [ -d "$ROOT_DIR/$c" ]; then unapply_patches "$c" "$ROOT_DIR/$c"; fi done # Component sources are copied from the submodule work trees, so modified or deleted tracked diff --git a/scripts/stages/20-libc-gnu.sh b/scripts/stages/20-libc-gnu.sh index f34fac7..56afc0a 100644 --- a/scripts/stages/20-libc-gnu.sh +++ b/scripts/stages/20-libc-gnu.sh @@ -1,40 +1,31 @@ # shellcheck shell=bash -# Stage 20: glibc at GLIBC_FLOOR, from the glibc submodule (release/2.34/master), built with -# the host GCC (glibc 2.34 cannot be built with clang). Installed with slibdir=/usr/lib. +# Stage 20: glibc at GLIBC_FLOOR, from CentOS 7's prebuilt glibc RPMs (pinned in versions.env; +# 2.17 does not build with a current GCC or clang). Only libraries, crt objects, linker scripts +# and glibc's own headers are taken (the UAPI headers stay stage 00's), flattened into /usr/lib +# like a slibdir=/usr/lib build, with relative symlinks and /usr/lib linker-script paths. stage_applies() { [ "$HOST_OS" = linux ]; } +GLIBC_RPMS="glibc glibc-devel glibc-headers glibc-static" + stage_main() { - local t sysroot build cpu staging + local t sysroot cpu raw staging pkg rpm t="$(bundle_triple_for_libc gnu)" sysroot="$(sysroot_of "$t")" cpu="$(triple_cpu "$t")" - build="$BUILD_DIR/glibc" + raw="$BUILD_DIR/glibc-rpms" staging="$BUILD_DIR/glibc-staging" [ -f "$sysroot/usr/include/linux/version.h" ] || die "kernel headers missing in $sysroot; run 00-sources" - apply_patches glibc "$ROOT_DIR/glibc" - fresh_dir "$build" + fresh_dir "$raw" fresh_dir "$staging" - ( - cd "$build" || exit 1 - unset CFLAGS CXXFLAGS LDFLAGS CPPFLAGS CC CXX - # GCC 15 defaults to C23, which glibc < 2.39 does not build under; pin gnu11. - # CXX=false: a real host C++ compiler leaks >2.34 libstdc++ symbols into links-dso-program. - "$ROOT_DIR/glibc/configure" \ - CC=gcc CXX=false CFLAGS="-O2 -std=gnu11" \ - --prefix=/usr --libdir=/usr/lib --libexecdir=/usr/lib \ - libc_cv_slibdir=/usr/lib \ - --with-headers="$sysroot/usr/include" \ - --enable-kernel="$GLIBC_ENABLE_KERNEL" \ - --enable-stack-protector=strong --enable-bind-now \ - --disable-werror --disable-profile --without-selinux - make -j"$JOBS" - make install DESTDIR="$staging" - ) - (cd "$ROOT_DIR/glibc" && git checkout -q .) # leave the submodule pristine; patches live in src/patches - # The list comes from glibc's own staging install, never the live sysroot: a rerun on a built - # tree would otherwise list component archives and exempt them from the bitcode/floor checks. + for pkg in $GLIBC_RPMS; do + rpm="$(fetch_glibc_rpm "$pkg" "$cpu")" + python3 -I "$ROOT_DIR/scripts/rpm-extract.py" "$rpm" "$raw" + done + flatten_glibc "$raw" "$staging" + # The list comes from the staging tree, never the live sysroot: a rerun on a built tree would + # otherwise list component archives and exempt them from the bitcode/floor checks. (cd "$staging" && find . \( -type f -o -type l \) | sed 's#^\./##' | sort) > "$OUT_DIR/glibc-files.txt" cp -a "$staging"/. "$sysroot"/ ensure_loader_link "$sysroot" "$cpu" @@ -43,6 +34,50 @@ stage_main() { printf 'INPUT(-lunwind)\n' > "$sysroot/usr/lib/libgcc_s.so" } +# fetch_glibc_rpm PKG CPU — download (cached, sha256-checked) one pinned RPM; prints its path. +fetch_glibc_rpm() { + local pkg="$1" cpu="$2" key base sha name + key="${cpu^^}" + base="GLIBC_RPM_BASE_$key" + sha="GLIBC_RPM_SHA256_${pkg//-/_}" + sha="${sha^^}_$key" + if [ -z "${!base:-}" ] || [ -z "${!sha:-}" ]; then die "no glibc RPM pin for $pkg on $cpu"; fi + name="$pkg-$GLIBC_VERSION-$GLIBC_RPM_RELEASE.$cpu.rpm" + fetch_pinned "${!base}/$name" "${!sha}" "$CACHE_DIR/glibc-rpms/$name" + printf '%s\n' "$CACHE_DIR/glibc-rpms/$name" +} + +# flatten_glibc RAW STAGING — RAW's /lib, /lib64 and /usr/lib64 top-level entries into +# STAGING/usr/lib (symlinks re-pointed at the sibling basename), /usr/include as is. +flatten_glibc() { + local raw="$1" staging="$2" d f name target + mkdir -p "$staging/usr/lib" + cp -a "$raw/usr/include" "$staging/usr/include" + for d in lib lib64 usr/lib64; do + [ -d "$raw/$d" ] || continue + for f in "$raw/$d"/*; do + name="$(basename "$f")" + if [ -L "$f" ]; then + target="$(basename "$(readlink "$f")")" + ln -sfn "$target" "$staging/usr/lib/$name" + elif [ -f "$f" ]; then + cp -p "$f" "$staging/usr/lib/$name" + fi + done + done + for f in "$staging/usr/lib"/*; do + if [ -L "$f" ] && [ ! -e "$f" ]; then die "dangling glibc link $(basename "$f") -> $(readlink "$f")"; fi + if [ -f "$f" ] && ! is_elf "$f" && head -c 512 "$f" | grep -q 'GNU ld script'; then + sed -i -E 's#(/usr)?/lib(64)?/#/usr/lib/#g' "$f" + fi + done + # Like glibc >= 2.34, -lc also provides libpthread and libdl (as needed, ahead of libc as with + # an explicit -lpthread): libc++abi/libunwind need them, and their .deplibs are lost under LTO. + sed -i -E 's#^GROUP \( (/usr/lib/libc\.so\.6 )#GROUP ( AS_NEEDED ( /usr/lib/libpthread.so.0 /usr/lib/libdl.so.2 ) /usr/lib/libpthread_nonshared.a \1#' \ + "$staging/usr/lib/libc.so" + grep -q 'libpthread.so.0' "$staging/usr/lib/libc.so" || die "could not extend libc.so with libpthread/libdl" +} + # ensure_loader_link SYSROOT CPU — the canonical PT_INTERP path must exist inside the sysroot # so libc.so's AS_NEEDED(ld-linux…) resolves at link time. Relative, so the sysroot relocates. ensure_loader_link() { diff --git a/scripts/stages/30-runtimes.sh b/scripts/stages/30-runtimes.sh index 9be4a85..ebaa3ba 100644 --- a/scripts/stages/30-runtimes.sh +++ b/scripts/stages/30-runtimes.sh @@ -60,7 +60,7 @@ build_builtins() { build_cxx_runtimes() { local t="$1" b="$BUILD_DIR/runtimes/$1/cxx" args=() musl=OFF if [ "$(triple_libc "$t")" = musl ]; then musl=ON; fi - mapfile -t args < <(runtimes_common_args "$t") + mapfile -t args < <(runtimes_common_args "$t"; libcxxabi_libc_args "$t") # MemProf runtime (x86_64 gnu only). Later -D options override runtimes_common_args' # MEMPROF=OFF. The always-built libclang_rt.memprof.so must link against our sysroot: no # libstdc++ (SANITIZER_CXX_ABI=none), and lld + compiler-rt crt instead of the host ld. diff --git a/scripts/stages/40-llvm-stage2.sh b/scripts/stages/40-llvm-stage2.sh index 719b63d..3cfec12 100644 --- a/scripts/stages/40-llvm-stage2.sh +++ b/scripts/stages/40-llvm-stage2.sh @@ -1,5 +1,5 @@ # shellcheck shell=bash -# Stage 40: the shipped LLVM, built by stage-1 clang (via the gnu cfg) against our glibc 2.34 +# Stage 40: the shipped LLVM, built by stage-1 clang (via the gnu cfg) against our glibc 2.17 # sysroot, with static libc++/libunwind/compiler-rt and no shared libLLVM/libclang, so the # tools run on any glibc >= GLIBC_FLOOR host. lld gets zlib + zstd from stage 36. diff --git a/scripts/stages/45-propeller.sh b/scripts/stages/45-propeller.sh index 197518d..83db0a3 100644 --- a/scripts/stages/45-propeller.sh +++ b/scripts/stages/45-propeller.sh @@ -1,7 +1,7 @@ # shellcheck shell=bash # Stage 45: llvm-propeller's generate_propeller_profiles (Propeller layout profiles and DeduBB # directives), linked against the stage-2 LLVM build tree's static libraries with the stage-1 -# gnu cfg compiler (glibc 2.34 sysroot, static libc++), so it meets the glibc floor like the +# gnu cfg compiler (glibc 2.17 sysroot, static libc++), so it meets the glibc floor like the # rest of bin/. Third-party deps come from the stage-00 cache; no network. Linux only (Propeller # and BB address maps are ELF-only). diff --git a/scripts/verify/checks.sh b/scripts/verify/checks.sh index fdf9566..3517dd5 100644 --- a/scripts/verify/checks.sh +++ b/scripts/verify/checks.sh @@ -162,7 +162,7 @@ check_shims() { rm -rf "$tmp" } -# check_containers ROOT — gnu output and the shipped clang run on glibc-2.34-era distros. +# check_containers ROOT — gnu output and the shipped clang run on glibc-floor-era distros. check_containers() { local root="$1" gnu musl image cmd gnu="$(bundle_triple_for_libc gnu)" @@ -173,7 +173,7 @@ check_containers() { fi cmd="/smoke-gnu/hello-c && /smoke-gnu/hello-cxx && /smoke-musl/hello-c && /tc/bin/clang --version >/dev/null \ && /tc/bin/$gnu-clang /src/hello.c -o /tmp/h && /tmp/h" - for image in almalinux:9 ubuntu:22.04; do + for image in centos:7 amazonlinux:2 ubuntu:20.04; do if docker run --rm -v "$root:/tc:ro" -v "$(smoke_dir "$gnu"):/smoke-gnu:ro" -v "$(smoke_dir "$musl"):/smoke-musl:ro" \ -v "$ROOT_DIR/tests/fixtures:/src:ro" "$image" sh -c "$cmd" >/dev/null 2>"$VERIFY_DIR/docker.err"; then pass "container $image" diff --git a/scripts/verify/elf.sh b/scripts/verify/elf.sh index a4f39fb..6e46a70 100644 --- a/scripts/verify/elf.sh +++ b/scripts/verify/elf.sh @@ -18,7 +18,7 @@ glibc_needs() { } # glibc_floor_violations FILE — one line per requirement above GLIBC_FLOOR, plus any -# GLIBC_ABI_* (e.g. DT_RELR, DT_X86_64_PLT: absent from stock 2.34 hosts) or GLIBC_PRIVATE. +# GLIBC_ABI_* (e.g. DT_RELR, DT_X86_64_PLT: absent from older hosts) or GLIBC_PRIVATE. glibc_floor_violations() { local f="$1" v for v in $(glibc_needs "$f"); do diff --git a/tests/fixtures/hello.cpp b/tests/fixtures/hello.cpp index ba2b9da..7df05e4 100644 --- a/tests/fixtures/hello.cpp +++ b/tests/fixtures/hello.cpp @@ -3,13 +3,17 @@ #include #include +// A thread_local with a destructor needs __cxa_thread_atexit (libc's _impl, or libc++abi's own). +thread_local std::string tls; + int main() { std::string msg; std::thread worker([&] { try { throw std::runtime_error("hello from elide-toolchain"); } catch (const std::exception& e) { - msg = e.what(); + tls = e.what(); + msg = tls; } }); worker.join(); diff --git a/tests/stages/20-libc-gnu.check.sh b/tests/stages/20-libc-gnu.check.sh index 2ec815b..ba6ce78 100644 --- a/tests/stages/20-libc-gnu.check.sh +++ b/tests/stages/20-libc-gnu.check.sh @@ -11,8 +11,15 @@ t="$(bundle_triple_for_libc gnu)"; s="$(sysroot_of "$t")"; cpu="$(triple_cpu "$t for f in usr/lib/libc.so.6 usr/lib/libc.so usr/lib/libc.a usr/lib/crt1.o usr/lib/libc_nonshared.a usr/include/stdio.h "$(glibc_loader "$cpu")"; do assert_file "$s/$f" done -maxdef="$(readelf -V "$s/usr/lib/libc.so.6" | grep -oE 'GLIBC_2\.[0-9]+' | sort -uV | tail -1)" -assert_eq "$maxdef" "GLIBC_$GLIBC_FLOOR" "libc.so.6 defines up to the floor" +assert_contains "$(readelf -V "$s/usr/lib/libc.so.6")" "GLIBC_$GLIBC_FLOOR" "libc.so.6 defines the floor" +# Upstream aarch64 glibc 2.17 exports _mcount@@GLIBC_2.18 (only -pg code references it). +nm="$STAGE1_DIR/bin/llvm-nm" +newer="$("$nm" -D --defined-only "$s/usr/lib/libc.so.6" | awk '{print $NF}' | grep -E '@@?GLIBC_[0-9]' \ + | grep -v '^GLIBC_' | grep -v '^_mcount@' | while IFS= read -r sym; do + v="${sym##*GLIBC_}"; if version_lt "$GLIBC_FLOOR" "$v"; then echo "$sym"; fi; done)" +assert_eq "$newer" "" "libc.so.6 defines nothing above the floor" +assert_contains "$(cat "$s/usr/lib/libc.so")" "AS_NEEDED ( /usr/lib/libpthread.so.0 /usr/lib/libdl.so.2 )" "-lc provides libpthread/libdl" +assert_not_contains "$(cat "$s/usr/lib/libc.so" "$s/usr/lib/libpthread.so")" "lib64" "linker scripts use /usr/lib" loader_target="$(readlink "$s/$(glibc_loader "$cpu")" || true)" assert_not_contains "x$loader_target" "x/" "loader link is relative" assert_file "$OUT_DIR/glibc-files.txt" diff --git a/tests/unit/cmake.test.sh b/tests/unit/cmake.test.sh index c8c4e19..8b012b5 100644 --- a/tests/unit/cmake.test.sh +++ b/tests/unit/cmake.test.sh @@ -69,6 +69,10 @@ for f in 10-llvm-stage1 30-runtimes 40-llvm-stage2; do done assert_contains "$(sed -n '/^san_runtimes_base_args()/,/^}/p' "$ROOT_DIR/scripts/lib/sanitizers.sh")" "llvm_link_jobs_args" "stages 31/60 cap links" assert_contains "$(cat "$ROOT_DIR/scripts/stages/45-propeller.sh")" "cmake_link_pool_args" "propeller uses a link pool" +assert_eq "$(libcxxabi_libc_args x86_64-unknown-linux-musl)" "-DLIBCXXABI_HAS_CXA_THREAD_ATEXIT_IMPL=OFF" "musl lacks __cxa_thread_atexit_impl" +assert_eq "$(GLIBC_FLOOR=2.17 libcxxabi_libc_args x86_64-unknown-linux-gnu)" "-DLIBCXXABI_HAS_CXA_THREAD_ATEXIT_IMPL=OFF" "glibc 2.17 lacks it" +assert_eq "$(GLIBC_FLOOR=2.18 libcxxabi_libc_args x86_64-unknown-linux-gnu)" "" "glibc 2.18 has it" +assert_contains "$(san_cxx_args x86_64-unknown-linux-musl | xargs)" "-DLIBCXXABI_HAS_CXA_THREAD_ATEXIT_IMPL=OFF" "variant libc++abi too" rm -rf "$T" diff --git a/tests/unit/elf.test.sh b/tests/unit/elf.test.sh index 321bbe3..5b78827 100755 --- a/tests/unit/elf.test.sh +++ b/tests/unit/elf.test.sh @@ -37,7 +37,8 @@ v="$(glibc_floor_violations x)" assert_contains "$v" "GLIBC_2.38" assert_contains "$v" "GLIBC_ABI_DT_RELR" assert_contains "$v" "GLIBC_ABI_DT_X86_64_PLT" -assert_not_contains "$v" "GLIBC_2.34" +assert_not_contains "$v" "GLIBC_2.2.5" +if version_lt "$GLIBC_FLOOR" 2.34; then assert_contains "$v" "GLIBC_2.34"; else assert_not_contains "$v" "GLIBC_2.34"; fi assert_eq "$(needed_libs x | xargs)" "libc.so.6 libstdc++.so.6" assert_eq "$(interp_of x)" "/lib64/ld-linux-x86-64.so.2" diff --git a/tests/unit/frontends.test.sh b/tests/unit/frontends.test.sh index 85ddd29..23a8590 100644 --- a/tests/unit/frontends.test.sh +++ b/tests/unit/frontends.test.sh @@ -17,6 +17,7 @@ assert_contains "$cfg" "-unwindlib=libunwind" assert_contains "$cfg" "-stdlib=libc++" assert_contains "$cfg" "-fuse-ld=lld" assert_not_contains "$cfg" "-static" "cfg never forces static" +assert_not_contains "$cfg" "-lpthread" "cfg adds no link inputs (they would leak into -r links)" dcfg="$(render_cfg arm64-apple-darwin)" assert_contains "$dcfg" "--target=arm64-apple-macos$MACOS_MIN" assert_contains "$dcfg" "-mmacosx-version-min=$MACOS_MIN" diff --git a/tests/unit/manifest.test.sh b/tests/unit/manifest.test.sh index 6da29a7..5f397a7 100644 --- a/tests/unit/manifest.test.sh +++ b/tests/unit/manifest.test.sh @@ -14,10 +14,10 @@ m="$(python3 "$ROOT_DIR/scripts/gen-manifest.py" manifest)" q() { printf '%s' "$m" | python3 -c "import json,sys; d=json.load(sys.stdin); print($1)"; } assert_eq "$(q 'd["name"]')" "elide-toolchain" assert_eq "$(q 'd["version"]')" "$TOOLCHAIN_VERSION" -assert_eq "$(q 'd["host"]["glibcFloor"]')" "2.34" +assert_eq "$(q 'd["host"]["glibcFloor"]')" "$GLIBC_FLOOR" assert_eq "$(q 'd["llvmMajor"]')" "$LLVM_MAJOR" assert_eq "$(q '" ".join(t["triple"] for t in d["targets"])')" "x86_64-unknown-linux-musl x86_64-unknown-linux-gnu" -assert_eq "$(q '[t["libcVersion"] for t in d["targets"] if t["libc"]=="glibc"][0]')" "2.34" +assert_eq "$(q '[t["libcVersion"] for t in d["targets"] if t["libc"]=="glibc"][0]')" "$GLIBC_FLOOR" assert_eq "$(q '" ".join(d["enabledComponents"])')" "zlib-ng zstd aws-lc" assert_eq "$(q 'd["components"]["llvm"]["version"]')" "$LLVM_VERSION" assert_eq "$(q 'd["features"]["memprof"]["runtimeTargets"]')" "['x86_64-unknown-linux-gnu']" diff --git a/versions.env b/versions.env index bc4240c..16d5978 100644 --- a/versions.env +++ b/versions.env @@ -3,12 +3,10 @@ # read by scripts/gen-manifest.py. Component pins are generated by scripts/bump-submodules.sh. TOOLCHAIN_NAME=elide-toolchain -TOOLCHAIN_VERSION=2026.10.0 +TOOLCHAIN_VERSION=2026.10.1 # Floors -GLIBC_FLOOR=2.34 -GLIBC_BRANCH=release/2.34/master -GLIBC_ENABLE_KERNEL=4.18 +GLIBC_FLOOR=2.17 MACOS_MIN=12.0 # Code generation (Linux; darwin uses the cflags profile's own -march/-mcpu) @@ -49,6 +47,21 @@ LLVM_PREBUILT_LINUX_ARM64_ICU_SHA256=ac68372cf4a976e6a206858fd9b28c68e49d37d650b # libc MUSL_VERSION=1.2.5 +# glibc for the gnu sysroots: CentOS 7.9's final glibc build, prebuilt (2.17 does not build with +# a current GCC). SHA256 = the repodata digests. Stage 20 extracts these over the UAPI headers. +GLIBC_VERSION=2.17 +GLIBC_RPM_RELEASE=326.el7_9.3 +GLIBC_RPM_BASE_X86_64=https://vault.centos.org/7.9.2009/updates/x86_64/Packages +GLIBC_RPM_BASE_AARCH64=https://vault.centos.org/altarch/7.9.2009/updates/aarch64/Packages +GLIBC_RPM_SHA256_GLIBC_X86_64=d2c498e78241cc2d36124d37d4771f877da25de95d6a31c1ad42e1287fdda746 +GLIBC_RPM_SHA256_GLIBC_DEVEL_X86_64=9c54883a611d1da210a5b0909cd7fd415b6c99473614fab81bae9df9cf8c6be2 +GLIBC_RPM_SHA256_GLIBC_HEADERS_X86_64=91de6d1a2c900bf6a030d637e635ba8bed416176970159ef63c61ba70f93a275 +GLIBC_RPM_SHA256_GLIBC_STATIC_X86_64=df21a3fb768e603f322d9c16831a48f1a953dcc954f4b9b79e30a3e77107cd77 +GLIBC_RPM_SHA256_GLIBC_AARCH64=98d52e08fed74855f8bec16abd64c6bc50554bb0efe175e7f3c490c9f24de00a +GLIBC_RPM_SHA256_GLIBC_DEVEL_AARCH64=884cb8c9aae5d2943dfa8fdb48a9afe7de1cbd171c7738605dcf4196c3e8b24d +GLIBC_RPM_SHA256_GLIBC_HEADERS_AARCH64=299b2ec1e39fc560ef7123d4ed705f906d6ad4c604e2a6fa8b0dc7eadba789df +GLIBC_RPM_SHA256_GLIBC_STATIC_AARCH64=3945fe93c62570fd0de46222870b02ac89b403c2c132c27a4968854a5b5f0700 + # Linux UAPI headers installed into Linux sysroots (latest longterm at pin time) LINUX_HEADERS_VERSION=6.18.55 LINUX_HEADERS_SHA256=f410638061a165c12f42ab871d2f3fcd525515359b5faeee80969cff84524df9 @@ -76,8 +89,6 @@ CFLAGS_REV=ec0e4d69ed22347bd96a561b6a96b3eca9c882fe CFLAGS_REF=main CRC32C_REV=02e65f4fd3065d27b2e29324800ca6d04df16126 CRC32C_VERSION=1.1.2 -GLIBC_REV=2b656ff94d72f93c84d8da2e7c76456c1994f02e -GLIBC_REF=release/2.34/master HIREDIS_REV=616f2286ba5503f74ae96e720623fa11dbc690af HIREDIS_VERSION=1.4.1 LEVELDB_REV=99b3c03b3284f5886f9ef9a4ef703d57373e61be