Skip to content

glibc: lower the floor to 2.17 - #9

Merged
Sam Gammon (sgammon) merged 4 commits into
mainfrom
feat/glibc-2.17
Oct 18, 2026
Merged

Sam Gammon (sgammon) merged 4 commits into
mainfrom
feat/glibc-2.17

Conversation

@sgammon

@sgammon Sam Gammon (sgammon) commented Oct 18, 2026 •

Copy link
Copy Markdown
Member

Lowers the gnu sysroot's glibc from 2.34 to 2.17 on linux-amd64 and linux-arm64, so Elide (which links against this sysroot) runs on RHEL/CentOS 7-8, Amazon Linux 2, Ubuntu 20.04 and Debian 11 (elide-dev/elide#1900). Bumps TOOLCHAIN_VERSION to 2026.10.1.

Changes

  • Stage 20: glibc 2.17 doesn't build with a current GCC or clang. Stage 20 now takes CentOS 7.9's final glibc build (glibc, glibc-devel, glibc-headers, glibc-static 2.17-326.el7_9.3, x86_64 from vault 7.9.2009/updates, aarch64 from AltArch). Each RPM is pinned in versions.env by its SHA256, cross-checked against the repodata digests. scripts/rpm-extract.py unpacks them using only the Python stdlib, on top of stage 00's current UAPI headers; CentOS's 3.10 kernel-headers aren't used. Everything is flattened into /usr/lib with relative symlinks, and linker scripts point at /usr/lib, the same layout as before. The glibc submodule and the CI sourceware/mirror fallback are removed.
  • Linking: below 2.34, libpthread and libdl are still separate from libc. libc++abi and libunwind need them, and their .deplibs don't reach lld under LTO. The sysroot's libc.so linker script now lists AS_NEEDED(libpthread.so.0 libdl.so.2) and libpthread_nonshared.a ahead of libc.so.6, which is the order an explicit -lpthread gives. As a result -lc behaves as it does on 2.34+, on every link path (cfg, bare clang, GNU ld, rust-lld), and -r links are left alone. librt users must still add -lrt.
  • runtimes: the runtimes' STATIC_LIBRARY try-compiles make check_library_exists always pass. As a result libc++abi took a strong reference to __cxa_thread_atexit_impl, which glibc only has from 2.18 and musl doesn't have at all. A thread_local with a destructor therefore failed to link on glibc 2.17, and it already fails on musl in 2026.10.0. The fix sets LIBCXXABI_HAS_CXA_THREAD_ATEXIT_IMPL=OFF for both, and hello.cpp now covers this case.
  • verify: the floor check enforces GLIBC_2.17. Container checks now run on centos:7, amazonlinux:2 and ubuntu:20.04. The manifest's libcRevision is the RPM release.

aarch64 note: upstream glibc 2.17 on aarch64 exports _mcount@@GLIBC_2.18. Only -pg code references it, and the floor check would still catch any such reference.

No release, tag or upload is part of this PR.

The runtimes build with CMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY, so check_library_exists
never links and always passes. libc++abi then referenced __cxa_thread_atexit_impl strongly, and
any thread_local with a destructor failed to link on musl (already broken in 2026.10.0) and on
glibc 2.17. Stage 30 and the add-on libc++ now set LIBCXXABI_HAS_CXA_THREAD_ATEXIT_IMPL=OFF there,
using libc++abi's own fallback; hello.cpp covers it.

Signed-off-by: Sam Gammon <sam@elide.dev>
Elide links against the gnu sysroot, so its 2.34 floor locked out RHEL/CentOS 7-8, Amazon Linux 2,
Ubuntu 20.04 and Debian 11 (elide-dev/elide#1900). glibc 2.17 does not build with a current GCC
or clang, so stage 20 now unpacks CentOS 7.9's final glibc, glibc-devel, glibc-headers and
glibc-static RPMs (2.17-326.el7_9.3, x86_64 and AltArch aarch64, SHA256-pinned to the repodata
digests) with a stdlib-only extractor, over stage 00's current UAPI headers. Libraries are
flattened into /usr/lib like the old slibdir=/usr/lib build, with relative symlinks and /usr/lib
linker-script paths. The glibc submodule and its CI fetch fallback are gone.

Below 2.34, libpthread, libdl and librt are separate from libc: the gnu cfg links them
--as-needed through link-only ($) options so C++ (libc++abi's pthread_key_create, libunwind's
dladdr) links as before. The floor check, container checks (centos:7, amazonlinux:2,
ubuntu:20.04), manifest (libcRevision = RPM release) and docs follow. TOOLCHAIN_VERSION 2026.10.1.

Signed-off-by: Sam Gammon <sam@elide.dev>
The `$` cfg inputs are added to every link, including `clang -r`: libFuzzer's partial link of
its private libc++ pulled static libpthread.a into fuzzer.o, which then failed to link
(R_X86_64_32 against __stack_user). They were never needed: libc++, libc++abi and libunwind
already name pthread and dl in .deplibs (C_SUPPORTS_COMMENT_LIB_PRAGMA), which lld honours.

Signed-off-by: Sam Gammon <sam@elide.dev>
libc++abi and libunwind name pthread and dl in .deplibs, but under LTO the member that needs
pthread_rwlock_* comes from bitcode and its deplibs never reach lld, so C programs linking the
static unwinder with -flto failed (mimalloc's CMake probe in stage 35). The sysroot's libc.so
script now lists AS_NEEDED(libpthread.so.0 libdl.so.2) and libpthread_nonshared.a ahead of
libc.so.6 (the order an explicit -lpthread gives), so every link path (cfg, bare clang, GNU ld,
rust-lld) resolves them and -r links are untouched.

Signed-off-by: Sam Gammon <sam@elide.dev>
@sgammon
Sam Gammon (sgammon) marked this pull request as ready for review October 18, 2026 22:54
@sgammon
Sam Gammon (sgammon) merged commit 171eb7c into main Oct 18, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant