Skip to content

Commit 3bbd4bc

Browse files
committed
fix(pkgs): chriskohlhoff.asio name 回归 FQN 形式 + lint 守卫 (mcpp#278)
#109 把 pkgs/c/chriskohlhoff.asio.lua 的 name 从 "chriskohlhoff.asio" 改成 "asio"(namespace 不变),这是该 commit 对描述符的唯一功能性改动, 其余全是注释重写。结果三平台 workspace job 全部在 tests/examples/asio-module 上失败: E_NOT_FOUND: package 'chriskohlhoff:chriskohlhoff.asio@1.38.1' not found 原因是 mcpp 内部两条规则对同一份描述符的口径不一致:身份归一化层 (manifest/xpkg.cppm canonical_xpkg_identity)认为 split 形式 (namespace="chriskohlhoff" + name="asio")与 FQN 形式等价、都合法, 而安装目标构造层(build/prepare.cppm)硬假设 name 字面值就等于 ns + "." + shortName。xlings/libxpkg 按前者的 name 字面值建索引 key (entries[package.name] = "asio"),mcpp 却拿 "chriskohlhoff.asio" 去点名, 两者永远不相交。 实测四种消费端写法(点式选择器、ns 表内点式、default 索引裸名、别名索引 裸名)全部无解 —— ns 被身份闸门钉死、短名被 xpm 版本表钉死,fqname 恒为 chriskohlhoff.asio 而 key 恒为 asio。等价约束是 name 必须 == namespace + "." + <短名>,只能在描述符里修。 改动: * pkgs/c/chriskohlhoff.asio.lua — name 写回 FQN 形式(与索引内其余 47 个 namespaced 包一致)。文件路径、namespace、消费端 mcpp.toml 均不动。 * pkgs/t/tensorvia-cpu.lua — 同类隐患(ns="aimol" + name="tensorvia-cpu"), 今天没被任何 workspace member 消费所以没暴露,但同样装不上;一并修正。 该文件是 `mcpp emit xpkg` 生成后手工补了 namespace 才落入 split 形式。 * tests/check_package_name.lua + validate.yml rule 5 — namespace 非空时 强制 name 以 "<namespace>." 开头。lint 秒级拦下,不再让这类错误跑满 三平台一小时后才炸。 验证(CI 钉住的 mcpp 0.0.102 + vendored xlings 0.4.67,冷 store 冷索引缓存): tests/examples/asio-module → 5 passed; 0 failed。lint 全量重放 exit 0, 负向测试(把 name 改回 split 形式)如期报错。 上游已提 mcpp-community/mcpp#278:mcpp 要么构造 target 时用描述符声明的 name(loadVersionDep 里 luaContent 已在作用域内),要么收紧规范让 `mcpp xpkg parse` 直接拒绝 split 形式。本 lint 是上游对齐前索引侧的守卫。
1 parent 788ce06 commit 3bbd4bc

4 files changed

Lines changed: 106 additions & 3 deletions

File tree

.github/workflows/validate.yml

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,18 @@ jobs:
9090
if ! lua5.4 tests/check_mirror_urls.lua "$f"; then
9191
fail=1
9292
fi
93-
# 5. c++fly admission policy (mcpp design 2026-07-14 §11-Q2, v1):
93+
# 5. `name` must be the fully-qualified `<namespace>.<short>`.
94+
# The split form (namespace = "chriskohlhoff", name = "asio")
95+
# parses and passes `mcpp xpkg parse`, but xlings keys the index
96+
# on the literal `name` while mcpp asks for the reconstructed
97+
# FQN — they never meet, so the package is uninstallable on
98+
# every platform (mcpp-community/mcpp#278). This check is cheap
99+
# and catches in seconds what otherwise fails an hour into the
100+
# workspace job.
101+
if ! lua5.4 tests/check_package_name.lua "$f"; then
102+
fail=1
103+
fi
104+
# 6. c++fly admission policy (mcpp design 2026-07-14 §11-Q2, v1):
94105
# c++fly means "toolchain's latest level + every experimental
95106
# gate" — deliberately toolchain-dependent, so a published
96107
# package built with it is not reproducible for consumers.

pkgs/c/chriskohlhoff.asio.lua

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,15 @@
3838
package = {
3939
spec = "1",
4040
namespace = "chriskohlhoff",
41-
name = "asio",
41+
-- `name` MUST be the fully-qualified `<namespace>.<short>`: xlings keys its
42+
-- index on this literal (libxpkg build_index → entries[package.name]),
43+
-- while mcpp asks for the FQN it reconstructs from the consumer's
44+
-- `[dependencies.<ns>] <short>`. Writing the split form ("asio") is legal
45+
-- per mcpp's own descriptor spec (manifest/xpkg.cppm canonical_xpkg_
46+
-- identity normalizes both spellings) but registers the index entry under
47+
-- `asio`, which no consumer request can ever hit → E_NOT_FOUND at install.
48+
-- See mcpp-community/mcpp#278; the lint in validate.yml enforces this.
49+
name = "chriskohlhoff.asio",
4250
description = "Standalone asio exposed as the C++23 module `asio` (separate compilation)",
4351
licenses = {"BSL-1.0"},
4452
repo = "https://github.com/chriskohlhoff/asio",

pkgs/t/tensorvia-cpu.lua

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
11
-- AUTO-GENERATED by `mcpp emit xpkg`. Do not edit by hand.
22
-- Source: mcpp.toml @ v0.1.1
3+
--
4+
-- Hand-edit on top of the generated file: `mcpp emit xpkg` writes the bare
5+
-- project name and no `namespace`; the `namespace = "aimol"` line below was
6+
-- added when the package was filed into this index, which made `name` the
7+
-- split form and left the package uninstallable (xlings keyed the entry under
8+
-- `tensorvia-cpu` while mcpp asks for `aimol.tensorvia-cpu`). `name` is now
9+
-- the fully-qualified spelling. See mcpp-community/mcpp#278.
310
package = {
411
spec = "1",
5-
name = "tensorvia-cpu",
12+
name = "aimol.tensorvia-cpu",
613
description = "CPU backend of Tensorvia, ported to C++23 modules",
714
licenses = {"MIT"},
815
repo = "https://github.com/Aimol-l/Tensorvia-cpu",

tests/check_package_name.lua

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
-- Lint `package.name` against `package.namespace`.
2+
--
3+
-- Rule: a namespaced descriptor MUST spell `name` as the fully-qualified
4+
-- `<namespace>.<short>`. The split form (namespace = "chriskohlhoff",
5+
-- name = "asio") parses fine and passes `mcpp xpkg parse` — mcpp's own
6+
-- identity layer normalizes both spellings to the same package — but it is
7+
-- NOT installable from an index:
8+
--
9+
-- * xlings/libxpkg keys the index on the literal `package.name`
10+
-- (libxpkg build_index → entries[package.name]), so the entry lands
11+
-- under `asio`;
12+
-- * mcpp asks xlings for the FQN it reconstructs from the consumer's
13+
-- `[dependencies.<ns>] <short>`, i.e. `chriskohlhoff.asio`
14+
-- (mcpp src/build/prepare.cppm — "xlings resolves packages by the full
15+
-- qualified name (ns.shortName) as it appears in the index's name field").
16+
--
17+
-- The two never meet → E_NOT_FOUND at install time, on every platform, after
18+
-- the workspace job has already burned an hour. No consumer-side spelling can
19+
-- work around it; the descriptor is the only place it can be fixed.
20+
--
21+
-- Upstream: mcpp-community/mcpp#278 (mcpp should either use the declared name
22+
-- or reject the split form in `mcpp xpkg parse`). Until that lands, this lint
23+
-- is the index's guard.
24+
--
25+
-- Zero-namespace packages (the public default-namespace module packages —
26+
-- imgui / ffmpeg / opencv) are unaffected: their bare `name` IS the FQN.
27+
--
28+
-- Usage: lua5.4 tests/check_package_name.lua <file.lua>
29+
30+
function import(...)
31+
return setmetatable({}, {__index = function() return function() end end})
32+
end
33+
34+
local path = assert(arg[1], "usage: check_package_name.lua <file>")
35+
package = nil
36+
local chunk = assert(loadfile(path, "t"))
37+
chunk()
38+
39+
local p = package
40+
if type(p) ~= "table" then os.exit(0) end
41+
42+
local fail = 0
43+
local function err(msg)
44+
io.stderr:write(string.format("::error file=%s::%s\n", path, msg))
45+
fail = 1
46+
end
47+
48+
local name = p.name
49+
local ns = p.namespace or ""
50+
51+
if type(name) ~= "string" or name == "" then
52+
err("package.name must be a non-empty string")
53+
os.exit(fail)
54+
end
55+
if type(ns) ~= "string" then
56+
err("package.namespace must be a string")
57+
os.exit(fail)
58+
end
59+
60+
if ns ~= "" then
61+
local prefix = ns .. "."
62+
if name:sub(1, #prefix) ~= prefix then
63+
err(string.format(
64+
"package.name must be the fully-qualified '<namespace>.<short>': " ..
65+
"namespace = %q but name = %q — write name = %q. " ..
66+
"The split form registers the index entry under %q, which no " ..
67+
"consumer request can ever resolve (E_NOT_FOUND at install). " ..
68+
"See mcpp-community/mcpp#278.",
69+
ns, name, prefix .. name, name))
70+
elseif #name == #prefix then
71+
err(string.format(
72+
"package.name = %q has an empty short name after the %q prefix",
73+
name, prefix))
74+
end
75+
end
76+
77+
os.exit(fail)

0 commit comments

Comments
 (0)