docs+ci: 本地上手三步走 + 平台矩阵拆分(linux/macos/win10/win11/win 无 MSVC STL) - #89
Conversation
README(三语 + book 两语)重写「本地练习环境」段,改成明确的三步:
1. 装工具 —— `xlings install d2x mcpp -y`,两个工具名都链到各自仓库
2. 取课程并验证环境 —— 默认 `d2x install d2mcpp` → `cd d2mcpp` → `mcpp test`;
clone 源码那条路收进 <details>,作为可选项而不是与默认路径并列的「二选一」
3. 开始练习 —— `d2x checker` / `d2x status`
第 2 步把 `mcpp test` 摆到台面上是有意的:练习就是测试,新环境跑一遍
「全部不通过」既是练习的起点,也已经证明工具链是通的。
CI 从单个 ubuntu job 拆成五档平台矩阵,每档都跑完整两层验证:
linux / macos / windows-10 线(windows-2022)/ windows-11 线(windows-2025)
/ windows 且无 MSVC STL
最后一档把 runner 上的 Visual Studio 藏掉(改名 vswhere.exe 与 VC 目录 +
清空 VS* 环境变量,并就地检查后置条件),模拟学习者的干净 Windows —— 这
才是多数人的机器。mcpp 应当自动回落到自带的 winlibs MinGW,产物 target
目录名(x86_64-windows-gnu)就是断言依据。
两层验证:
- `mcpp test`(已有 e2e.sh)—— pristine 全不过 + 覆盖答案后全过
- `d2x checker`(新增 checker-e2e.sh)—— 答案就位后 checker 必须自己走完
52 道题并退 0
加第二层是因为 checker 在 mcpp test 之上还叠了 Provider 的 NDJSON 协议、
进度持久化、文件监听三层;这三层断掉时 mcpp test 照样全绿,Windows 上就
出过这种静默回归(#87)。checker-e2e.sh 的看门狗自己用 shell 轮询实现,
不依赖 timeout(1)(macOS 默认没有)。
顺带:
- .xlings.json pin 上抬 —— mcpp 2026.8.1.1 → 2026.8.2.1(裸 Windows 自动
回落 MinGW 是这个版本才有的能力,无 MSVC STL 那一档依赖它),
d2x 2026.08.02.1 → 2026.08.02.2
- 修复文件名核对 job:它还在按迁移前的布局找 `intro/tests cpp*/tests`,
练习早已搬进 src/,于是一个文件都没扫到、永远绿。现在真的核对 52 对。
- 工作流触发路径补上 .xlings.json
本地已验:e2e.sh all(zh/en 各 52/52)、checker-e2e.sh zh 与 en 均全过。
chapter_1 是三份 README 的「更多细节」落点,但它的 §0 只装 xlings, 接着就直接 `d2x install d2mcpp` —— 一台干净的机器照着做会在第二条命令 上失败,因为 d2x 这个二进制根本还没装。 补两处,与 README 新的三步保持同一套说法: - §0 结尾加 `xlings install d2x mcpp -y`,两个工具名链到各自仓库 - §1 加「验证环境」小节:`cd d2mcpp` + `mcpp test`,并说明「刚拿到课程 时全部未通过」既是起点也是工具链已通的证据
|
CI 结果:五档全绿(run 30730372646)。macOS 与三档 Windows 是首次跑完整门课,全部一次通过。
无 MSVC STL 那一档确认不是空过 —— 遮蔽真的生效了,回落也真的发生了: 两档 baseline 的日志里没有这段回落公告(mcpp 只在回落时才打),说明它们走的确实是 MSVC —— 三档 Windows 覆盖到的是三条不同的路径,不是同一条跑三遍。 另外补了一个 commit: |
原话把 `mcpp test` 说成「验证每道练习都能编译并运行」,正好说反了:练习发 下来就是没做完的,`std:endl`、`D2X_YOUR_ANSWER` 这类东西**必然编不过**, pristine 状态下 0 passed 才是对的(e2e.sh 的断言 1 就是在守这条)。 顺带澄清一个容易误会的点:`solutions/` 不是工作区成员(mcpp.toml 的 members 里没有它),`mcpp test` 从头到尾不碰它。要它变绿得先覆盖到练习 文件上——那是 CI 的动作,不是学习者跑一条命令就会发生的事。 改成说清楚它到底验了什么:工具链解析成功、d2x 库编译通过、运行器逐题都 跑到了;练习本身红着是设计如此。README 三语 + book 两语 + chapter_1 两语 共 7 处同步。
在此之前 solutions/ 只是一堆躺在磁盘上的 .cpp:不是工作区成员,mcpp 从头到
尾不认识它。想验证答案对不对,唯一的办法是把 52 个文件覆盖到 src/*/tests/
上、跑一遍、再 git 还原 —— 一套带副作用、要求工作树干净、只有 CI 脚本会用
的流程。学习者或贡献者想确认「答案是好的」,没有一条命令可以跑。
现在 solutions/ 是一个正经工程:
solutions/mcpp.toml name=solutions, c++23, 依赖 d2x
solutions/tests/<std>/... 52 份答案,就是它的测试
于是:
mcpp test -p solutions # 52 passed; 0 failed
mcpp test -p solutions cpp11 # 按子串筛
零副作用、不碰练习目录、任何人随手可跑。布局与练习一一对应,测试名
(intro/hello-mcpp、cpp11/00-auto-and-decltype/0) 直接对回练习文件。
配置刻意与练习工程一致(c++23 + d2x),否则「答案能过」推不出「答案放进
练习里也能过」。
覆盖-还原那套 e2e 保留 —— 它验的是另一件事:答案放到练习的位置上也成立,
且练习在未完成时确实不通过。两条互补:新的这条挂了说明答案本身是错的,
旧的那条挂了说明答案与练习对不上。
- e2e.sh 新增 solutions_selftest(),并核对测试条数 == 答案文件数:测试发现
是按 tests/**/*.cpp 自动扫的,布局一改就可能一个都没扫到,而「0 个测试」
在 mcpp 眼里同样是 "test result ok"
- CI 每档平台新增独立一段 `mcpp test -p solutions`,排在覆盖-还原之前,
失败定位最短
- e2e.sh / checker-e2e.sh / 文件名核对 job 的路径映射跟随改为 solutions/tests/
上一版让 step 2 跑裸 `mcpp test`,然后解释「全红是对的」。这在逻辑上站不住:
工具链坏掉时也是全红,学习者看着同样的输出,分辨不出是自己还没做题还是环境
没装好——一个只会红的命令没法用来验证环境。
solutions/ 成为工程之后就有了确定的绿:
mcpp test -p solutions # 验证环境: 52 份参考答案, 应当全绿
mcpp test # 你的进度表: 练习还没做, 此刻全红
两条命令各自含义明确:第一条绿 = 工具链没问题;第二条红 = 你的起点。
README 三语 + book 两语 + chapter_1 两语同步。chapter_1 里另外写清了答案与
练习靠 tests/ 相对路径配对,以及 `mcpp test -p solutions cpp11` 的筛选用法。
撰稿技能(.agents/skills/d2mcpp-authoring)的路径与「答案怎么验」也跟随更新:
新增答案后可以直接 `mcpp test -p solutions <slug>` 自查,不必再走覆盖流程。
补充:
|
| 档 | mcpp test -p solutions |
|---|---|
| linux | 52 passed; 0 failed (29.6s) |
| macos | 52 passed; 0 failed (22.0s) |
| windows-10 线 | 52 passed; 0 failed (19.4s) |
| windows-11 线 | 52 passed; 0 failed (23.9s) |
| windows 无 MSVC STL | 52 passed; 0 failed (56.7s) |
顺带解决了 README step 2 的一个逻辑问题
原来 step 2 让学习者跑裸 mcpp test 然后解释「全红是对的」—— 但工具链坏掉时也是全红,两种情况输出一样,这个命令根本没法用来验证环境。现在有了确定的绿:
mcpp test -p solutions # 验证环境: 52 份参考答案, 应当全绿
mcpp test # 你的进度表: 练习还没做, 此刻全红第一条绿 = 工具链没问题;第二条红 = 你的起点。README 三语 + book 两语 + chapter_1 两语已同步,撰稿技能也更新为「新增答案后直接 mcpp test -p solutions <slug> 自查」。
step 2 摆两条命令、再解释「第一条绿第二条红」,等于在验证环境这一步塞了
一个当下用不上的概念。step 2 现在只做一件事:
mcpp test -p solutions # 验证环境: 52 份参考答案, 应当全绿
裸 `mcpp test`(你自己的进度表)本来就属于「不经过 d2x 怎么练」这一类,
归到 step 3 已有的那条可选 note 里,和 `mcpp test -p src/cpp11` 放一起:
> 不想经过 d2x? 练习就是测试 —— `mcpp test` 打印你的完整进度表(动手前
> 全红), `mcpp test -p src/cpp11` 只跑某一章。
同步的地方:
- README 三语 + book 两语:step 2 收敛为一条命令;<details> 里 clone 那条
路的环境验证也跟着改成 `mcpp test -p solutions`(原来还是裸 mcpp test)
- chapter_1 两语:「验证环境」节同样只留参考答案那条;裸 `mcpp test` 落到
已有的「原生模式(可选)」节,作为该节三条命令里的第一条
1. README:「本地练习环境」改成明确的三步
三份顶层 README(zh / zh-hant / en)与 book 两语 README 同步。
xlings install d2x mcpp -y—— 两个工具名分别链到 d2x 和 mcpp 仓库d2x install d2mcpp→cd d2mcpp→mcpp testd2x checker/d2x status原来的「方式 A / 方式 B 二选一」把 clone 源码摆成了和一键安装并列的选项,新手在第一屏就要做一个他还没有依据去做的决定。现在默认路径只有一条,clone 源码收进
<details>作为可选项。第二步把
mcpp test摆到台面上是有意的:练习就是测试。新环境跑一遍会看到「全部不通过」——这既是练习的起点,也已经证明工具链是通的。把参考答案覆盖进去,同一条命令就全绿。2. CI:单个 ubuntu job → 五档平台矩阵
最后一档是重点。 GitHub 的 Windows 镜像预装 VS 2022 Enterprise,所以在托管 runner 上「Windows 能跑」测到的其实是「装了 Visual Studio 的 Windows 能跑」——而学习者的机器多数不是这样。这一档把 VS 藏掉(改名
vswhere.exe与VC目录、清空VS*环境变量),遮蔽手法取自 mcpp 自己的ci-windows.yml,并就地检查后置条件:漏遮的后果是这一档静悄悄退化成第二个 windows-11 baseline,绿灯但什么都没验到。mcpp 应当自动回落到自带的 winlibs MinGW,产物 target 目录名就是断言依据:
test -d d2x/buildtools/target/x86_64-windows-gnu3. 每档都跑两层验证
mcpp teste2e.sh(已有)d2x checkerchecker-e2e.sh(新增)加第二层的理由:checker 在
mcpp test之上还叠了 Provider 的 NDJSON 协议、进度持久化、文件监听三层。这三层断掉时mcpp test照样全绿 —— Windows 上就出过这种静默回归(#87)。checker-e2e.sh的两条判据缺一不可:.d2x/state.json会让 checker 一道题都不编译就宣告完成并退 0看门狗用 shell 逐秒轮询自己实现,不依赖
timeout(1)(macOS 默认没有这个命令)。4. 顺带修的
.xlings.jsonpin 上抬:mcpp2026.8.1.1→2026.8.2.1,d2x2026.08.02.1→2026.08.02.2。不是可选的:裸 Windows 自动回落 MinGW 是 mcpp 2026.8.2.1 才有的能力(mcpp#332),更早的版本在无 MSVC 的机器上直接硬失败,「无 MSVC STL」那一档没有它就跑不起来。intro/tests cpp*/tests,而练习早已搬进src/,于是一个文件都没扫到、恒绿。现在真的核对 52 对。.xlings.json。验证情况
Linux 本地全部实跑通过(mcpp 2026.8.2.1 + d2x 2026.08.02.2):
macOS 与三档 Windows 只能靠本 PR 的 CI 来验 —— 手上没有对应机器,而这四档此前从未跑过完整课程(旧 CI 只有 ubuntu 一档;d2x 侧的 Windows 冒烟只断言 checker 能报出第一题的编译错误,没验过全部答案能过)。所以这几档首次运行有可能红,那正是这个 PR 想要暴露的信息。合并前请看 CI 结果。