fix(pm): install_path 跨命名空间返回了别的包的目录 (2026.8.6.1) - #364
Merged
Conversation
…#346) Every mcpp CI job builds either mcpp itself (tens of TUs) or a synthetic e2e project (single digits). Link-line length, the response-file path and ninja graph size over a large object set therefore had no coverage at all, and the whole command-length defect family surfaced in the ecosystem instead: #274 ninja goals argv 50781 chars vs cmd.exe 8191 #247 Windows CreateProcess 32 KiB #345 POSIX MAX_ARG_STRLEN 128 KiB #360 link.exe LNK1170, response-file line capped at 128 KiB 190 asserts the shape of the generated rule at 25 objects. 191 asserts the scale: 1400 C TUs whose object list is 140 KiB, past the largest command-line ceiling in cmdlimits.cppm, required to link and to run. The regime is asserted rather than assumed. Object naming, the disambiguation prefix and the file count all influence how large the list actually is, so the response file's size is checked against the ceiling directly: if it ever falls back under, the test reports that it has stopped covering the axis instead of passing quietly. Verified to fail without the fix — reverting the generated cxx_link rule to its pre-#345 inline form on this project reproduces the original symptom verbatim: `ninja: fatal: posix_spawn: Argument list too long`. Cost: 1.3s wall on a developer machine. Padded file names carry the object paths to ~100 bytes so the ceiling is reached at a file count this small, bounded on the other side by Windows MAX_PATH.
`Fetcher::install_path(ns, shortName, version)` 回答的是"**这个**包装在哪"。它最后
那道 legacy 扫描却匹配任何以 `-x-<shortName>` 结尾的目录、不看命名空间,于是查
`ocornut:imgui@1.92.8` 会返回 `compat-x-imgui/1.92.8` —— 另一个仅仅短名相同的包。
调用方随后(a)认为"已安装"而跳过安装,(b)把那个包的源码树当作本包读取。
**危险形态是静默的。** 我是在一个 Form B 邻居上撞见的,所以错误的 verdir 里没有
mcpp.toml,构建停在 "index entry has no `mcpp = ...` field" —— 一个指向错误原因的
诊断。而当两个包的源码都在 verdir 里时,没有任何报错:构建**编译了另一个包的源码
并成功**。e2e 192 在旧二进制上正是这么红的:
Compiling acme.widget v1.5.0
Finished dev [unoptimized + debuginfo] in 0.07s
FAIL: build succeeded, so acme:widget was satisfied from somewhere —
the only widget payload on disk belongs to compat.
**为什么一直够不到。** install_path 同时匹配版本,所以同短名的两个包只有在版本也相
同的时候才会撞;而生态里 module 层用的是打包计数(`imgui@0.0.6`),compat 用的是上
游版本(`compat.imgui@1.92.8`),永远不撞。把 module 层的版本对齐到上游
(mcpp-index#163)之后它们就重合了 —— 这个 bug 是被那次对齐**逼出来**的,不是新引入的。
修法:bare `-x-<shortName>` 这一支现在要求目录自身的命名空间前缀是调用方确实问过的
(请求的 ns,或旧式 index-prefixed 布局里的 index 名)。`-x-<ns>.<name>` 那一支把命
名空间带在后缀里,无需前缀约束。这保住了它存在的两种旧布局,拒掉的正是它从不该服务
的那一种。
顺带修诊断:`<verdir>` 是个字面占位符,无法区分"包是 Form B 而你忘了写 mcpp 字段"
与"mcpp 解析到的 verdir 根本不是这个包的"。现在打印真实路径,并在后一种情况下点名。
验证:
* 单测 4 条(tests/unit/test_fallback_legacy_dirs.cpp),含"仍要找得到自己命名空间的
短名布局"与"index-prefixed 旧布局"两条防止修过头。
* e2e 192,实测旧二进制红、修复后绿。
* 真实复现同环境 A/B:store 里有 compat-x-imgui/1.92.8 时,ocornut:imgui@1.92.8 在
旧二进制上失败、在修复后正常安装并构建。
* 59 个单测全过。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
症状
Fetcher::install_path(ns, shortName, version)回答的是"这个包装在哪"。它最后那道 legacy 扫描匹配任何以-x-<shortName>结尾的目录、不看命名空间:于是查
ocornut:imgui@1.92.8返回compat-x-imgui/1.92.8—— 另一个仅仅短名相同的包。调用方随后跳过安装("已存在"),并把那个包的源码树当作本包读取。危险形态是静默的
我是在一个 Form B 邻居上撞见的,所以错误的 verdir 里没有 mcpp.toml,构建停在
index entry has no mcpp = ... field—— 一个指向错误原因的诊断,我因此在错误方向上找了一阵。当两个包的源码都在 verdir 里时,没有任何报错。e2e 192 在旧二进制上红的正是这个:
编译的是 compat 的源码,冠以 acme.widget 的名字,然后成功。
为什么现在才够得到
install_path同时匹配版本,所以同短名的两个包只有在版本也相同时才撞。而生态里 module 层用的是打包计数(imgui@0.0.6),compat 用的是上游版本(compat.imgui@1.92.8)—— 永远不撞。把 module 层版本对齐到上游(mcpp-index#163)之后它们重合了。这个 bug 是被那次对齐逼出来的,不是新引入的,而它挡住了整个迁移。
修法
bare
-x-<shortName>这一支现在要求目录自身的命名空间前缀是调用方确实问过的(请求的 ns,或旧式 index-prefixed 布局里的 index 名)。-x-<ns>.<name>那一支把命名空间带在后缀里,无需前缀约束。保住它存在的两种旧布局,拒掉它从不该服务的那一种。顺带修诊断:
<verdir>是字面占位符,无法区分"Form B 忘了写 mcpp 字段"与"解析到的 verdir 根本不是这个包的"。现在打印真实路径,并在后一种情况下点名。验证
tests/unit/test_fallback_legacy_dirs.cpp),含两条防止修过头的:仍要找得到自己命名空间的短名布局、以及 index-prefixed 旧布局。compat-x-imgui/1.92.8时,ocornut:imgui@1.92.8在旧二进制上失败、在修复后正常安装并构建。