From 7e2210ff712232ebfcbb5907d8528570b222144e Mon Sep 17 00:00:00 2001 From: Ophestra Date: Sun, 3 May 2026 19:46:07 +0900 Subject: [PATCH] internal/rosa/llvm: provide runtimes early in stage0 The LLVM build system fails to handle a dynamically linked toolchain correctly, and leaks the system installation during builds. Signed-off-by: Ophestra --- internal/rosa/all.go | 12 +++++ internal/rosa/llvm.go | 123 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 134 insertions(+), 1 deletion(-) diff --git a/internal/rosa/all.go b/internal/rosa/all.go index ef3275d6..a9c4ae56 100644 --- a/internal/rosa/all.go +++ b/internal/rosa/all.go @@ -178,6 +178,18 @@ const ( PresetUnexportedStart llvmSource = iota - 1 + // earlyCompilerRT is an early, standalone compiler-rt installation for the + // standalone runtimes build. + // + // earlyCompilerRT must only be loaded by [LLVM]. + earlyCompilerRT + // earlyRuntimes is an early, standalone installation of LLVM runtimes to + // work around the cmake build system leaking the system LLVM installation + // when invoking the newly built toolchain. + // + // earlyRuntimes must only be loaded by [LLVM]. + earlyRuntimes + buildcatrust utilMacros diff --git a/internal/rosa/llvm.go b/internal/rosa/llvm.go index 7669e0d0..2751410c 100644 --- a/internal/rosa/llvm.go +++ b/internal/rosa/llvm.go @@ -30,7 +30,128 @@ func litArgs(verbose bool, skipChecks ...string) string { return "'" + strings.Join(args, " ") + "'" } +func (t Toolchain) newEarlyCompilerRT() (pkg.Artifact, string) { + version := t.Version(llvmSource) + major, _, _ := strings.Cut(version, ".") + return t.NewPackage("early-compiler-rt", version, t.Load(llvmSource), &PackageAttr{ + Flag: TExclusive, + }, &CMakeHelper{ + Append: []string{"compiler-rt"}, + + Cache: []KV{ + // libc++ not yet available + {"CMAKE_CXX_COMPILER_TARGET", ""}, + + {"LLVM_HOST_TRIPLE", `"${ROSA_TRIPLE}"`}, + {"LLVM_DEFAULT_TARGET_TRIPLE", `"${ROSA_TRIPLE}"`}, + {"LLVM_ENABLE_PER_TARGET_RUNTIME_DIR", "ON"}, + + {"COMPILER_RT_BUILD_BUILTINS", "ON"}, + {"COMPILER_RT_DEFAULT_TARGET_ONLY", "OFF"}, + {"COMPILER_RT_SANITIZERS_TO_BUILD", "asan"}, + + // does not work without libunwind + {"COMPILER_RT_BUILD_CTX_PROFILE", "OFF"}, + {"COMPILER_RT_BUILD_LIBFUZZER", "OFF"}, + {"COMPILER_RT_BUILD_MEMPROF", "OFF"}, + {"COMPILER_RT_BUILD_PROFILE", "OFF"}, + {"COMPILER_RT_BUILD_XRAY", "OFF"}, + }, + SkipTest: true, + Script: ` +mkdir -p "/work/system/lib/clang/` + major + `/lib/" +ln -s \ + "../../../${ROSA_TRIPLE}" \ + "/work/system/lib/clang/` + major + `/lib/" + +ln -s \ + "clang_rt.crtbegin-` + linuxArch() + `.o" \ + "/work/system/lib/${ROSA_TRIPLE}/crtbeginS.o" +ln -s \ + "clang_rt.crtend-` + linuxArch() + `.o" \ + "/work/system/lib/${ROSA_TRIPLE}/crtendS.o" +`, + }, + Python, + + muslHeaders, + KernelHeaders, + ), version +} +func init() { + artifactsM[earlyCompilerRT] = Metadata{ + f: Toolchain.newEarlyCompilerRT, + + Name: "early-compiler-rt", + Description: "early LLVM runtime: compiler-rt", + + Dependencies: P{ + Musl, + }, + } +} + +func (t Toolchain) newEarlyRuntimes() (pkg.Artifact, string) { + version := t.Version(llvmSource) + return t.NewPackage("early-runtimes", version, t.Load(llvmSource), &PackageAttr{ + Flag: TExclusive, + }, &CMakeHelper{ + Append: []string{"runtimes"}, + + Cache: []KV{ + // libc++ not yet available + {"CMAKE_CXX_COMPILER_WORKS", "ON"}, + + {"LLVM_HOST_TRIPLE", `"${ROSA_TRIPLE}"`}, + {"LLVM_DEFAULT_TARGET_TRIPLE", `"${ROSA_TRIPLE}"`}, + {"LLVM_ENABLE_RUNTIMES", "'libunwind;libcxx;libcxxabi'"}, + + {"LIBUNWIND_USE_COMPILER_RT", "ON"}, + {"LIBCXX_HAS_MUSL_LIBC", "ON"}, + {"LIBCXX_USE_COMPILER_RT", "ON"}, + {"LIBCXX_HAS_ATOMIC_LIB", "OFF"}, + {"LIBCXXABI_USE_COMPILER_RT", "ON"}, + {"LIBCXXABI_USE_LLVM_UNWINDER", "ON"}, + {"LIBCXXABI_HAS_CXA_THREAD_ATEXIT_IMPL", "OFF"}, + + {"LLVM_ENABLE_ZLIB", "FORCE_ON"}, + {"LLVM_ENABLE_ZSTD", "FORCE_ON"}, + {"LLVM_ENABLE_LIBXML2", "OFF"}, + }, + SkipTest: true, + }, + Python, + + Zlib, + Zstd, + earlyCompilerRT, + KernelHeaders, + ), version +} +func init() { + artifactsM[earlyRuntimes] = Metadata{ + f: Toolchain.newEarlyRuntimes, + + Name: "early-runtimes", + Description: "early LLVM runtimes: libunwind, libcxx, libcxxabi", + + Dependencies: P{ + earlyCompilerRT, + }, + } +} + func (t Toolchain) newLLVM() (pkg.Artifact, string) { + var early PArtifact = muslHeaders + if t.isStage0() { + // The LLVM build system is buggy around LLVM_LINK_LLVM_DYLIB and leaks + // the system installation when invoking the newly built toolchain. This + // is worked around in stage0 by providing standalone builds of + // runtimes. Later stages rely on 3-stage determinism and allows the + // system installation from its previous stage to leak through. + early = earlyRuntimes + } + cache := []KV{ {"ENABLE_LINKER_BUILD_ID", "ON"}, {"COMPILER_RT_USE_BUILTINS_LIBRARY", "ON"}, @@ -173,7 +294,7 @@ ninja ` + jobsFlagE + ` check-all Zlib, Zstd, - muslHeaders, + early, KernelHeaders, ), version }