Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
27 changes: 16 additions & 11 deletions docs/05-mcpp-toml.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 `"<namespace>:<name>" = "<version>"`, 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
Expand Down
2 changes: 1 addition & 1 deletion docs/13-baremetal.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
21 changes: 12 additions & 9 deletions docs/zh/05-mcpp-toml.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 的项目
Expand Down
2 changes: 1 addition & 1 deletion docs/zh/13-baremetal.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 格式化浮点值,
Expand Down
2 changes: 1 addition & 1 deletion examples/07-project-subos/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion examples/07-project-subos/mcpp.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
2 changes: 1 addition & 1 deletion mcpp.toml
Original file line number Diff line number Diff line change
@@ -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"]
Expand Down
22 changes: 17 additions & 5 deletions modules/manifest/src/toml.cppm
Original file line number Diff line number Diff line change
Expand Up @@ -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: `[<ns>:]<target>[@<version>]` back into its parts. Used by the
Expand Down Expand Up @@ -1561,8 +1575,7 @@ std::expected<Manifest, ManifestError> 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) {
Expand All @@ -1575,9 +1588,8 @@ std::expected<Manifest, ManifestError> 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(
Expand Down
2 changes: 1 addition & 1 deletion modules/versioning/src/version.cppm
Original file line number Diff line number Diff line change
Expand Up @@ -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
6 changes: 4 additions & 2 deletions tests/e2e/331_xlings_workspace_one_table.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
6 changes: 4 additions & 2 deletions tests/unit/test_manifest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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];
}

Expand Down
Loading