musl host support: bootstrap and run on Alpine (x86_64-alpine-linux-musl)
All checks were successful
CI / build-test-release (push) Successful in 7m43s
CI / release-musl (push) Successful in 8m56s

The Linux host code paths were gated on the x86_64_pc_linux_gnu target
define alone, and LoadProject hardcoded --target=x86_64-pc-linux-gnu when
compiling project.cpp and the module PCMs. Both break on musl hosts: the
glibc release launcher cannot run there at all (no glibc loader; gcompat
lacks libgcc_s and the __isoc23_* symbols), and a musl-built launcher
would still compile project.cpp for the wrong libc.

- The host gates test clang's __linux__ instead of one triple's define:
  they mean "Linux host", whatever the libc (or, later, the CPU).
- LoadProject derives the host triple from HostTarget() (clang's
  -print-target-triple), which is also more correct on glibc distros
  whose triple isn't x86_64-pc-linux-gnu.
- project.cpp / the cmake libc++ flags treat any *-linux-gnu or
  *-linux-musl target as Linux.
- build.sh targets the host toolchain's triple (CRAFTER_BUILD_TARGET
  overrides) and derives the per-target define from it. On Arch this is
  byte-for-byte the previous behaviour.
- CI: a release-musl job bootstraps on alpine:edge, runs the tests, and
  attaches crafter-build-linux-x86_64-musl-v2.tar.gz to the rolling
  latest release (via the API, so the glibc assets survive). Dynamic
  against musl libc++: the launcher dlopens project.so, so it cannot be
  fully static.

First consumer: imsd's package CI, which cross-compiles for aarch64 from
an Alpine container.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Jorijn van der Graaf 2026-09-01 23:49:00 +02:00
commit dc239f4257
7 changed files with 131 additions and 22 deletions

View file

@ -307,7 +307,7 @@ CompileCommand Crafter::GetCompileCommand(const Configuration& config) {
}
if(config.type == ConfigurationType::LibraryDynamic) {
#ifdef CRAFTER_BUILD_CONFIGURATION_TARGET_x86_64_pc_linux_gnu
#ifdef __linux__
out.command += " -fPIC -D CRAFTER_BUILD_CONFIGURATION_TYPE_SHARED_LIBRARY";
#endif
#if defined(CRAFTER_BUILD_CONFIGURATION_TARGET_x86_64_pc_windows_msvc) || defined(CRAFTER_BUILD_CONFIGURATION_TARGET_x86_64_w64_mingw32)
@ -453,7 +453,7 @@ BuildResult Crafter::Build(Configuration& config, std::unordered_map<fs::path, s
// users supply cfg.sysroot pointing at their wasi-sdk install. Covers all
// wasm32-* triples (wasi, wasip1, wasip2, ...); the sysroot's per-triple
// subdirs handle the differences.
#ifdef CRAFTER_BUILD_CONFIGURATION_TARGET_x86_64_pc_linux_gnu
#ifdef __linux__
if (config.sysroot.empty() && config.target.starts_with("wasm32")) {
config.sysroot = "/usr/share/wasi-sysroot";
}
@ -1131,7 +1131,7 @@ BuildResult Crafter::Build(Configuration& config, std::unordered_map<fs::path, s
if(buildResult.repack) {
Progress::Task task(std::format("Linking {}", config.outputName));
if(config.type == ConfigurationType::Executable) {
#ifdef CRAFTER_BUILD_CONFIGURATION_TARGET_x86_64_pc_linux_gnu
#ifdef __linux__
if(config.target == "x86_64-w64-mingw32") {
try {
// Copy any LibraryDynamic dependency DLLs alongside
@ -1204,7 +1204,7 @@ BuildResult Crafter::Build(Configuration& config, std::unordered_map<fs::path, s
}
#endif
} else if(config.type == ConfigurationType::LibraryStatic) {
#ifdef CRAFTER_BUILD_CONFIGURATION_TARGET_x86_64_pc_linux_gnu
#ifdef __linux__
// ThinLTO emits LLVM bitcode objects; plain `ar` writes an archive
// index that omits their symbols, so a consumer's lld link can't
// pull the needed members. llvm-ar writes a bitcode-aware index.
@ -1550,7 +1550,7 @@ ArgQuery Crafter::ApplyStandardArgs(Configuration& cfg, std::span<const std::str
// includes it. (Build() also runs this once more for callers that bypassed
// ApplyStandardArgs, but doing it here makes dep PcmDirs consistent
// between the consumer's command-construction and the dep's own build.)
#ifdef CRAFTER_BUILD_CONFIGURATION_TARGET_x86_64_pc_linux_gnu
#ifdef __linux__
if (cfg.sysroot.empty() && cfg.target.starts_with("wasm32")) {
cfg.sysroot = "/usr/share/wasi-sysroot";
}