From aeb7a0548350abb84361e6553188215abb5500af Mon Sep 17 00:00:00 2001 From: speak-agent <248744407+speak-agent@users.noreply.github.com> Date: Thu, 3 Sep 2026 12:53:19 +0800 Subject: [PATCH] manifest+docs: the recommended spelling is the namespace on the key, and the advisory teaches it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit An entry names a package and then says which version of it, so the namespace belongs to the name: "xim:picolibc-riscv" = "1.8.12". Official packages use that form. The advisory for the superseded deps key suggested the other one. That form is accepted and is what the materialised .xlings.json carries — a key there is an xvm target and the scope qualifies the version — but it is the file's vocabulary, not the author's. A suggestion is copied, so one that teaches the non-recommended form pushes the convention the wrong way. XlingsEntry::authored_line is the recommended spelling and the advisory's only source for it, so the message and the documentation cannot drift. docs/05 states the form and why the other is still accepted; docs/13 and the project-subos example follow. Both languages. Parsing is unchanged, and so is the materialised file. --- CHANGELOG.md | 24 ++++++++++++++++++ docs/05-mcpp-toml.md | 27 ++++++++++++--------- docs/13-baremetal.md | 2 +- docs/zh/05-mcpp-toml.md | 21 +++++++++------- docs/zh/13-baremetal.md | 2 +- examples/07-project-subos/README.md | 2 +- examples/07-project-subos/mcpp.toml | 2 +- mcpp.toml | 2 +- modules/manifest/src/toml.cppm | 22 +++++++++++++---- modules/versioning/src/version.cppm | 2 +- tests/e2e/331_xlings_workspace_one_table.sh | 6 +++-- tests/unit/test_manifest.cpp | 6 +++-- 12 files changed, 83 insertions(+), 35 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a3a94ec8..cf6ff563 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,30 @@ > 本文件追踪 `mcpp-community/mcpp` 公开仓的版本演进。 > 格式参考 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/)。 +## [2026.9.3.2] — 2026-09-03 + +`[xlings.workspace]` 的**推荐书写形态**定为命名空间在键上,官方包全部使用它; +mcpp 打印的建议行随之改成同一形态。 + +```toml +[xlings.workspace] +"xim:picolibc-riscv" = "1.8.12" +``` + +> **建议行是会被照抄的。** `[xlings] deps` 的替代提示此前给出的是 +> `picolibc-riscv = "xim:1.8.12"` —— 命名空间在版本上。那种形态仍然接受,但它是 +> **物化出来的文件**所用的词汇(那里的键是 xvm target,scope 限定版本),不是作者 +> 书写的词汇(先点名一个包,再说用它的哪个版本)。一个教人写非推荐形态的提示,会 +> 把约定推向它自己的反面。 + +### 变更 + +- `[xlings] deps` 的替代提示改为推荐形态,键带引号(TOML 裸键不能含冒号)。 +- `docs/05` §2.13 明确写出推荐形态与它的理由,并说明另一种形态为何仍然接受; + `docs/13` 与 `examples/07-project-subos` 的示例改成推荐形态。中英双份。 + +行为不变:两种形态解析结果完全相同,物化出来的 `.xlings.json` 也不变。 + ## [2026.9.3.1] — 2026-09-03 `[xlings]` 收敛成一张表。`[xlings.workspace]` 说出工程用哪个包、用哪个版本,mcpp diff --git a/docs/05-mcpp-toml.md b/docs/05-mcpp-toml.md index f7e2b5d3..e86f4298 100644 --- a/docs/05-mcpp-toml.md +++ b/docs/05-mcpp-toml.md @@ -1870,11 +1870,10 @@ who can judge it is looking at the release, not at this build. ```toml [xlings.workspace] # what this project's environment contains -cmake = "3.28" -picolibc-riscv = "xim:1.8.12" # namespace on the version -"xim:qemu-user-aarch64" = "7.2.0" # or on the key - quotes required -code = "" # present; version unconstrained -llvm = { macosx = "20", default = "22" } +cmake = "3.28" +"xim:picolibc-riscv" = "1.8.12" # a namespaced package - quotes required +code = "" # present; version unconstrained +llvm = { macosx = "20", default = "22" } ``` ```toml @@ -1900,14 +1899,20 @@ to. | `cmake = "3.28"` | that version | | `llvm = "22"` | the highest installed `22.*`; a version prefix resolves | | `code = ""` | present, version unconstrained | -| `picolibc-riscv = "xim:1.8.12"` | from the `xim` index | -| `"xim:picolibc-riscv" = "1.8.12"` | the same entry, namespace written on the key | +| `"xim:picolibc-riscv" = "1.8.12"` | a package from the `xim` index | | `llvm = { macosx = "20", default = "22" }` | per host platform | -The namespace may be written on either half. Writing it on the key requires -**quotes**, because a TOML bare key cannot contain a colon. Writing it on both -halves with different values is an error, and so is naming one package twice -under two spellings. +**A namespaced package is written `":" = ""`, and the +quotes are required** — a TOML bare key cannot contain a colon. That is the +recommended form and the one every official package uses: an entry names a +package and then says which version of it, so the namespace belongs to the +name. + +The namespace is also accepted on the version (`picolibc-riscv = "xim:1.8.12"`), +because that is what the materialised `.xlings.json` carries — a key there is an +xvm target and the scope qualifies the version. Two vocabularies, one entry. +Writing it on both halves with different values is an error, and so is naming +one package twice under two spellings. Platform keys are xlings' own — `linux`, `macosx`, `windows` — plus `default`. `macos` and `macosx` are the same platform written in two vocabularies (mcpp's diff --git a/docs/13-baremetal.md b/docs/13-baremetal.md index b20062b4..cdb752c2 100644 --- a/docs/13-baremetal.md +++ b/docs/13-baremetal.md @@ -671,7 +671,7 @@ The package's manifest declares the emulator and nothing else: ```toml [xlings.workspace] -qemu-riscv = "xim:9.2.4-1" +"xim:qemu-riscv" = "9.2.4-1" ``` Linking `clang_rt.builtins` is not optional on this board. picolibc formats diff --git a/docs/zh/05-mcpp-toml.md b/docs/zh/05-mcpp-toml.md index ec33db69..afd7aa45 100644 --- a/docs/zh/05-mcpp-toml.md +++ b/docs/zh/05-mcpp-toml.md @@ -1595,11 +1595,10 @@ platforms = ["linux", "macos", "windows"] ```toml [xlings.workspace] # 这个工程的环境里有什么 -cmake = "3.28" -picolibc-riscv = "xim:1.8.12" # 命名空间写在版本上 -"xim:qemu-user-aarch64" = "7.2.0" # 或写在键上 —— 必须带引号 -code = "" # 存在即可,版本不限 -llvm = { macosx = "20", default = "22" } +cmake = "3.28" +"xim:picolibc-riscv" = "1.8.12" # 带命名空间的包 —— 必须带引号 +code = "" # 存在即可,版本不限 +llvm = { macosx = "20", default = "22" } ``` ```toml @@ -1622,12 +1621,16 @@ mcpp 既供给它——机器上没有就装,有就映射——也把它物化 | `cmake = "3.28"` | 该版本 | | `llvm = "22"` | 已装的最高 `22.*`;版本前缀会被解析 | | `code = ""` | 存在即可,版本不限 | -| `picolibc-riscv = "xim:1.8.12"` | 来自 `xim` 索引 | -| `"xim:picolibc-riscv" = "1.8.12"` | 同一条,命名空间写在键上 | +| `"xim:picolibc-riscv" = "1.8.12"` | 来自 `xim` 索引的包 | | `llvm = { macosx = "20", default = "22" }` | 按宿主平台 | -命名空间写在哪一半都可以。写在键上**必须带引号**,因为 TOML 的裸键不能含冒号。 -两半都写且不一致是错误;同一个包用两种拼法出现两次也是错误。 +**带命名空间的包写成 `"<命名空间>:<名字>" = "<版本>"`,引号必需** —— TOML 的裸键 +不能含冒号。这是**推荐形态,也是所有官方包使用的形态**:一条条目先点名一个包, +再说用它的哪个版本,所以命名空间属于名字。 + +命名空间写在版本上(`picolibc-riscv = "xim:1.8.12"`)同样接受,因为物化出来的 +`.xlings.json` 里正是那种形态 —— 那里的键是 xvm target,scope 限定的是版本。 +两套词汇,同一条条目。两半都写且不一致是错误;同一个包用两种拼法出现两次也是错误。 平台键是 xlings 自己的 —— `linux`、`macosx`、`windows`,外加 `default`。`macos` 与 `macosx` 是同一个平台的两套词汇(mcpp 的三元组说前者,描述符与 xlings 的项目 diff --git a/docs/zh/13-baremetal.md b/docs/zh/13-baremetal.md index 4294bab3..214084ac 100644 --- a/docs/zh/13-baremetal.md +++ b/docs/zh/13-baremetal.md @@ -603,7 +603,7 @@ int main() { ```toml [xlings.workspace] -qemu-riscv = "xim:9.2.4-1" +"xim:qemu-riscv" = "9.2.4-1" ``` 在这块板子上链接 `clang_rt.builtins` 不是可选项。picolibc 通过 ryu 格式化浮点值, diff --git a/examples/07-project-subos/README.md b/examples/07-project-subos/README.md index ae075367..36aeb8bd 100644 --- a/examples/07-project-subos/README.md +++ b/examples/07-project-subos/README.md @@ -19,7 +19,7 @@ warning: project-subos: this project's subos is populated subos = "default" [xlings.workspace] -qemu-riscv = "xim:9.2.4-1" +"xim:qemu-riscv" = "9.2.4-1" ``` `subos` names the environment this project builds in. mcpp already used that diff --git a/examples/07-project-subos/mcpp.toml b/examples/07-project-subos/mcpp.toml index 5b0953c3..91a1a38f 100644 --- a/examples/07-project-subos/mcpp.toml +++ b/examples/07-project-subos/mcpp.toml @@ -27,4 +27,4 @@ subos = "default" # project uses it at. mcpp provisions it and pins it, which is why the emulator # below is both installed on the first build and the one the project resolves. [xlings.workspace] -qemu-riscv = "xim:9.2.4-1" +"xim:qemu-riscv" = "9.2.4-1" diff --git a/mcpp.toml b/mcpp.toml index 36d9df6b..c38496d9 100644 --- a/mcpp.toml +++ b/mcpp.toml @@ -1,6 +1,6 @@ [package] name = "mcpp" -version = "2026.9.3.1" +version = "2026.9.3.2" description = "Modern C++ build & package management tool" license = "Apache-2.0" authors = ["mcpp-community"] diff --git a/modules/manifest/src/toml.cppm b/modules/manifest/src/toml.cppm index 8fe8053f..465945a3 100644 --- a/modules/manifest/src/toml.cppm +++ b/modules/manifest/src/toml.cppm @@ -212,6 +212,20 @@ struct XlingsEntry { if (version.empty()) return {}; return ns.empty() ? version : ns + ":" + version; } + // The RECOMMENDED authored spelling, which is not the same thing as the + // materialised one. A manifest names a package and then says which version + // of it, so the namespace belongs to the package and rides the key: + // + // "xim:qemu-riscv" = "9.2.4-1" + // + // The other position is accepted and is what the file itself carries, + // because a `.xlings.json` key is an xvm target and the scope there + // qualifies the version. Two vocabularies, one entry; mcpp suggests the + // one an author writes. + std::string authored_line() const { + auto key = ns.empty() ? target : std::format("\"{}:{}\"", ns, target); + return std::format("{} = \"{}\"", key, version); + } }; // The inverse: `[:][@]` back into its parts. Used by the @@ -1561,8 +1575,7 @@ std::expected parse_string(std::string_view content, // The same statement in both tables. Not an error and not two // entries: appending it again would ask xlings to install one // package twice, so only the advisory below is produced. - replacement += std::format("\n {} = \"{}\"", - entry.target, entry.pin()); + replacement += "\n " + entry.authored_line(); continue; } else if (pinned != m.xlings.workspace.end()) { auto say = [](const std::string& p) { @@ -1575,9 +1588,8 @@ std::expected parse_string(std::string_view content, entry.target, say(entry.pin()), say(pinned->second)))); } m.xlings.deps.push_back(**r); - // Show the author the line to write, not merely that one exists. - replacement += std::format("\n {} = \"{}\"", - entry.target, entry.pin()); + // Show the author the line to write, in the recommended spelling. + replacement += "\n " + entry.authored_line(); } if (!replacement.empty()) m.schemaWarnings.push_back(std::format( diff --git a/modules/versioning/src/version.cppm b/modules/versioning/src/version.cppm index 3f3f7853..de82c29a 100644 --- a/modules/versioning/src/version.cppm +++ b/modules/versioning/src/version.cppm @@ -31,6 +31,6 @@ import std; export namespace mcpp { -inline constexpr std::string_view MCPP_VERSION = "2026.9.3.1"; +inline constexpr std::string_view MCPP_VERSION = "2026.9.3.2"; } // namespace mcpp diff --git a/tests/e2e/331_xlings_workspace_one_table.sh b/tests/e2e/331_xlings_workspace_one_table.sh index 0c4e10b9..4f807ada 100755 --- a/tests/e2e/331_xlings_workspace_one_table.sh +++ b/tests/e2e/331_xlings_workspace_one_table.sh @@ -62,8 +62,10 @@ out=$(declare_and_build '[xlings] deps = ["xim:mcpp-e2e-absent@1.0"]') grep -q "xim:mcpp-e2e-absent@1.0" <<<"$out" || fail "deps entry not provisioned: $out" grep -q "\[xlings.workspace\]" <<<"$out" || fail "no advisory naming the new table: $out" -grep -q 'mcpp-e2e-absent = "xim:1.0"' <<<"$out" \ - || fail "the advisory does not show the line to write: $out" +# The recommended spelling, which is the namespace on the KEY: an author names +# a package and then says which version of it. +grep -q '"xim:mcpp-e2e-absent" = "1.0"' <<<"$out" \ + || fail "the advisory does not show the recommended line to write: $out" # ── 5. one package in both tables, two versions, is refused ─────────────── out=$(declare_and_build '[xlings] diff --git a/tests/unit/test_manifest.cpp b/tests/unit/test_manifest.cpp index f367db3a..2a45bb0f 100644 --- a/tests/unit/test_manifest.cpp +++ b/tests/unit/test_manifest.cpp @@ -4687,8 +4687,10 @@ deps = ["xim:qemu-riscv@9.2.4-1"] ASSERT_EQ(m->schemaWarnings.size(), 1u); EXPECT_NE(m->schemaWarnings[0].find("[xlings.workspace]"), std::string::npos) << m->schemaWarnings[0]; - // The message shows the line to write, not merely that a line exists. - EXPECT_NE(m->schemaWarnings[0].find("qemu-riscv = \"xim:9.2.4-1\""), + // The message shows the line to write, in the RECOMMENDED spelling: the + // namespace on the key, which is what an author writes and what every + // official package uses. + EXPECT_NE(m->schemaWarnings[0].find("\"xim:qemu-riscv\" = \"9.2.4-1\""), std::string::npos) << m->schemaWarnings[0]; }