internal/rosa: llvm artifact abstraction
All checks were successful
Test / Create distribution (push) Successful in 31s
Test / Sandbox (push) Successful in 3m19s
Test / Sandbox (race detector) (push) Successful in 6m7s
Test / ShareFS (push) Successful in 6m10s
Test / Hpkg (push) Successful in 6m50s
Test / Hakurei (push) Successful in 7m30s
Test / Hakurei (race detector) (push) Successful in 9m5s
Test / Flake checks (push) Successful in 1m58s
All checks were successful
Test / Create distribution (push) Successful in 31s
Test / Sandbox (push) Successful in 3m19s
Test / Sandbox (race detector) (push) Successful in 6m7s
Test / ShareFS (push) Successful in 6m10s
Test / Hpkg (push) Successful in 6m50s
Test / Hakurei (push) Successful in 7m30s
Test / Hakurei (race detector) (push) Successful in 9m5s
Test / Flake checks (push) Successful in 1m58s
The llvm bootstrap is multi-stage by nature, and cannot be completed in a single artifact. Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
191
internal/rosa/llvm.go
Normal file
191
internal/rosa/llvm.go
Normal file
@@ -0,0 +1,191 @@
|
||||
package rosa
|
||||
|
||||
import (
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"hakurei.app/container/check"
|
||||
"hakurei.app/internal/pkg"
|
||||
)
|
||||
|
||||
// llvmAttr holds the attributes that will be applied to a new [pkg.Artifact]
|
||||
// containing a LLVM variant.
|
||||
type llvmAttr struct {
|
||||
flags int
|
||||
|
||||
// Concatenated with default environment for CMakeAttr.Env.
|
||||
env []string
|
||||
// Concatenated with generated entries for CMakeAttr.Cache.
|
||||
cmake [][2]string
|
||||
// Override CMakeAttr.Append.
|
||||
append []string
|
||||
// Concatenated with default dependencies for CMakeAttr.Extra.
|
||||
extra []pkg.Artifact
|
||||
// Concatenated with default fixup for CMakeAttr.Script.
|
||||
script string
|
||||
// Passed through to CMakeAttr.Prefix.
|
||||
prefix *check.Absolute
|
||||
}
|
||||
|
||||
const (
|
||||
llvmProjectClang = 1 << iota
|
||||
llvmProjectLld
|
||||
|
||||
llvmProjectAll = 1<<iota - 1
|
||||
|
||||
llvmRuntimeCompilerRT = 1 << iota
|
||||
llvmRuntimeLibunwind
|
||||
llvmRuntimeLibc
|
||||
llvmRuntimeLibcxx
|
||||
llvmRuntimeLibcxxABI
|
||||
|
||||
llvmAll = 1<<iota - 1
|
||||
llvmRuntimeAll = llvmAll - (2 * llvmProjectAll) - 1
|
||||
)
|
||||
|
||||
// llvmFlagName resolves a llvmAttr.flags project or runtime flag to its name.
|
||||
func llvmFlagName(flag int) string {
|
||||
switch flag {
|
||||
case llvmProjectClang:
|
||||
return "clang"
|
||||
case llvmProjectLld:
|
||||
return "lld"
|
||||
|
||||
case llvmRuntimeCompilerRT:
|
||||
return "compiler-rt"
|
||||
case llvmRuntimeLibunwind:
|
||||
return "libunwind"
|
||||
case llvmRuntimeLibc:
|
||||
return "libc"
|
||||
case llvmRuntimeLibcxx:
|
||||
return "libcxx"
|
||||
case llvmRuntimeLibcxxABI:
|
||||
return "libcxxabi"
|
||||
|
||||
default:
|
||||
panic("invalid flag " + strconv.Itoa(flag))
|
||||
}
|
||||
}
|
||||
|
||||
// newLLVM returns a [pkg.Artifact] containing a LLVM variant.
|
||||
func (t Toolchain) newLLVM(variant string, attr *llvmAttr) pkg.Artifact {
|
||||
const (
|
||||
version = "21.1.8"
|
||||
checksum = "8SUpqDkcgwOPsqHVtmf9kXfFeVmjVxl4LMn-qSE1AI_Xoeju-9HaoPNGtidyxyka"
|
||||
)
|
||||
if attr == nil {
|
||||
panic("LLVM attr must be non-nil")
|
||||
}
|
||||
|
||||
var projects, runtimes []string
|
||||
for i := 1; i < llvmProjectAll; i <<= 1 {
|
||||
if attr.flags&i != 0 {
|
||||
projects = append(projects, llvmFlagName(i))
|
||||
}
|
||||
}
|
||||
for i := (llvmProjectAll + 1) << 1; i < llvmRuntimeAll; i <<= 1 {
|
||||
if attr.flags&i != 0 {
|
||||
runtimes = append(runtimes, llvmFlagName(i))
|
||||
}
|
||||
}
|
||||
|
||||
var script, scriptEarly string
|
||||
|
||||
cache := [][2]string{
|
||||
{"CMAKE_BUILD_TYPE", "Release"},
|
||||
|
||||
{"LLVM_HOST_TRIPLE", `"${ROSA_TRIPLE}"`},
|
||||
{"LLVM_DEFAULT_TARGET_TRIPLE", `"${ROSA_TRIPLE}"`},
|
||||
}
|
||||
if len(projects) > 0 {
|
||||
cache = append(cache,
|
||||
[2]string{"LLVM_ENABLE_PROJECTS", `"${ROSA_LLVM_PROJECTS}"`})
|
||||
}
|
||||
if len(runtimes) > 0 {
|
||||
cache = append(cache,
|
||||
[2]string{"LLVM_ENABLE_RUNTIMES", `"${ROSA_LLVM_RUNTIMES}"`})
|
||||
}
|
||||
|
||||
cmakeAppend := []string{"llvm"}
|
||||
if attr.append != nil {
|
||||
cmakeAppend = attr.append
|
||||
} else {
|
||||
cache = append(cache,
|
||||
[2]string{"LLVM_ENABLE_LIBCXX", "ON"},
|
||||
[2]string{"LLVM_USE_LINKER", "lld"},
|
||||
|
||||
[2]string{"LLVM_INSTALL_BINUTILS_SYMLINKS", "ON"},
|
||||
[2]string{"LLVM_INSTALL_CCTOOLS_SYMLINKS", "ON"},
|
||||
)
|
||||
}
|
||||
|
||||
extra := []pkg.Artifact{
|
||||
t.NewPython(),
|
||||
t.NewKernelHeaders(),
|
||||
}
|
||||
if t == toolchainStage3 {
|
||||
extra = nil
|
||||
}
|
||||
|
||||
if attr.flags&llvmProjectClang != 0 {
|
||||
cache = append(cache,
|
||||
[2]string{"CLANG_DEFAULT_CXX_STDLIB", "libc++"},
|
||||
[2]string{"CLANG_DEFAULT_RTLIB", "compiler-rt"},
|
||||
)
|
||||
}
|
||||
if attr.flags&llvmProjectLld != 0 {
|
||||
script += `
|
||||
ln -s ld.lld /work/system/bin/ld
|
||||
`
|
||||
}
|
||||
if attr.flags&llvmRuntimeCompilerRT != 0 {
|
||||
if attr.append == nil {
|
||||
cache = append(cache,
|
||||
[2]string{"COMPILER_RT_USE_LLVM_UNWINDER", "ON"})
|
||||
}
|
||||
}
|
||||
if attr.flags&llvmRuntimeLibunwind != 0 {
|
||||
cache = append(cache,
|
||||
[2]string{"LIBUNWIND_USE_COMPILER_RT", "ON"})
|
||||
}
|
||||
if attr.flags&llvmRuntimeLibcxx != 0 {
|
||||
cache = append(cache,
|
||||
[2]string{"LIBCXX_HAS_MUSL_LIBC", "ON"},
|
||||
[2]string{"LIBCXX_USE_COMPILER_RT", "ON"},
|
||||
)
|
||||
|
||||
if t > toolchainStage3 {
|
||||
// libcxxabi fails to compile if c++ headers not prefixed in /usr
|
||||
// is found by the compiler, and doing this is easier than
|
||||
// overriding CXXFLAGS; not using mv here to avoid chown failures
|
||||
scriptEarly += `
|
||||
cp -r /system/include /usr/include && rm -rf /system/include
|
||||
`
|
||||
}
|
||||
}
|
||||
if attr.flags&llvmRuntimeLibcxxABI != 0 {
|
||||
cache = append(cache,
|
||||
[2]string{"LIBCXXABI_USE_COMPILER_RT", "ON"},
|
||||
[2]string{"LIBCXXABI_USE_LLVM_UNWINDER", "ON"},
|
||||
)
|
||||
}
|
||||
|
||||
return t.NewViaCMake("llvm", version, variant, pkg.NewHTTPGetTar(
|
||||
nil, "https://github.com/llvm/llvm-project/archive/refs/tags/"+
|
||||
"llvmorg-"+version+".tar.gz",
|
||||
mustDecode(checksum),
|
||||
pkg.TarGzip,
|
||||
), &CMakeAttr{
|
||||
Cache: slices.Concat(cache, attr.cmake),
|
||||
Append: cmakeAppend,
|
||||
Extra: slices.Concat(attr.extra, extra),
|
||||
Prefix: attr.prefix,
|
||||
|
||||
Env: slices.Concat([]string{
|
||||
"ROSA_LLVM_PROJECTS=" + strings.Join(projects, ";"),
|
||||
"ROSA_LLVM_RUNTIMES=" + strings.Join(runtimes, ";"),
|
||||
}, attr.env),
|
||||
ScriptEarly: scriptEarly, Script: script + attr.script,
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user