起因:mcpp#143 —— 用户在 Android/Termux (aarch64) 上无法编译 mcpp。 范围:让 mcpp 及其工具链生态在 aarch64-linux 上可安装、可自举、可构建。 状态:MVP(musl-static 路线)已闭环。日期:2026-06-22(更新 2026-06-23)。
musl-static 路线已打通并自举闭环(PR #146/#147/#148 + 后续):
xlings install mcpp→mcpp new/build/run(import std)在原生 aarch64 runner 上通过;- self-host 最后一公里:
mcpp build --target aarch64-linux-musl自举 mcpp + xlings。曾因ensure_ninja拉xim:glibc@2.39(aarch64 无资产)卡死而失败。- 本轮修复:把 ninja 做成两 arch 全静态自包含(x86_64 glibc-static / aarch64 musl-static),上架
ninja-1.12.1-linux-aarch64.tar.gz到xlings-res/ninja(GLOBAL),并在xim-pkgindex的ninja.lua删除xim:glibc/xim:gcc-runtimeruntime deps(引擎按 OS 而非 arch 解析依赖,glibc dep 会在 aarch64 上 404)。模型对齐patchelf.lua(同为自包含 bootstrap 工具)。- arch token 勘误:Linux=
aarch64、macOS=arm64(引擎detect_arch_()平台感知;§1.4 已更正)。- 遗留:①
ninja资产的 gitcode(CN)镜像需手动同步;② glibc-world(glibc/binutils/gcc-16-glibc/gcc-runtime/linux-headers/llvm 的 aarch64 资产)仍全缺 —— 仅 musl-static 路线可用,glibc 原生 ABI(GUI/X11/GL)路线未建,见 §4 阶段①/②。
mcpp 是一个 self-host(自己编译自己)的 C++ 构建/包管理工具。它本身不携带 LLVM,而是通过 bundled 的 xlings 包管理器下载托管的 sandbox 工具链(gcc/glibc/llvm 等),并用 patchelf 把 loader/RUNPATH 重写成 sandbox 内的绝对路径。因此 mcpp 的正常工作流 不依赖宿主 OS 的 libc。
用户在 Termux 上遇到的 import std / Bionic 头冲突(sigcontext/sigaction 重定义),是因为他 绕开 mcpp、直接用系统 clang -fmodules 去啃 Bionic 头 —— 那不是 mcpp 的执行路径。mcpp 如果正常跑,Bionic 根本不参与。
| 目标 | 难度 | 本质 |
|---|---|---|
| A. aarch64-linux (glibc/musl) | 中等、可控 | mcpp 的 triple 检测本就架构无关;真正阻塞 = 少量硬编码 loader + CI 矩阵 + 外部需产出 aarch64 工具链二进制并上架 |
| B. Termux/Android (bionic) | 大一个量级 | 全生态零 Android 处理;__linux__ 与 glibc 强绑定。取巧路线:走 aarch64-linux-musl 全静态,绕开 bionic ABI 与 "glibc 能否在 Android 内核运行" 两个变量 |
本报告聚焦 目标 A;目标 B 在 §7 单列。
- xlings 按 OS 解析依赖,不按 arch 解析。 包选择 key 是
linux/macosx/windows,archs={...}字段引擎根本不读(纯元数据)。 - arch 只在两处真正参与:
XLINGS_RESsentinel → 下载 URL 的 arch token 拼接(xlings/src/core/xim/installer.cppm:146build_xlings_res_url_,按detect_arch_()自动带);libxpkg的elfpatch.lua给 ELF 打 INTERP/rpath 时的 loader 选择。
XLINGS_RES包的 per-arch 已天然工作 —— 引擎已自动把 arch 拼进 URL。所以走 sentinel 的工具链包 无需改 DSL,只需上架 aarch64 资产。DSL "不支持同平台 per-arch URL"(xim-pkgindex/docs/specs/url-template.md:69)只卡 写显式上游 URL 的包(如 fish/jq)。
引擎 detect_arch_()(xlings/src/core/xim/installer.cppm:123-133)是 平台感知 的:
- Linux(及非 Apple 平台)→
aarch64(沿用 GNU/uname -m拼写,与aarch64-linux-*工具链三元组一致); - macOS(Apple)→
arm64(Apple 自家拼写)。
→ Linux 的 XLINGS_RES 资产必须命名 <pkg>-<ver>-linux-aarch64.tar.gz(内层目录同名);
macOS 才是 <pkg>-<ver>-macosx-arm64.tar.gz。
已发布资产即此约定:musl-gcc-15.1.0-linux-aarch64.tar.gz、aarch64-linux-musl-gcc-15.1.0-linux-aarch64.tar.gz、ninja-1.12.1-macosx-arm64.tar.gz。
→ install.sh 的 PLAT 同步映射成 linux-aarch64。
注意:mcpp 内部的 target triple(由编译器
-dumpmachine产出)是aarch64-linux-gnu/aarch64-linux-musl—— 工具链三元组与 xlings 资产 token 现已统一为aarch64(Linux),不再有arm64混淆;只有 macOS 资产沿用 Apple 的arm64。
| 仓库 | 角色 | 适配性质 |
|---|---|---|
mcpp-community/mcpp |
本体(self-host 构建工具) | 代码 + CI + 配置 |
openxlings/xlings |
包管理器引擎(C++23,由 mcpp 编译) | 主要是 CI 产出 aarch64 二进制 |
mcpplibs/libxpkg |
xlings 的 ELF patch / xpkg 执行库 | 代码(loader 路径) |
openxlings/xim-pkgindex |
包索引(每包一个 .lua) | 元数据 + 硬编码 loader + (可选)DSL 扩展 |
xlings-res/* |
资产托管(GitHub GLOBAL + gitcode CN) | 上架 aarch64 二进制 |
| (横切) 工具链构建 | gcc/glibc/llvm/musl 的 aarch64 产出 | 最重的底层活 |
graph TD
subgraph build["① 工具链构建 [最底层]"]
TC_LLVM["llvm/clang aarch64<br/>(LLVM 官方有 Linux-ARM64,可镜像)"]
TC_GCC["gcc@16 + glibc payload aarch64<br/>(crosstool-ng / 原生构建)"]
TC_MUSL["musl-cross aarch64-linux-musl<br/>(全静态路线)"]
TC_AUX["patchelf / ninja aarch64<br/>(上游现成)"]
end
subgraph res["② xlings-res 资产上架 (linux-aarch64 命名)"]
RES["github.com/xlings-res/*<br/>gitcode.com/xlings-res/*"]
end
subgraph engine["③ 引擎/库代码"]
XLINGS["xlings: CI 产出 aarch64 二进制<br/>+ os.arch stub 修正"]
LIBXPKG["libxpkg: elfpatch 加<br/>aarch64 loader 路径"]
end
subgraph index["④ xim-pkgindex"]
IDX_META["各包 archs 元数据 + aarch64"]
IDX_HC["硬编码 loader/triple 修正<br/>(glibc/gcc/llvm/musl-gcc)"]
IDX_DSL["(可选) DSL per-arch URL 扩展"]
end
subgraph mcpp["⑤ mcpp 本体"]
MCPP_CODE["loader/triple 硬编码 4 处<br/>+ host_arch 抽象"]
MCPP_INSTALL["install.sh 加 Linux-aarch64"]
MCPP_CI["release.yml aarch64 job"]
MCPP_TOML["mcpp.toml [target.aarch64-linux-musl]"]
end
BOOT0["⓪ 第 0 个 aarch64 mcpp<br/>(一次性引导:交叉/ARM runner)"]
TC_LLVM --> RES
TC_GCC --> RES
TC_MUSL --> RES
TC_AUX --> RES
BOOT0 --> XLINGS
XLINGS --> RES
LIBXPKG --> XLINGS
RES --> IDX_META
IDX_HC --> IDX_META
IDX_DSL -.可选.-> IDX_META
IDX_META --> MCPP_INSTALL
MCPP_CODE --> MCPP_CI
MCPP_TOML --> MCPP_CI
LIBXPKG --> IDX_HC
XLINGS --> MCPP_CI
RES --> MCPP_CI
MCPP_INSTALL --> DONE["✅ xlings install mcpp<br/>在 aarch64-linux 闭环"]
MCPP_CI --> DONE
flowchart LR
A["⓪ 现成编译器<br/>(ARM runner / 交叉)"] -->|引导| B["第 0 个<br/>aarch64 mcpp"]
B -->|编译| C["xlings aarch64<br/>(静态 musl)"]
D["aarch64 工具链资产<br/>(优先复用 LLVM 官方)"] -->|上架 aarch64| E["xlings-res"]
F["libxpkg + glibc.lua<br/>aarch64 loader 修正"] --> G
C --> G["xlings install mcpp<br/>正常拉取"]
E --> G
G -->|self-host| H["✅ aarch64 闭环<br/>(后续版本自动滚动)"]
graph LR
LH["linux-headers"] --> GLIBC["glibc"]
GLIBC --> BINUTILS["binutils"]
GLIBC --> GSC["gcc-specs-config"]
GLIBC --> GRT["gcc-runtime"]
BINUTILS --> GCC["gcc"]
GSC --> GCC
GRT --> GCC
GLIBC --> NINJA["ninja"]
GRT --> NINJA
GCC --> MCPP["mcpp"]
NINJA --> MCPP
PATCHELF["patchelf"] -.musl路线.-> MUSL["musl-gcc"]
GLIBC -.clang路线.-> LLVM["llvm / llvm-tools"]
图例:
[构建]需为 aarch64 重新编译 ·[资产]需上架二进制 ·[代码]源码改动 ·[CI]流水线 ·[决策]需拍板
-
[构建]在 aarch64 上(ubuntu-24.04-arm原生 runner 或 x86_64 交叉)用现成编译器引导出 第 0 个 aarch64 mcpp。参考已有scripts/bootstrap-macos.sh+.github/workflows/bootstrap-macos.yml的 xmake "Plan B" 思路。
-
[构建]llvm/clang aarch64-linux —— LLVM 官方有…-Linux-ARM64release,直接镜像最省事;走此路import std也通。 -
[构建]gcc@16(glibc)+ glibc payload aarch64 —— crosstool-ng / 原生构建。 -
[构建]musl-crossaarch64-linux-musl—— 全静态路线关键(也是 Termux 取巧路线的基础)。 -
[构建]patchelf / ninja aarch64 —— 上游现成,镜像即可。
向 github.com/xlings-res/<pkg>(GLOBAL)+ gitcode.com/xlings-res/<pkg>(CN)各上传 <pkg>-<ver>-linux-aarch64.tar.gz(内层目录同名,布局对齐 x86_64):
-
[资产]最小主链:linux-headers→glibc→binutils→gcc-specs-config→gcc-runtime→gcc→ninja→mcpp -
[资产]补充:llvm/llvm-tools(clang /import std路线)、patchelf、musl-gcc/musl-cross-make(musl 路线)
mcpplibs/libxpkg(ELF 安装后能否运行的关键)
-
[代码]src/lua-stdlib/xim/libxpkg/elfpatch.lua—— ELF class 检测已支持 aarch64(_EM_AARCH64,:153)✓;但_detect_system_loader(:287-289)与 subos_resolve_loader(:315-317)只列 x86_64 loader → 补ld-linux-aarch64.so.1/ld-musl-aarch64.so.1。 -
[代码]src/xpkg-lua-stdlib.cppm:1181—— 同逻辑的内嵌副本,同步改。
openxlings/xlings(几乎不阻塞)
-
[代码]src/core/xim/installer.cppm:779—— Luaos.archstub 硬编码'arm64',既存疑点,改为反映detect_arch_()真值。 -
[CI]tools/linux_release.sh:26,45——ARCH/MCPP_TARGET参数化(aarch64/aarch64-linux-musl)。 -
[CI].github/workflows/release.yml—— 新增build-linux-aarch64job(runs-on: ubuntu-24.04-arm),加进 releasefiles:。 -
[CI]tools/setup_musl_runtime.sh:7-26—— musl loader/SDK 路径参数化(ld-musl-aarch64.so.1)。 -
[CI]xlings-ci-linux*.yml—— 可选 aarch64 矩阵。
D-1. 必改的硬编码 loader/triple(install/config 钩子,被 elfpatch 直接消费)
-
[代码]pkgs/g/glibc.lua:33,40-42——loader=lib64/ld-linux-x86-64.so.2、abi=linux-x86_64-glibc、库清单 → aarch64 版(lib/ld-linux-aarch64.so.1/linux-aarch64-glibc)。不改会打错 INTERP。 -
[代码]pkgs/g/gcc.lua:81,106-108,169——x86_64-linux-gnu-*triple +ld-linux-x86-64.so.2→ arch 派生aarch64-linux-gnu-*。 -
[代码]pkgs/g/gcc-specs-config.lua:48,76-77,87——old_dynamic_linker表加 aarch64 项,消除:87的multi-arch?TODO。 -
[代码]pkgs/g/gcc-runtime.lua:67—— 内层目录名 arch 化。 -
[代码]pkgs/l/llvm.lua:117,124,142-143,165,256—— 内层目录 + triplex86_64-unknown-linux-gnu+ 链接器 → aarch64。 -
[代码]pkgs/l/llvm-tools.lua:24-25—— url 表 arch 化。 -
[代码]pkgs/m/musl-gcc.lua:59-79,83,162-167,225—— 改动最大,整套x86_64-linux-musl-*+ld-musl-x86_64.so.1→aarch64-linux-musl-*。 -
[代码]pkgs/m/mcpp.lua:41、pkgs/p/patchelf.lua:39——url_template写死 x86_64,仅影响 CI version-check,install 走 XLINGS_RES。
D-2. 元数据
-
[代码]各包archs={...}加aarch64(gcc/glibc/binutils/ninja/patchelf/linux-headers/gcc-runtime/llvm-tools 当前只{x86_64})。
D-3. 委托型
-
[构建]pkgs/l/linux-headers.lua—— 委托scode:linux-headers,需源包提供 aarch64 内核头(asm/)。
D-0. (可选/长期)DSL 引擎扩展 per-arch URL
-
[决策]``[代码]xim-pkgindex/docs/specs/url-template.md:69列为 TODO。两种形态择一:- 形态 A(推荐):让显式 URL 也支持
{arch}占位 + 引擎按detect_arch_()填(与 XLINGS_RES 同源)。 - 形态 B:新增平台 key
linux-aarch64(沿用ubuntu={ref="linux"}继承哲学),引擎识别。 - 注:mcpp 工具链链几乎全走 XLINGS_RES,此项主要为将来镜像上游显式 URL 的包铺路,非主链阻塞。
- 形态 A(推荐):让显式 URL 也支持
安装入口
-
[代码]install.sh:28-38——case加Linux-aarch64) PLAT="linux-aarch64" ;;(映射aarch64),改行 33 文案。
生产代码硬编码 loader/triple
-
[代码]src/platform/linux.cppm:85—— runtime lib dir 写死x86_64-unknown-linux-gnu→ 按探测 triple 拼。 -
[代码]src/build/flags.cppm:336——--dynamic-linker写死ld-linux-x86-64.so.2→ arch 派生ld-linux-aarch64.so.1。 -
[代码]src/pack/pack.cppm:648—— PT_INTERP 写死/lib64/ld-linux-x86-64.so.2→/lib/ld-linux-aarch64.so.1(且不在/lib64)。 -
[代码]src/pack/pipeline.cppm:37,61—— pack 默认 target 写死x86_64-linux-musl→ 按 host 推导。 -
[代码]src/toolchain/post_install.cppm(93/115/118/146/249/306/319)、src/toolchain/lifecycle.cppm(382/387/406/407)—— glibc loader 名 +x86_64-*triple 目录(patchelf/specs/cfg 修复链)→ arch 派生。 -
[代码]建议新增src/platform/common.cppm的host_arch抽象 +arch→loader映射表,统一上面所有点(当前只有 OS 维度,无 CPU arch 维度)。
配置
-
[代码]mcpp.toml:24—— 新增[target.aarch64-linux-musl](前提:xlings 有 aarch64 musl-gcc)。 -
.xlings.json:3—— bootstrap pin 纯版本号,无需改 arch(前提:xim-x-mcpp 有 aarch64 资产)。
发布/CI
-
[CI].github/workflows/release.yml—— 新增 aarch64 job(runs-on: ubuntu-24.04-arm)或 matrix;改行 102(xlings 引导下载)、127/131/143-146(--target/资产名)、165-168(别名)、248-256(files:)。 -
[CI]ci-linux.yml/ci-fresh-install.yml—— 可选 aarch64 leg。 -
[代码]README.md:215/README.zh-CN.md:215——Linux aarch64状态 🔄→✅。
测试夹具
-
[代码]tests/unit/*、tests/e2e/*.sh多处断言x86_64-linux-*路径 → 参数化或加 aarch64 用例。
顺手 bug(非 arch,但影响所有 Clang 宿主)
-
[代码]src/doctor.cppm:106—— std 模块检查只认std.gcm,Clang 产std.pcm会误报。
只为跑通 gcc 路线的 xlings install mcpp + mcpp build:
⓪ 引导第0个 aarch64 mcpp
→ ① 构建 gcc/glibc/binutils/ninja aarch64(linux-headers 走 scode)
→ ② 上架 aarch64 资产(8 个最小主链包)
→ ③ libxpkg elfpatch + glibc.lua loader 修正
→ ⑤ mcpp 4 处硬编码 + install.sh + release.yml aarch64 job
llvm(clang/import std)、musl-gcc、DSL 扩展可作为第二阶段。
| 结论 | 出处 |
|---|---|
引擎 arch token:Linux=aarch64 / macOS=arm64(平台感知) |
xlings/src/core/xim/installer.cppm:123-133 detect_arch_() |
| XLINGS_RES 自动拼 arch | xlings/src/core/xim/installer.cppm:146 build_xlings_res_url_ |
| 依赖解析只按 OS 不按 arch | xlings resolver/catalog/index 全用 platform key |
| DSL 不支持同平台 per-arch URL | xim-pkgindex/docs/specs/url-template.md:69-72 |
| elfpatch loader 只列 x86_64 | libxpkg/.../elfpatch.lua:287-289,315-317 |
| mcpp 二进制全静态(musl) | mcpp/mcpp.toml:24-26 [target.x86_64-linux-musl] linkage=static |
| mcpp 静态链接不挂 glibc payload | mcpp/src/build/flags.cppm:322-323 |
triple 由 -dumpmachine 动态产出 |
mcpp/src/toolchain/probe.cppm:260-269 |
目标 A(aarch64-linux)做完,在 Termux 原生(bionic)上仍不能直接用,因为 Android 用 bionic libc,与 glibc/musl ABI 不兼容,且全生态零 android 平台维度。
额外阻塞:
- xlings/xim-pkgindex 需新增
android/termux平台 key(改src/platform/、所有entries.find(platform)、索引数据)。 - ELF loader 完全不同(
/system/bin/linker64、Termux$PREFIX/lib),elfpatch 的 ld-linux 假设全失效。 - sysroot 在
$PREFIX,glibc 探测(/usr/include、features.h、/lib64)全不成立。 - 工具链需 NDK
aarch64-linux-android或 Termux 自身工具链。
推荐取巧路线: 优先做 aarch64-linux-musl 全静态 —— 产物和工具链全静态,同时绕开 bionic ABI 和 "glibc 能否在 Android 内核运行" 两个变量。代价是 musl-gcc.lua 那套三元组/loader 改动量大(§4 D-1)。
给 #143 报告人的最快验证: 出一个 aarch64-linux-musl 全静态 mcpp,让其在 Termux 原生直接跑(不进 proot)试探;或先用 aarch64-linux glibc 包在 proot-distro(Ubuntu)里验证 self-contained 路线成立。
- LLVM 官方
Linux-ARM64libc++ 是否带std.cppm+-print-library-module-manifest-path(决定 aarch64 上import std是否开箱即用)。 - GitHub
ubuntu-24.04-armrunner 在本项目 org 是否可用(决定原生构建 vs 交叉)。 -
scode:linux-headers是否已有 aarch64 源(委托型,§4 D-3)。 - CN 镜像(gitcode)aarch64 资产同步是否需要额外脚本(参考 [[release-publish-pipeline]] 的双端镜像流程)。