Skip to content

feat: promote riscv64-linux-musl from planned to verified cross target - #402

Open
lildengzi wants to merge 2 commits into
mcpp-community:mainfrom
lildengzi:riscv64-linux-musl-verified
Open

feat: promote riscv64-linux-musl from planned to verified cross target#402
lildengzi wants to merge 2 commits into
mcpp-community:mainfrom
lildengzi:riscv64-linux-musl-verified

Conversation

@lildengzi

Copy link
Copy Markdown
Contributor

内容

riscv64-linux-muslplanned 提升为 verified 交叉目标,与已 verified 的 aarch64-linux-musl 对齐。

  • src/toolchain/triple.cppmriscv64-linux-musl 状态 planned → verified,约定工具链 pin gcc@16.1.0
  • .github/workflows/cross-build-test.yml:cross 矩阵加 riscv64-linux-musl 行(qemu-riscv64-staticfile 断言 UCB RISC-V),支持矩阵注释同步。
  • tests/e2e/103_target_vocabulary.sh:planned-tier 断言示例改用仍为 plannedaarch64-linux-gnu
  • tests/unit/test_linkmodel.cpp:补 riscv64 loader 断言(musl ld-musl-riscv64.so.1 + glibc ld-linux-riscv64-lp64d.so.1)。
  • README.md / README.zh-CN.md:平台表 riscv64-linux-musl 标为 ✅,注明基础 rv64gc/lp64d ISA,可选扩展(-march=rv64gcv、Zb*)自行指定。

前置依赖

本 PR 的 cross-build CI 需要 xim:riscv64-linux-musl-gcc@16.1.0 能从索引拉到,该工具链包由 openxlings/xim-pkgindex#585 提供(musl-cross-make 源码构建,gcc 16.1.0,全静态)。

两个 PR 联动:#585(工具链包)先合入,本 PR(mcpp 侧 planned→verified)随后。

验证

本地端到端实测(工具链手动装进本机 xpkgs,模拟 #585 合入后的状态):

  • mcpp build --target riscv64-linux-musl 在 toy_kernel(RISC-V 64 freestanding)上完整跑通:
    • 正确解析工具链 riscv64-linux-musl-g++(从本地 payload,不再触发下载)
    • 编译全部 .cppm/.cpp/.S 源码 → target/riscv64-linux-musl/ 下产物
    • 产物为 ELF 64-bit LSB relocatable, UCB RISC-V, RVC, double-float ABI
  • 裸机链接(-nostartfiles -nostdlib -static -T link.ld)→ ELF 64-bit LSB executable, UCB RISC-V, statically linked
  • qemu-riscv64 实测运行:输出 "Hello from toy_kernel!"
  • 单元测试:mcpp test linkmodel(12 passed)、mcpp test triple(16 passed)
  • tests/e2e/103_target_vocabulary.sh:OK(planned 断言正确落在 aarch64-linux-gnu)

未验证:可选 ISA 扩展集(V 向量、Zb* 位操作)不在本 PR 范围——工具链实测支持 -march=rv64gcvrv64gc_zba_zbb 等编译,但不属于基础三元组,需构建时显式指定,未做运行验证。

范围 / 非目标

  • riscv64-linux-muslhosted RISC-V Linux 用户态目标(rv64gc/lp64d 基础 ISA,musl),与 aarch64-linux-musl 同构。
  • 覆盖裸机/freestanding(riscv64-none-elf、自定义 link.ld、qemu -kernel 启动)——mcpp 嵌入式设计(决策 feat: lib-root convention (Levels 1+2) #15)已推迟,本 PR 不含。

@Sunrisepeak

Copy link
Copy Markdown
Member

Review:代码侧正确,3 处要处理

前置依赖已满足openxlings/xim-pkgindex#585 已合入 main(66adc53a),Publish Index Artifact / pkgindex test / xpkg-mirror-release 全绿,xim:riscv64-linux-musl-gcc@16.1.0 现在可以从索引拉到(并且带 per-arch checksum,走 xlings-res GitHub + GitCode 双镜像)。

一、必须处理

1. 与 main 冲突mergeStateStatus: DIRTY

实测 trial merge:只有 .github/workflows/cross-build-test.yml 是真冲突 —— main 上那张支持矩阵注释表已经多了 x86_64-linux-musl | windows→linux 一行,本 PR 是在旧的两行表上加的 riscv64 行。其余 4 个文件(README ×2、triple.cppmtest_linkmodel.cpp)都能自动合并。rebase 一下即可。

2. 漏改两处文档

docs/03-toolchains.md:104docs/zh/03-toolchains.md:102mcpp toolchain list 示例输出仍是:

     riscv64-linux-musl      static, cross         —                 planned

促级之后真实输出会变成 gcc 16.1.0 / available。两个 README 改了,这两处漏了。

3. feat: 缺 CHANGELOG 条目

仓库惯例是 feat: 进 CHANGELOG.md(55a39d9fdad1658783350 都有),fix:/ci:/docs: 不进。新增一个受支持 target 属于用户可见能力,应该有一条。

二、建议(不阻塞)

tests/e2e/103_target_vocabulary.sh 的 planned 档断言把硬编码从 riscv64-linux-musl 换成了 aarch64-linux-gnu —— 这一行已经是第二次因为促级被改,等 aarch64-linux-gnu 促级时还要再改一次。建议从 mcpp toolchain list 里动态取一个 planned 档 target,这个测试就不再随 target 促级而腐化。

三、已核对无误的部分

  • "只改一行表项" 确实成立to_xim_package()src/toolchain/registry.cppm:236)对 cross musl target 推导 t.str() + "-gcc"riscv64-linux-musl-gcc,与 #585 的包名逐字一致;frontend candidate riscv64-linux-musl-g++ 在 tarball 的 bin/ 里确实存在。集成路径零代码改动是对的。
  • loader_filename()src/toolchain/linkmodel.cppm:230)本来就有 riscv64 行:musl → ld-musl-riscv64.so.1,gnu → ld-linux-riscv64-lp64d.so.1。新增的两条断言是锁定既有行为,会通过。
  • is_cross_serviceable() 走 musl 分支返回 true → 该 target 会显示 available 而不是不可服务。
  • 表项形状与 aarch64-linux-musl 行完全一致(tier / note / pin / defaultStatic)。
  • e2e 换成 aarch64-linux-gnu 有效:planned 档检查(src/build/prepare.cppm:1397)在可服务性判断之前触发,且该 target 仍是 planned。
  • CI 两条 file 断言都会命中 —— 我用 #585 的工具链实测产物是 ELF 64-bit LSB executable, UCB RISC-V, RVC, double-float ABI, ..., statically linkedUCB RISC-Vstatically linked 都在;ubuntu-24.04 的 qemu-user-static 提供 qemu-riscv64-static

