musl host support: bootstrap and run on Alpine (x86_64-alpine-linux-musl)
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:
parent
802caac1c2
commit
dc239f4257
7 changed files with 131 additions and 22 deletions
18
project.cpp
18
project.cpp
|
|
@ -32,6 +32,18 @@ extern "C" Configuration CrafterBuildProject(std::span<const std::string_view> a
|
|||
|
||||
CrafterBuildLib->dependencies = { math, asset };
|
||||
CrafterBuildLib->defines.push_back({"CRAFTER_BUILD_HAS_ASSET", ""});
|
||||
// Crafter.Build-Lint includes libclang's clang-c/Index.h. glibc distros
|
||||
// keep it in /usr/include; Alpine keeps LLVM under /usr/lib/llvmNN, so ask
|
||||
// llvm-config and add the dir when it is not already on the default path
|
||||
// (never /usr/include itself: that breaks libc++'s #include_next).
|
||||
if (CrafterBuildLib->target.ends_with("-linux-gnu") || CrafterBuildLib->target.ends_with("-linux-musl")) {
|
||||
auto llvmInc = RunCommandWithTimeout("llvm-config --includedir 2>/dev/null", std::chrono::seconds(10));
|
||||
std::string incDir = llvmInc.output;
|
||||
while (!incDir.empty() && (incDir.back() == '\n' || incDir.back() == '\r')) incDir.pop_back();
|
||||
if (llvmInc.exitCode == 0 && !incDir.empty() && incDir != "/usr/include") {
|
||||
CrafterBuildLib->compileFlags.push_back(std::format("-I{}", incDir));
|
||||
}
|
||||
}
|
||||
{
|
||||
std::array<fs::path, 11> interfaces = {
|
||||
"interfaces/Crafter.Build",
|
||||
|
|
@ -87,7 +99,9 @@ extern "C" Configuration CrafterBuildProject(std::span<const std::string_view> a
|
|||
std::array<fs::path, 1> implementations = { "implementations/main" };
|
||||
cfg.GetInterfacesAndImplementations(interfaces, implementations);
|
||||
}
|
||||
if (cfg.target == "x86_64-pc-linux-gnu") {
|
||||
// Linux hosts, glibc or musl (Alpine): -ldl is a libc stub on musl, harmless.
|
||||
const bool linuxTarget = cfg.target.ends_with("-linux-gnu") || cfg.target.ends_with("-linux-musl");
|
||||
if (linuxTarget) {
|
||||
cfg.linkFlags.push_back("-Wl,--export-dynamic");
|
||||
cfg.linkFlags.push_back("-ldl");
|
||||
}
|
||||
|
|
@ -102,7 +116,7 @@ extern "C" Configuration CrafterBuildProject(std::span<const std::string_view> a
|
|||
// links each test exe against CrafterBuildLib built from the local
|
||||
// sources — so the code under test is whatever's in this checkout.
|
||||
// Mirrors how downstream consumers link their own libraries into tests.
|
||||
if (cfg.target == "x86_64-pc-linux-gnu") {
|
||||
if (linuxTarget) {
|
||||
cfg.AddTest("HelloWorld").Dependencies({ CrafterBuildLib.get() });
|
||||
cfg.AddTest("StaticLib").Dependencies({ CrafterBuildLib.get() });
|
||||
cfg.AddTest("ModuleInterface").Dependencies({ CrafterBuildLib.get() });
|
||||
|
|
|
|||
Loading…
Reference in a new issue