三件小事,同一个根源:关于 MSVC 模块构建状态的三处陈述都过期了,而代码早就走通了。它们互不依赖,但一起修最省事。
发现于 #411 收尾时追查「.ixx 在三家编译器上到底能不能用」。
1. mcpp toolchain default msvc 印一句过期的假话(用户可见)
src/toolchain/lifecycle.cppm:664:
std::println("note: `mcpp build` with native MSVC (cl.exe) is not yet "
"supported — coming in a later release.");
return 0;
但它是假的。 判据两条:
-
grep -rn "CompilerId::MSVC" src/build/*.cppm 的 6 处命中没有一处是拒绝/早退 —— 全是走不同分支(VC tools 探测、方言选择、命名)。构建路径里没有 MSVC 的门。
-
tests/e2e/99_msvc_native_build.sh 断言的是一次完整的原生模块构建:
out=$("$MCPP" build 2>&1) || { echo "FAIL: msvc build"; exit 1; }
[[ "$run_out" == *"cl-ok"* ]] # 跑出结果
find target -path "*ifc.cache*" -name "*.ifc" | grep -q . # 产出 .ifc
它在 toolchains + regressions (windows x64) 里以 -e -o pipefail 执行,该 job 绿。
这句 note 的实际效果是劝退一个能用的功能:用户切到 msvc,看到"还不支持",就不会去试。
修法:删掉这行,或改成陈述当前真实状态(例如 .ifc 管线已就位、已知限制是什么)。
2. tests/e2e/95_msvc_system_toolchain.sh 的头注释与它自己的断言矛盾
第 9 行:
# - `mcpp build` fails with the owned "not yet supported" gate message
而这个文件里没有任何一条断言在做这件事 —— 它的断言在第 35–59 行,全部止于工具链探测/选择/pin 校验。
95 说 build 会被 gate 挡住,99 说 build 会成功并产出 .ifc,两者同时绿 —— 因为 95 那句只是注释。
修法:把这行从头注释里删掉。
3. ⚠️ 217_module_extensions.sh 在 Windows 与 macOS 上整条被跳过
tests/e2e/217_module_extensions.sh 第 2 行是 # requires: gcc。而 run_all.sh 明确不在 Windows / macOS 上授予 gcc:
# NOTE: Windows runners may have g++.exe (MinGW/Strawberry) in PATH
# but it's not a proper mcpp-compatible GCC. Don't add gcc capability.
# macOS g++ is Apple Clang, not real GCC — don't add gcc capability.
⇒ [build] module_extensions 只在 Linux 上被测过(那里覆盖了 GCC 与 Clang 两条腿)。
后果:「用户声明 module_extensions = [".ixx"] 然后在 MSVC 上构建」这条路没有任何测试走过。 它推理上必然通(.ixx 是 cl 的原生后缀,而 mcpp 无条件发 /interface /TP),但推理不是测量。macOS 同理(那边默认 LLVM,等同已验证的 Clang 档,同样没测)。
这与 #411 里指出 #272 的问题是同一形状——「# requires: elf gcc 让 Clang/MSVC 从未被走到」——只是程度轻一些。
修法:补一条不依赖 gcc 能力的 219,按平台选默认工具链(Windows→msvc + llvm,macOS→llvm),验证 .ixx / .ccm 走完 build→link→run。
为什么值得一起修
三条都是**「写下来的状态」与「实际行为」脱节**:两处陈旧文字 + 一处没被测试覆盖到的平台。修完之后,「mcpp 在 MSVC 上支持模块构建、并且 .ixx 可以通过 module_extensions 使用」这句话就有了代码、文字、测试三方一致的支撑。
已知事实速查(供实施时参考)
| 编译器 |
驱动原生认 .ixx? |
mcpp 发什么 |
验证状态 |
MSVC cl |
✅ 原生(它自己的约定) |
/interface /TP |
模块构建 e2e 99 绿;.ixx + module_extensions 未测 |
| GCC 16.1.0 |
✅ |
-x c++ |
e2e 217 四后缀 build→link→run ✅ |
| Clang 22.1.8 |
❌ 当链接输入,退出码 0 且不产 BMI |
-x c++-module |
e2e 217 四后缀 build→link→run ✅ |
反过来 .cppm 是 GCC/Clang 认、cl 不认的那个(ninja_backend.cppm:666 原话:"our module interfaces are .cppm, unknown to cl")。两家互为盲区,所以 mcpp 每次都显式声明,不去维护"谁认哪个后缀"的表 —— 那张表会随编译器版本过期,而错了是退出码 0 的静默空转。
三件小事,同一个根源:关于 MSVC 模块构建状态的三处陈述都过期了,而代码早就走通了。它们互不依赖,但一起修最省事。
发现于 #411 收尾时追查「
.ixx在三家编译器上到底能不能用」。1.
mcpp toolchain default msvc印一句过期的假话(用户可见)src/toolchain/lifecycle.cppm:664:但它是假的。 判据两条:
grep -rn "CompilerId::MSVC" src/build/*.cppm的 6 处命中没有一处是拒绝/早退 —— 全是走不同分支(VC tools 探测、方言选择、命名)。构建路径里没有 MSVC 的门。tests/e2e/99_msvc_native_build.sh断言的是一次完整的原生模块构建:它在
toolchains + regressions (windows x64)里以-e -o pipefail执行,该 job 绿。这句 note 的实际效果是劝退一个能用的功能:用户切到 msvc,看到"还不支持",就不会去试。
修法:删掉这行,或改成陈述当前真实状态(例如
.ifc管线已就位、已知限制是什么)。2.
tests/e2e/95_msvc_system_toolchain.sh的头注释与它自己的断言矛盾第 9 行:
而这个文件里没有任何一条断言在做这件事 —— 它的断言在第 35–59 行,全部止于工具链探测/选择/pin 校验。
95 说 build 会被 gate 挡住,99 说 build 会成功并产出
.ifc,两者同时绿 —— 因为 95 那句只是注释。修法:把这行从头注释里删掉。
3.⚠️
217_module_extensions.sh在 Windows 与 macOS 上整条被跳过tests/e2e/217_module_extensions.sh第 2 行是# requires: gcc。而run_all.sh明确不在 Windows / macOS 上授予gcc:⇒
[build] module_extensions只在 Linux 上被测过(那里覆盖了 GCC 与 Clang 两条腿)。后果:「用户声明
module_extensions = [".ixx"]然后在 MSVC 上构建」这条路没有任何测试走过。 它推理上必然通(.ixx是 cl 的原生后缀,而 mcpp 无条件发/interface /TP),但推理不是测量。macOS 同理(那边默认 LLVM,等同已验证的 Clang 档,同样没测)。这与 #411 里指出 #272 的问题是同一形状——「
# requires: elf gcc让 Clang/MSVC 从未被走到」——只是程度轻一些。修法:补一条不依赖
gcc能力的219,按平台选默认工具链(Windows→msvc + llvm,macOS→llvm),验证.ixx/.ccm走完 build→link→run。为什么值得一起修
三条都是**「写下来的状态」与「实际行为」脱节**:两处陈旧文字 + 一处没被测试覆盖到的平台。修完之后,「mcpp 在 MSVC 上支持模块构建、并且
.ixx可以通过module_extensions使用」这句话就有了代码、文字、测试三方一致的支撑。已知事实速查(供实施时参考)
.ixx?cl/interface /TP.ixx+module_extensions未测-x c++-x c++-module反过来
.cppm是 GCC/Clang 认、cl 不认的那个(ninja_backend.cppm:666原话:"our module interfaces are .cppm, unknown to cl")。两家互为盲区,所以 mcpp 每次都显式声明,不去维护"谁认哪个后缀"的表 —— 那张表会随编译器版本过期,而错了是退出码 0 的静默空转。