四、剩下的真实风险

CI 这一行要交叉编译 mcpp 和 xlings 本身(两个完整的 C++23 module 工程),而 PR 里的本地实测是 toy_kernel + import std demo —— 断言的东西比验证过的东西大一圈。

我拿 #585 的工具链做了一轮针对性压测(-static -O2 + import std):4 线程并发 + std::atomic<uint64_t> fetch_add、std::filesystem、异常抛接、std::chronostd::format/std::map,链接干净,qemu 下输出正确(counter=4000 flag=true tmp_exists=true map=2 / caught: exception path)。riscv64 交叉最常见的两个坑(libatomic、静态 libstdc++ 的异常展开表)都是通的。剩下的不确定性只是完整 module graph 的规模,这个只能靠 CI 实跑。

结论:rebase + 补两处文档 + CHANGELOG 之后可以合。

@lildengzi

Copy link
Copy Markdown
Contributor Author

明白,这个改动涉及 CI 矩阵和完整交叉编译验证,影响面较大。我觉得还是先在日常使用中观察一下工具链稳定性,暂时搁置。工具链本身已在用,等后续确认没问题或有需要再继续推进。

lildengzi and others added 2 commits August 10, 2026 18:57
- triple.cppm: mark riscv64-linux-musl verified, pin gcc@16.1.0
- cross-build-test.yml: add riscv64-linux-musl qemu matrix row
- 103_target_vocabulary.sh: use aarch64-linux-gnu as the planned-tier example
- test_linkmodel.cpp: assert riscv64 loader names (musl + glibc)
- README/README.zh-CN: riscv64-linux-musl now verified with rv64gc/lp64d note

