1
0
forked from rosa/hakurei
Files
hakurei/internal/rosa/llvm.go
Ophestra a7f7ce1795 internal/rosa/llvm: migrate compiler-rt
The newLLVM family of functions predate the package system. This change migrates compiler-rt without changing any resulting artifacts.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-04-14 00:19:33 +09:00

303 lines
7.3 KiB
Go

package rosa
import (
"runtime"
"slices"
"sync"
"hakurei.app/internal/pkg"
)
// llvmSource is the unpatched upstream LLVM monorepo.
var llvmSource = newFromGitHub(
"llvm/llvm-project",
"llvmorg-"+llvmVersion,
llvmChecksum,
)
// llvmAttr holds the attributes that will be applied to a new [pkg.Artifact]
// containing a LLVM variant.
type llvmAttr struct {
// Concatenated with default environment for PackageAttr.Env.
env []string
// Concatenated with generated entries for CMakeHelper.Cache.
cmake []KV
// Override CMakeHelper.Append.
append []string
// Passed through to PackageAttr.NonStage0.
nonStage0 []pkg.Artifact
// Concatenated with default fixup for CMakeHelper.Script.
script string
// Patch name and body pairs.
patches []KV
}
// newLLVMVariant returns a [pkg.Artifact] containing a LLVM variant.
func (t Toolchain) newLLVMVariant(variant string, attr *llvmAttr) pkg.Artifact {
if attr == nil {
panic("LLVM attr must be non-nil")
}
cmakeAppend := []string{"llvm"}
if attr.append != nil {
cmakeAppend = attr.append
}
return t.NewPackage("llvm", llvmVersion, llvmSource, &PackageAttr{
Patches: slices.Concat(attr.patches, llvmPatches),
NonStage0: attr.nonStage0,
Env: attr.env,
Flag: TExclusive,
}, &CMakeHelper{
Variant: variant,
Cache: attr.cmake,
Append: cmakeAppend,
Script: attr.script,
},
Python,
Perl,
Diffutils,
Bash,
Gawk,
Coreutils,
Findutils,
KernelHeaders,
)
}
func (t Toolchain) newCompilerRT() (pkg.Artifact, string) {
muslHeaders, _ := t.newMusl(true, []string{
"CC=clang",
})
return t.newLLVMVariant("compiler-rt", &llvmAttr{
env: stage0ExclConcat(t, []string{},
"LDFLAGS="+earlyLDFLAGS(false),
),
cmake: []KV{
{"CMAKE_BUILD_TYPE", "Release"},
{"LLVM_HOST_TRIPLE", `"${ROSA_TRIPLE}"`},
{"LLVM_DEFAULT_TARGET_TRIPLE", `"${ROSA_TRIPLE}"`},
// libc++ not yet available
{"CMAKE_CXX_COMPILER_TARGET", ""},
{"COMPILER_RT_BUILD_BUILTINS", "ON"},
{"COMPILER_RT_DEFAULT_TARGET_ONLY", "OFF"},
{"COMPILER_RT_SANITIZERS_TO_BUILD", "asan"},
{"LLVM_ENABLE_PER_TARGET_RUNTIME_DIR", "ON"},
// 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"},
},
append: []string{"compiler-rt"},
nonStage0: []pkg.Artifact{
muslHeaders,
},
script: `
mkdir -p "/work/system/lib/clang/` + llvmVersionMajor + `/lib/"
ln -s \
"../../../${ROSA_TRIPLE}" \
"/work/system/lib/clang/` + llvmVersionMajor + `/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"
`,
}), llvmVersion
}
func init() {
artifactsM[LLVMCompilerRT] = Metadata{
f: Toolchain.newCompilerRT,
Name: "llvm-compiler-rt",
Description: "LLVM runtime: compiler-rt",
Website: "https://llvm.org/",
}
}
// newLLVM returns LLVM toolchain across multiple [pkg.Artifact].
func (t Toolchain) newLLVM() (musl, runtimes, clang pkg.Artifact) {
target := "'AArch64;RISCV;X86'"
if t.isStage0() {
switch runtime.GOARCH {
case "386", "amd64":
target = "X86"
case "arm64":
target = "AArch64"
case "riscv64":
target = "RISCV"
default:
panic("unsupported target " + runtime.GOARCH)
}
}
minimalDeps := []KV{
{"LLVM_ENABLE_ZLIB", "OFF"},
{"LLVM_ENABLE_ZSTD", "OFF"},
{"LLVM_ENABLE_LIBXML2", "OFF"},
}
compilerRT := t.Load(LLVMCompilerRT)
musl, _ = t.newMusl(false, stage0ExclConcat(t, []string{
"CC=clang",
"LIBCC=/system/lib/clang/" + llvmVersionMajor + "/lib/" +
triplet() + "/libclang_rt.builtins.a",
"AR=ar",
"RANLIB=ranlib",
},
"LDFLAGS="+earlyLDFLAGS(false),
), compilerRT)
runtimes = t.newLLVMVariant("runtimes", &llvmAttr{
env: stage0ExclConcat(t, []string{},
"LDFLAGS="+earlyLDFLAGS(false),
),
cmake: slices.Concat([]KV{
{"CMAKE_BUILD_TYPE", "Release"},
{"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"},
{"LIBCXXABI_USE_COMPILER_RT", "ON"},
{"LIBCXXABI_USE_LLVM_UNWINDER", "ON"},
// libc++ not yet available
{"CMAKE_CXX_COMPILER_WORKS", "ON"},
{"LIBCXX_HAS_ATOMIC_LIB", "OFF"},
{"LIBCXXABI_HAS_CXA_THREAD_ATEXIT_IMPL", "OFF"},
}, minimalDeps),
append: []string{"runtimes"},
nonStage0: []pkg.Artifact{
compilerRT,
musl,
},
})
clang = t.newLLVMVariant("clang", &llvmAttr{
env: stage0ExclConcat(t, []string{},
"CFLAGS="+earlyCFLAGS,
"CXXFLAGS="+earlyCXXFLAGS(),
"LDFLAGS="+earlyLDFLAGS(false),
),
cmake: slices.Concat([]KV{
{"CMAKE_BUILD_TYPE", "Release"},
{"LLVM_HOST_TRIPLE", `"${ROSA_TRIPLE}"`},
{"LLVM_DEFAULT_TARGET_TRIPLE", `"${ROSA_TRIPLE}"`},
{"LLVM_ENABLE_PROJECTS", "'clang;lld'"},
{"LLVM_ENABLE_LIBCXX", "ON"},
{"LLVM_USE_LINKER", "lld"},
{"LLVM_INSTALL_BINUTILS_SYMLINKS", "ON"},
{"LLVM_INSTALL_CCTOOLS_SYMLINKS", "ON"},
{"LLVM_LIT_ARGS", "'--verbose'"},
{"CLANG_DEFAULT_LINKER", "lld"},
{"CLANG_DEFAULT_CXX_STDLIB", "libc++"},
{"CLANG_DEFAULT_RTLIB", "compiler-rt"},
{"CLANG_DEFAULT_UNWINDLIB", "libunwind"},
{"LLVM_TARGETS_TO_BUILD", target},
{"CMAKE_CROSSCOMPILING", "OFF"},
{"CXX_SUPPORTS_CUSTOM_LINKER", "ON"},
}, minimalDeps),
nonStage0: []pkg.Artifact{
musl,
compilerRT,
runtimes,
},
script: `
ln -s ld.lld /work/system/bin/ld
ln -s clang /work/system/bin/cc
ln -s clang++ /work/system/bin/c++
ninja check-all
`,
})
return
}
func init() {
artifactsM[LLVMRuntimes] = Metadata{
f: func(t Toolchain) (pkg.Artifact, string) {
_, runtimes, _ := t.newLLVM()
return runtimes, llvmVersion
},
Name: "llvm-runtimes",
Description: "LLVM runtimes: libunwind, libcxx, libcxxabi",
Website: "https://llvm.org/",
}
artifactsM[LLVMClang] = Metadata{
f: func(t Toolchain) (pkg.Artifact, string) {
_, _, clang := t.newLLVM()
return clang, llvmVersion
},
Name: "clang",
Description: `an "LLVM native" C/C++/Objective-C compiler`,
Website: "https://llvm.org/",
ID: 1830,
}
artifactsM[Libclc] = Metadata{
f: func(t Toolchain) (pkg.Artifact, string) {
return t.newLLVMVariant("libclc", &llvmAttr{
cmake: []KV{
{"CMAKE_BUILD_TYPE", "Release"},
{"LLVM_HOST_TRIPLE", `"${ROSA_TRIPLE}"`},
{"LLVM_DEFAULT_TARGET_TRIPLE", `"${ROSA_TRIPLE}"`},
{"LIBCLC_TARGETS_TO_BUILD", "all"},
},
append: []string{"libclc"},
script: "ninja test",
}), llvmVersion
},
Name: "libclc",
Description: "an open source, BSD/MIT dual licensed implementation of the library requirements of the OpenCL C programming language",
Website: "https://libclc.llvm.org/",
}
}
var (
// llvm stores the result of Toolchain.newLLVM.
llvm [_toolchainEnd][3]pkg.Artifact
// llvmOnce is for lazy initialisation of llvm.
llvmOnce [_toolchainEnd]sync.Once
)
// NewLLVM returns LLVM toolchain across multiple [pkg.Artifact].
func (t Toolchain) NewLLVM() (musl, runtimes, clang pkg.Artifact) {
llvmOnce[t].Do(func() {
llvm[t][0], llvm[t][1], llvm[t][2] = t.newLLVM()
})
return llvm[t][0], llvm[t][1], llvm[t][2]
}