From c52ab14f84c863e2d7de1cc9ea476f885116c6dc Mon Sep 17 00:00:00 2001 From: Sunrisepeak Date: Tue, 23 Jun 2026 03:54:40 +0800 Subject: [PATCH] feat(aarch64): default to musl-static toolchain on non-x86 Linux Bare `mcpp build` (new project, no [toolchain]) on aarch64 tried to install the glibc default gcc@16.1.0 + glibc + linux-headers, which have no aarch64 assets (HTTP 404). On non-x86_64 Linux, default to gcc@15.1.0-musl instead: it's published for aarch64, self-contained (skip glibc/linux-headers deps), and yields portable static binaries (ideal for aarch64/Termux). x86_64 keeps the glibc default. Seeds the host triple so the -linux-musl-g++ frontend resolves for the no---target default. Also: fresh-install CI self-hosts mcpp AND xlings via --target aarch64-linux-musl (their manifests pin a glibc default). --- .../workflows/ci-aarch64-fresh-install.yml | 14 ++++++-- src/build/prepare.cppm | 33 +++++++++++++++---- 2 files changed, 37 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ci-aarch64-fresh-install.yml b/.github/workflows/ci-aarch64-fresh-install.yml index 1355149..48ddfaf 100644 --- a/.github/workflows/ci-aarch64-fresh-install.yml +++ b/.github/workflows/ci-aarch64-fresh-install.yml @@ -69,12 +69,20 @@ jobs: file "$bin" file "$bin" | grep -q "ARM aarch64" || { echo "expected aarch64 ELF"; exit 1; } - - name: Self-host — build mcpp from source natively + - name: Self-host — build mcpp + xlings from source natively run: | + # mcpp/xlings manifests pin a glibc default toolchain; on aarch64 the + # musl-static target is the published path, so build with --target. git clone --depth 1 https://github.com/mcpp-community/mcpp /tmp/mcpp-src cd /tmp/mcpp-src mcpp self config --mirror GLOBAL 2>/dev/null || true - mcpp build - m=$(find target -type f -name mcpp | head -1) + mcpp build --target aarch64-linux-musl + m=$(find target/aarch64-linux-musl -type f -name mcpp | head -1) file "$m" | grep -q "ARM aarch64" || { echo "expected aarch64 mcpp"; exit 1; } "$m" --version + git clone --depth 1 https://github.com/openxlings/xlings /tmp/xlings-src + cd /tmp/xlings-src + mcpp build --target aarch64-linux-musl + x=$(find target/aarch64-linux-musl -type f -name xlings | head -1) + file "$x" | grep -q "ARM aarch64" || { echo "expected aarch64 xlings"; exit 1; } + "$x" --version diff --git a/src/build/prepare.cppm b/src/build/prepare.cppm index 1e664a0..6db7db6 100644 --- a/src/build/prepare.cppm +++ b/src/build/prepare.cppm @@ -607,9 +607,29 @@ prepare_build(bool print_fingerprint, // breaks GUI/native packages out of the box. musl-static stays // opt-in via `mcpp build --target x86_64-linux-musl` for users // who explicitly want portable static binaries. - std::string defaultSpec = (mcpp::platform::is_macos || mcpp::platform::is_windows) - ? "llvm@20.1.7" : "gcc@16.1.0"; + // Linux default is arch-aware: + // x86_64 → glibc gcc (native ABI; the glibc toolchain is published + // for x86_64). musl-static stays opt-in via --target. + // other arches (aarch64, ...) → musl-static gcc: it's what's + // published for them, is self-contained, and yields portable + // static binaries (ideal for aarch64 / Termux, no bionic dep). + // glibc-world linking (X11/GL) needs an explicit glibc + // toolchain, addable later for native-ABI aarch64 builds. + std::string defaultSpec; + if constexpr (mcpp::platform::is_macos || mcpp::platform::is_windows) { + defaultSpec = "llvm@20.1.7"; + } else if (mcpp::platform::host_arch == std::string_view("x86_64")) { + defaultSpec = "gcc@16.1.0"; + } else { + defaultSpec = "gcc@15.1.0-musl"; + } + bool muslDefault = defaultSpec.find("-musl") != std::string::npos; auto defaultParsed = mcpp::toolchain::parse_toolchain_spec(defaultSpec); + // Host-native musl default has no --target, so seed the triple so the + // resolver finds the `-linux-musl-g++` frontend. + if (muslDefault) + defaultParsed->targetTriple = + std::string(mcpp::platform::host_arch) + "-linux-musl"; auto defaultPkg = mcpp::toolchain::to_xim_package(*defaultParsed); if constexpr (mcpp::platform::is_macos || mcpp::platform::is_windows) { @@ -618,8 +638,8 @@ prepare_build(bool print_fingerprint, defaultSpec)); } else { mcpp::ui::info("First run", - std::format("no toolchain configured — installing {} (glibc, native ABI) as default", - defaultSpec)); + std::format("no toolchain configured — installing {} ({}) as default", + defaultSpec, muslDefault ? "musl, static" : "glibc, native ABI")); } auto cfg = get_cfg(); @@ -628,9 +648,8 @@ prepare_build(bool print_fingerprint, mcpp::fetcher::InstallProgressHandler progress; // The glibc default toolchain needs the sysroot payloads (C library + - // kernel headers), exactly like `mcpp toolchain install` provides. - // The old musl-static default was self-contained, which masked this. - if constexpr (!mcpp::platform::is_macos && !mcpp::platform::is_windows) { + // kernel headers). The musl default is self-contained, so skip them. + if (!mcpp::platform::is_macos && !mcpp::platform::is_windows && !muslDefault) { for (auto dep : {"xim:glibc", "xim:linux-headers"}) { (void)fetcher.resolve_xpkg_path(dep, /*autoInstall=*/true, &progress); }