Requires xim riscv64-linux-musl-gcc@16.1.0 (openxlings/xim-pkgindex#585).
`mcpp toolchain list`'s sample output in docs/03-toolchains.md (+ zh) still
showed riscv64-linux-musl as `— / planned`; the real output after the promotion
is `gcc 16.1.0 / available`. Verified against a built binary, not transcribed.
The row that used to illustrate the `planned` status is replaced by
aarch64-linux-gnu so the block still shows all three states.

103_target_vocabulary.sh now reads its planned-tier target out of
`toolchain list` instead of hardcoding one. That assertion is about the TIER;
with a hardcoded triple every promotion silently turns it into a test of
something else (riscv64-linux-musl was the second target to go that way), and
the check degrades to a skip once no planned target is left.
@Sunrisepeak
Sunrisepeak force-pushed the riscv64-linux-musl-verified branch from 633b553 to e811d8f Compare August 10, 2026 11:02
@Sunrisepeak

Copy link
Copy Markdown
Member

Review:代码侧全对,但 payload 不完整,这一行现在合不了

按维护者要求接手做完:已 rebase 到 main(yml 冲突已解,README/triple/test 自动合)、补了漏改的两处文档、把 103 的 planned 断言改成动态取。但在推之前本机实测了一遍真实交叉构建,失败,随后 CI 复现同一处。

一、阻塞项:riscv64 payload 的 sysroot 里没有内核 UAPI 头

本机 mcpp build --target riscv64-linux-musl(就是 CI 那一步做的事):

failed: obj/scaffold_fs.m.o gcm.cache/mcpp.platform.scaffold_fs.gcm
src/platform/scaffold_fs.cppm:15:12: fatal error: linux/fs.h: No such file or directory
   15 | #  include <linux/fs.h>

CI 同一处停下 —— job 93433367536Cross-build mcpp -> riscv64-linux-musl = failure,后面 Cross-build xlingsSmoke-run under qemu 都 skipped。

根因在两个 payload 的 sysroot 对比里,很干净:

# aarch64(已 verified 的那一行)
$ ls ~/.mcpp/registry/data/xpkgs/xim-x-aarch64-linux-musl-gcc/16.1.0/aarch64-linux-musl/include
... asm/  asm-generic/  drm/  linux/ ...          # 内核 UAPI 头齐全

# riscv64(本 PR 要 verified 的那一行)
$ ls ~/.mcpp/registry/data/xpkgs/xim-x-riscv64-linux-musl-gcc/16.1.0/riscv64-linux-musl/include
... 只有 musl 自己的头 ...
$ find ~/.mcpp/registry/data/xpkgs/xim-x-riscv64-linux-musl-gcc -type d -name linux
(空)

riscv64 那份是在没有把 Linux kernel headers 装进 sysroot 的情况下构建的(musl-cross-make 的 LINUX_HEADERS / install-headers 那一步)。aarch64 那份有。所以这不是 mcpp 缺陷,也不是本 PR 的代码问题 —— 是 openxlings/xim-pkgindex#585 的构建配方差一步。

之前那轮 review 说「工具链本身实测通过」是真的,但验的是 toy_kernel + import std demo,那些只用 musl 自己的头;mcpp/xlings 这种真实工程会碰到 UAPI,差别就出在这里。这正是当时记下的「断言的东西比验证过的东西大一圈」,只是缺口比预期的更靠前。

修法在上游:重出 riscv64-linux-musl-gcc@16.1.0(或 .1)的资产,把 kernel headers 装进 riscv64-linux-musl/include/,与 aarch64 那份对齐。之后本 PR 原样重跑 CI 即可 —— 代码侧不需要再动。

附一个可能有用的事实,但不建议用它绕过:mcpp 全仓对内核 UAPI 的依赖只有这一处,src/platform/scaffold_fs.cppm:15<linux/fs.h>,而且只为拿 RENAME_NOREPLACE 这一个 ABI 稳定的常量。手写常量能让 mcpp 这半边过,但 CI 这一行还要交叉编译 xlings,而且让构建去容忍一份缺头的 sysroot,等于把下一次同类缺口推迟到更难定位的地方。缺的是 payload,就补 payload。

二、已经做完、等 payload 就绪即可用的部分

  • rebase 到 main:真冲突只有 .github/workflows/cross-build-test.yml 那张注释表(main 上多了 x86_64-linux-musl | windows→linux 一行),按 main 的列宽插入 riscv64 行。
  • 补两处漏改的文档docs/03-toolchains.mddocs/zh/03-toolchains.mdtoolchain list 示例。改后的行是拿构建出来的二进制真跑一遍抄的,不是手写:riscv64-linux-musl static, cross gcc 16.1.0 available;原来演示 planned 状态的位置换成 aarch64-linux-gnu,示例仍然三种状态齐全。
  • 103_target_vocabulary.sh 不再写死 planned 目标:改成 toolchain list | awk '$NF=="planned"{print $1; exit}'。那条断言测的是档位,写死三元组的话每次促级它就悄悄变成在测别的东西(riscv64 已经是第二个);没有 planned 目标时退化为 skip。
  • 核对无误loader_filename() 本来就有 riscv64 行,新增的两条断言实测通过(test_linkmodel --gtest_filter=LoaderFilename.* 单独跑过,不是靠全量绿);to_xim_package() 推导出的 riscv64-linux-musl-gcc 与索引里的包名逐字一致(pkgs/r/riscv64-linux-musl-gcc.lua 存在,HTTP 200);表项形状与 aarch64 行一致。

三、结论

分支已更新到可合状态,但先不合:合进去等于让 main 常驻一个红的 cross-build riscv64-linux-musl,并且 README 上挂一个 ✅ 是假的。等 #585 的资产带上 kernel headers 重出后重跑 CI,绿了再合。

(这也和作者自己「先观察一下工具链稳定性,暂时搁置」的判断一致 —— 只是现在有了具体的、可执行的解除条件。)

🤖 Generated with Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants