## 问题描述 升级到近期版本后,在同一工作空间依次构建 CLI → GUI → CLI,公共依赖 core 会反复重新编译,即使源码、工具链、profile 和 core 自身的配置都没有变化。 当前使用 mcpp `2026.10.26.1`。从已有构建日志、编译数据库和上游实现看,原因指向 `2026.10.24.1` 引入的 release 默认 `trim_paths = true`:本次构建计划中所有包的路径映射都被追加到全局编译参数,所选成员发生变化时,公共依赖的编译命令也跟着变化。 路径裁剪本身是有用的功能,但不相关消费方的加入或移除,不应该使公共依赖失去增量复用。 ## 环境 - Windows x64 - mcpp:`2026.10.26.1` - 工具链:`llvm@23.1.3`,目标 `x86_64-pc-windows-msvc` - MSVC:`14.51.36231` - Windows SDK:`10.0.26100.0` - 同一个工作空间,release profile(`opt = 3`、`debug = true`、`lto = true`),未显式配置 `trim_paths` ## 工作空间关系与复现步骤 实际项目关系简化如下: ```text workspace ├── gpp.core 公共库 ├── gpp.version 公共版本模块 ├── gpp.cli → gpp.core、gpp.version ├── gpp.gui → gpp.core、gpp.version、gpp.updater(artifact) └── gpp.updater ``` CLI 和 GUI 都是同一个工作空间的成员,使用相同的工具链和 release 配置,`gpp.core` 的包配置与构建脚本在两种选择下相同。 在工作空间根目录,不修改任何源文件,依次执行: ```powershell mcpp build -p GPPCLI mcpp build -p GPPGUI mcpp build -p GPPCLI ``` 预期:第一次构建完成后,切换消费者时仍然复用 core 的对象文件和 BMI。 实际:切换后 core 重新编译,再切回来又重新编译。CLI 和 GUI 共用同一个配置目录及 core 输出路径,因此会反复覆盖这些公共对象。 ## 已有产物中的证据 以下是实际生成参数的摘录,工作空间路径统一简化为 `D:/work/GPP`。 CLI 的编译数据库中,**core 源文件**的编译命令包含: ```text -ffile-prefix-map=D:/work/GPP/GPPCLI=cli@3.2.9 -ffile-prefix-map=D:/work/GPP/GPPVersion=version@3.2.9 -ffile-prefix-map=D:/work/GPP/GalTranslPP=core@3.2.9 ``` GUI 的已有 verbose 构建日志中,全局编译参数则包含: ```text -ffile-prefix-map=D:/work/GPP/GPPGUI=gui@3.2.9 -ffile-prefix-map=D:/work/GPP/Updater=updater@3.2.9 -ffile-prefix-map=D:/work/GPP/GPPVersion=version@3.2.9 -ffile-prefix-map=D:/work/GPP/GalTranslPP=core@3.2.9 ``` 这些映射进入全局 `cxxflags`,所以即使 core 自身的代码和选项相同,它的实际编译命令也随 CLI / GUI 的选择而变化。Ninja 因编译命令变化而将公共对象判为过期,符合当前观察到的重编行为。 两种选择的配置目录均为 `target/x86_64-windows-msvc/e15bf6648b405e65`;公共对象使用相同的 `obj/gpp_core/...` 路径。 本次排查通过读取已有构建记录和源码进行,没有为这个 issue 额外执行一轮完整的 CLI → GUI → CLI 构建,也没有将上述结构另建为独立最小项目运行。 ## 相关更新与实现 - [2026.10.24.1 更新说明](https://github.com/mcpp-community/mcpp/releases/tag/v2026.10.24.1):新增 `trim_paths`,release / dist 默认启用。 - [`src/build/plan.cppm`](https://github.com/mcpp-community/mcpp/blob/d5ec182876d9dc2392af2b503a74623914c3a3f5/src/build/plan.cppm):`trim_map(packages, ...)` 从当前计划的包集合构造 `plan.trimMap`。 - [`src/build/flags.cppm`](https://github.com/mcpp-community/mcpp/blob/d5ec182876d9dc2392af2b503a74623914c3a3f5/src/build/flags.cppm):将整张 `plan.trimMap` 追加到全局编译参数 `opt_flag`,随后进入 `f.cxx` / `f.cc`。 这会让公共包的编译参数依赖于当前选择的其他成员,破坏工作空间中“同一配置的公共依赖只编译一次”的行为。 ## 临时规避与期望 按配置语义,可以临时关闭裁剪,以去掉这组变化的参数: ```toml [workspace.profile.release] trim_paths = false ``` 这里记录的是规避方式,没有在本次排查中修改项目配置并重新构建验证。 期望开启 `trim_paths` 时,共享源文件的有效编译参数也能在不同消费方选择之间保持稳定。修复时需要考虑包映射的集合及顺序,而不只是把 CLI / GUI 写进输出目录指纹;后者会通过分开输出目录来避免覆盖,却仍然不能复用相同的 core 编译结果。
Activity
fix: GCC module maps name the BMI directory, keyed in the cache; trim…