Skip to content

Commit 6d8083a

Browse files
authored
feat(toolchain): toolchain × target 命名统一 — 二轴身份模型 (0.0.93) (#217)
toolchain = family@version (gcc|llvm|msvc) × target = arch-os[-env] triple; musl/mingw/cross 不再是工具链名字,全部旧拼写永久兼容(compat.cppm); canonical x86_64-windows-gnu;--target 封闭词汇表校验 + did-you-mean; CLI --target 选项 + [build] target;list 两轴重排;README 平台表从词汇表重画。 设计:.agents/docs/2026-07-15-toolchain-target-naming-unification-design.md
1 parent b17245f commit 6d8083a

34 files changed

Lines changed: 2488 additions & 590 deletions

.agents/docs/2026-07-15-toolchain-target-naming-unification-design.md

Lines changed: 456 additions & 0 deletions
Large diffs are not rendered by default.

.github/workflows/ci-linux.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ jobs:
138138
- name: "Toolchain: musl-gcc — build mcpp (--target)"
139139
run: |
140140
"$MCPP" clean
141-
"$MCPP" build --target x86_64-linux-musl 2>&1 | tee build.log; grep -q "Resolved gcc@16.1.0-musl" build.log
141+
"$MCPP" build --target x86_64-linux-musl 2>&1 | tee build.log; grep -q "Resolved gcc@16.1.0 → x86_64-linux-musl" build.log
142142
143143
- name: "Toolchain: LLVM — build mcpp"
144144
run: |

CHANGELOG.md

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,53 @@
33
> 本文件追踪 `mcpp-community/mcpp` 公开仓的版本演进。
44
> 格式参考 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/)
55
6+
## [0.0.93] — 2026-07-15
7+
8+
### 变更(命名统一,全部旧拼写永久兼容)
9+
10+
- **工具链 × 目标 命名统一 —— 二轴身份模型**。toolchain = `family@version`
11+
(family 只剩 **gcc | llvm | msvc**),target = mcpp 自有三段 triple
12+
`arch-os[-env]`(Zig 式砍 vendor)。变体(gnu/musl/msvc)进 triple env 段,
13+
**"cross"/"musl"/"mingw" 不再是工具链名字**——`mingw-cross 16.1.0` 的本体是
14+
`gcc@16.1.0 → x86_64-windows-gnu`,交叉只是 host≠target 的关系。业界对照
15+
(rustup 零 "cross" 命名/Zig 三段 triple/musl.cc 分发层先例)与决策记录见
16+
`.agents/docs/2026-07-15-toolchain-target-naming-unification-design.md`
17+
- **canonical triple**:`x86_64-windows-gnu` 为正典(D1);GNU 拼写
18+
`x86_64-w64-mingw32` 及 4 段 Rust 拼写为**永久别名**,归一后进同一
19+
`target/<canonical>/` 目录(同一构建缓存)。macOS 产物目录随 canonical 变为
20+
`aarch64-macos`
21+
- **`--target` 封闭词汇表校验**:打错字**硬错 + did-you-mean**
22+
(`did you mean 'x86_64-linux-musl'?`),不再静默 fall through 编成宿主产物
23+
(最坏失败模式根治);自定义 triple 走显式 `[target.X]` 节逃生舱;planned
24+
档位(riscv64 等)报「registered but not yet supported」。两条硬编码约定
25+
(`*-musl``x86_64-w64-mingw32`)改为词汇表数据行(pin + 默认 static)。
26+
- **单一 triple 解析器 `triple.cppm`**:cfgpred/abi/model 谓词/registry 四处
27+
平行解析收敛;abi 的 os 维 `darwin``macos`(与 cfg 词汇分叉消灭,
28+
`darwin`/`arm64` 作为约束别名接受)。
29+
- **`compat.cppm` 兼容层**:唯一知道旧拼写的文件(musl-gcc/gcc@V-musl/
30+
<triple>-gcc/mingw/mingw-cross/clang),归一 + 单行 `note:` 提示;xim 分发包名
31+
(`mingw-cross-gcc` 等)不动——"cross" 在分发层合法(musl.cc/Debian 先例)。
32+
- **CLI 单名词 + `--target` 选项**(D4,不设 `mcpp target` 子命令):
33+
`toolchain install [gcc 16] --target <triple>`(family 可省→约定 pin)、
34+
`toolchain default gcc@16 --target <triple>`(默认变 **pair**,持久化
35+
`default` + `default_target` 两键)、`toolchain remove … --target <triple>`;
36+
主路径仍是 `mcpp build --target <triple>` 自动装链(零仪式)。
37+
- **`[build] target = "<triple>"`** 新 manifest 键(≙ cargo `build.target`):
38+
「默认全静态 musl」的正确归宿(产物属性,非编译器家族属性);优先级
39+
`--target` flag > `[build] target` > 全局 `default_target` > host。
40+
- **`toolchain list` 两轴重排**:Toolchains 块(family@version)+ Targets 块
41+
(target × 状态 installed/available/**planned**,planned 行使词汇表用户可见);
42+
修版本字典序排序 bug(9.4.0 不再排在 15.1.0 前);`gcc X-musl` 行不再被
43+
`llvm` 劈开。README 平台表从词汇表重画(target × tier 维度,补 MSVC=✅ 与
44+
windows-gnu 行——旧表 MSVC 仍标 planned 是错的)。
45+
- 修 Windows host 上 `mingw` 的门:Linux`toolchain install mingw` 现在
46+
合法(= 装交叉 payload,同一身份 host 分流);`mcpp run` 位置参数 help 改为
47+
「Binary name」消除与 `--target` 的语义撞名。
48+
- 验证:单测 35(新增 triple/compat 套件);e2e 新增 103(typo/planned/逃生舱/
49+
`[build] target`/别名同目录)、102 双拼写断言;本机实测双拼写同 Resolved
50+
行+同缓存(alias 二跑 0.07s 全命中)、PE wine 真跑、musl 静态链、typo
51+
did-you-mean。
52+
653
## [0.0.92] — 2026-07-15
754

855
### 新增

README.md

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -231,22 +231,39 @@ import mcpplibs.cmdline;
231231

232232
## Platform Support
233233

234-
| OS / arch | GCC (glibc) | GCC (musl) | Clang / LLVM | MSVC |
235-
|------------------|:-----------:|:----------:|:------------:|:----:|
236-
| Linux x86_64 ||*default* |||
237-
| Linux aarch64 | 🔄 |*default* | 🔄 ||
238-
| macOS arm64 |||*default* ||
239-
| macOS x86_64 ||| 🔄 ||
240-
| Windows x86_64 ||| ✅ ¹ *default* | 🔄 |
241-
242-
✅ supported | 🔄 planned
243-
244-
> *default*: the default toolchain on Linux is musl-gcc; release binaries are fully static musl builds.
245-
> The default toolchain on macOS ARM64 / Windows x86_64 is LLVM/Clang.
234+
mcpp's identity model has two orthogonal axes: a **toolchain** is
235+
`family@version` (family ∈ gcc | llvm | msvc), a **target** is a triple
236+
`arch-os[-env]`. Cross-compiling is just `mcpp build --target <triple>`
237+
the right toolchain payload is resolved and installed automatically.
238+
`mcpp toolchain list` shows live status on your machine.
239+
240+
**Hosts** (where mcpp itself runs): Linux x86_64 / aarch64, macOS arm64, Windows x86_64.
241+
242+
**Targets** (what `--target` accepts; this table mirrors the in-code vocabulary):
243+
244+
| Target | Convention toolchain | Status |
245+
|---|---|:---:|
246+
| `x86_64-linux-gnu` | gcc *(Linux default)* or llvm ||
247+
| `x86_64-linux-musl` | gcc 16, fully static ||
248+
| `aarch64-linux-musl` | gcc 16, fully static — cross from x86_64 (qemu-verified) or native ||
249+
| `x86_64-windows-gnu` | gcc 16 MinGW-w64 — native on Windows, cross from Linux (wine-verified) ||
250+
| `x86_64-windows-msvc` | `msvc@system` (detected VS/BuildTools) or llvm ¹ *(Windows default)* ||
251+
| `aarch64-macos` | llvm *(macOS default)* ||
252+
| `riscv64-linux-musl` || 🔄 |
253+
| `aarch64-linux-gnu` || 🔄 |
254+
| `x86_64-macos` || 🔄 |
255+
256+
✅ verified — CI builds **and executes** the artifact end-to-end (qemu/wine included) | 🔄 planned
257+
258+
> Release binaries for Linux are fully static musl builds (`x86_64-linux-musl`).
259+
> Legacy spellings — `x86_64-w64-mingw32`, `gcc@16.1.0-musl`, `mingw-cross@…`,
260+
> `musl-gcc@…` — stay permanently accepted as aliases and normalize to the
261+
> canonical forms above.
246262
>
247-
> ¹ On Windows, Clang/LLVM currently requires an existing **MSVC BuildTools or Visual Studio** installation
248-
> (providing the UCRT, Windows SDK, and MSVC STL). A zero-MSVC `llvm-mingw` route is planned
249-
> ([discussion](https://github.com/mcpp-community/mcpp/issues)).
263+
> ¹ On Windows, llvm requires an existing **MSVC BuildTools or Visual Studio**
264+
> (UCRT, Windows SDK, MSVC STL). The MinGW route (`--target x86_64-windows-gnu`,
265+
> or `mcpp toolchain default gcc@16 --target x86_64-windows-gnu`) needs no
266+
> Visual Studio at all.
250267
251268
## Documentation
252269

README.zh-CN.md

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -231,22 +231,35 @@ import mcpplibs.cmdline;
231231

232232
## 平台支持
233233

234-
| OS / arch | GCC (glibc) | GCC (musl) | Clang / LLVM | MSVC |
235-
|------------------|:-----------:|:----------:|:------------:|:----:|
236-
| Linux x86_64 ||*默认* |||
237-
| Linux aarch64 | 🔄 |*默认* | 🔄 ||
238-
| macOS arm64 |||*默认* ||
239-
| macOS x86_64 ||| 🔄 ||
240-
| Windows x86_64 ||| ✅ ¹ *默认* | 🔄 |
241-
242-
✅ 已支持 | 🔄 计划中
243-
244-
> *默认*:Linux 默认工具链为 musl-gcc,release 二进制走 musl 全静态;
245-
> macOS ARM64 / Windows x86_64 默认工具链均为 LLVM/Clang。
234+
mcpp 的身份模型是两条正交轴:**工具链** = `family@version`(family ∈ gcc | llvm | msvc),
235+
**目标** = 三段 triple `arch-os[-env]`。交叉编译只需 `mcpp build --target <triple>`——
236+
对应的工具链包会自动解析并安装。`mcpp toolchain list` 查看本机实时状态。
237+
238+
**宿主**(mcpp 本身运行在哪):Linux x86_64 / aarch64、macOS arm64、Windows x86_64。
239+
240+
**目标**(`--target` 接受什么;本表与代码内词汇表同源):
241+
242+
| Target | 约定工具链 | 状态 |
243+
|---|---|:---:|
244+
| `x86_64-linux-gnu` | gcc(*Linux 默认*)或 llvm ||
245+
| `x86_64-linux-musl` | gcc 16,全静态 ||
246+
| `aarch64-linux-musl` | gcc 16,全静态——x86_64 交叉(qemu 实测)或原生 ||
247+
| `x86_64-windows-gnu` | gcc 16 MinGW-w64——Windows 原生,Linux 交叉(wine 实测) ||
248+
| `x86_64-windows-msvc` | `msvc@system`(探测 VS/BuildTools)或 llvm ¹(*Windows 默认*) ||
249+
| `aarch64-macos` | llvm(*macOS 默认*) ||
250+
| `riscv64-linux-musl` || 🔄 |
251+
| `aarch64-linux-gnu` || 🔄 |
252+
| `x86_64-macos` || 🔄 |
253+
254+
✅ 已验证——CI 端到端构建**并真实执行**产物(含 qemu/wine)| 🔄 计划中
255+
256+
> Linux release 二进制为 musl 全静态构建(`x86_64-linux-musl`)。
257+
> 旧拼写——`x86_64-w64-mingw32``gcc@16.1.0-musl``mingw-cross@…``musl-gcc@…`——
258+
> 作为别名**永久接受**,归一到上表的 canonical 形式。
246259
>
247-
> ¹ Windows 上 Clang/LLVM 当前依赖系统已安装 **MSVC BuildTools 或 Visual Studio**
248-
> (提供 UCRT、Windows SDK、MSVC STL)。零-MSVC 依赖的 `llvm-mingw` 路线在规划中
249-
> ([讨论](https://github.com/mcpp-community/mcpp/issues))
260+
> ¹ Windows 上 llvm 依赖已安装的 **MSVC BuildTools 或 Visual Studio**(UCRT、Windows
261+
> SDK、MSVC STL)。MinGW 路线(`--target x86_64-windows-gnu`,或
262+
> `mcpp toolchain default gcc@16 --target x86_64-windows-gnu`)完全不需要 Visual Studio
250263
251264
## 文档
252265

docs/03-toolchains.md

Lines changed: 104 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -16,22 +16,45 @@ Downloading xim:musl-gcc@15.1.0 [====> ] 312 MB / 808 MB 3.7 MB/s
1616
Default set to gcc@15.1.0-musl
1717
```
1818

19-
Linux defaults to `gcc@15.1.0-musl`; macOS defaults to `llvm@20.1.7`.
19+
The first-run default is host-aware: Linux x86_64 → `gcc@16.1.0` (glibc — the
20+
native ABI, so X11/GL/system libraries link out of the box); other Linux
21+
arches (aarch64, …) → `gcc@15.1.0-musl` (self-contained, fully static);
22+
macOS and Windows → `llvm@20.1.7`. Fully-static musl output stays one flag
23+
away on any Linux host: `mcpp build --target x86_64-linux-musl`.
2024

2125
Subsequent builds do not trigger this process again.
2226

2327
> [!TIP]
2428
> In CI or offline environments, you can disable automatic installation by setting `MCPP_NO_AUTO_INSTALL=1`. With this set, if no toolchain is installed, `mcpp build` fails immediately instead of making any network requests.
2529
30+
## The Identity Model: Toolchain × Target
31+
32+
Two orthogonal axes name everything:
33+
34+
- **toolchain** = `family@version`, family ∈ `gcc | llvm | msvc`*who compiles*
35+
- **target** = a triple `arch-os[-env]` (e.g. `x86_64-linux-musl`,
36+
`x86_64-windows-gnu`, `aarch64-macos`) — *what it produces for*
37+
38+
Variants live in the target's `env` segment (`gnu | musl | msvc`), never in
39+
the toolchain name. "Cross" is not a name either — it's just the relation
40+
`host ≠ target`, and the same command works for both. Legacy spellings
41+
(`musl-gcc`, `gcc@15.1.0-musl`, `mingw`, `mingw-cross`, `clang`,
42+
`x86_64-w64-mingw32`) are **permanently accepted aliases** that normalize to
43+
this model with a one-line `note:` hint.
44+
2645
## Manual Installation
2746

2847
```bash
29-
mcpp toolchain install gcc 16.1.0 # GNU libc, for the default dynamic-linking case
30-
mcpp toolchain install gcc 15.1.0-musl # musl libc, for fully static builds
31-
mcpp toolchain install musl-gcc 15.1.0 # equivalent to the line above
32-
mcpp toolchain install llvm 20.1.7 # LLVM/Clang, the default toolchain on macOS
48+
mcpp toolchain install gcc 16.1.0 # host target (GNU libc on Linux)
49+
mcpp toolchain install llvm 20.1.7 # LLVM/Clang, the default on macOS/Windows
50+
mcpp toolchain install gcc 16 --target x86_64-linux-musl # musl target payload
51+
mcpp toolchain install --target x86_64-windows-gnu # family omitted → the
52+
# target's convention pin (gcc@16.1.0)
3353
```
3454

55+
Explicit installation is mostly for CI cache warm-up and offline prep —
56+
`mcpp build --target <triple>` auto-installs whatever the target needs.
57+
3558
Version numbers support partial matching:
3659

3760
```bash
@@ -41,56 +64,76 @@ mcpp toolchain install gcc@16 # the @ form works too
4164

4265
## Switching the Default Toolchain
4366

67+
The default is a *pair* — toolchain axis + target axis (target omitted = host):
68+
4469
```bash
4570
mcpp toolchain default gcc@16.1.0
46-
mcpp toolchain default gcc 15 # with a partial version, picks the highest installed match
71+
mcpp toolchain default gcc 15 # partial version → highest installed match
72+
mcpp toolchain default gcc@16 --target x86_64-linux-musl # "default to fully-static musl"
4773
```
4874

75+
The pair persists as `[toolchain] default = "gcc@16.1.0"` +
76+
`default_target = "x86_64-linux-musl"` in `~/.mcpp/config.toml`. (Older
77+
configs with combined spellings like `default = "gcc@15.1.0-musl"` keep
78+
working unchanged.)
79+
4980
## Inspecting Toolchain Status
5081

5182
```bash
5283
mcpp toolchain list
5384
```
5485

55-
The output looks like this:
86+
The output has two blocks — one per axis:
5687

5788
```
58-
Installed:
59-
TOOLCHAIN BINARY
60-
gcc 15.1.0-musl @mcpp/registry/data/xpkgs/xim-x-musl-gcc/15.1.0/bin/x86_64-linux-musl-g++
61-
* gcc 16.1.0 @mcpp/registry/data/xpkgs/xim-x-gcc/16.1.0/bin/g++
62-
63-
Available (run `mcpp toolchain install <compiler> <version>`):
64-
TOOLCHAIN
65-
gcc 13.3.0
66-
gcc 11.5.0
67-
...
89+
Toolchains:
90+
* gcc 16.1.0 (default)
91+
gcc 15.1.0
92+
llvm 22.1.8
93+
94+
Targets:
95+
TARGET NOTE TOOLCHAIN STATUS
96+
x86_64-linux-gnu host gcc 16.1.0 installed
97+
* x86_64-linux-musl static gcc 16.1.0 installed
98+
x86_64-windows-gnu PE, static, cross gcc 16.1.0 installed
99+
aarch64-linux-musl static, cross gcc 16.1.0 available
100+
riscv64-linux-musl static, cross — planned
101+
102+
Available toolchains (run `mcpp toolchain install <family> <version>`):
103+
gcc 15.1.0 / 13.3.0 / 11.5.0 / 9.4.0
104+
llvm 20.1.7
68105
```
69106

70-
The entry marked with `*` is the current default toolchain. `@mcpp/...` is shorthand for `~/.mcpp/...`, used to keep the output narrower.
107+
`*` marks the default pair. The Targets block is the live view of the target
108+
vocabulary: `installed` payloads, `available` targets this host can install,
109+
and `planned` targets that are registered but not yet shipped.
71110

72-
## MinGW (Windows-native GCC, no Visual Studio required)
111+
## Windows PE via MinGW-w64 (`x86_64-windows-gnu`, no Visual Studio required)
73112

74-
On Windows, `mingw` installs a self-contained MinGW-w64 GCC (winlibs
75-
standalone build, UCRT runtime) into mcpp's sandbox — the same managed-xpkg
76-
model as `gcc`/`llvm`, no Visual Studio needed:
113+
"MinGW" in mcpp is a **target**, not a toolchain name: `x86_64-windows-gnu`
114+
— GCC producing Windows PE with the GNU CRT. The same identity works from
115+
both hosts; which self-contained payload serves it is resolved automatically
116+
(Windows host → winlibs UCRT build; Linux host → the from-source MSVCRT
117+
cross toolchain, wine-verified in CI):
77118

78119
```bash
79-
mcpp toolchain install mingw 16.1.0
80-
mcpp toolchain default mingw@16.1.0
120+
mcpp build --target x86_64-windows-gnu # from Windows OR Linux
121+
mcpp toolchain default gcc@16 --target x86_64-windows-gnu
122+
# legacy spellings still accepted: mingw@16.1.0, mingw-cross@16.1.0,
123+
# --target x86_64-w64-mingw32
81124
```
82125

83126
It uses the regular GCC module pipeline (`gcm.cache`, `import std` via
84-
libstdc++'s `bits/std.cc`). Produced binaries statically link libstdc++ and
85-
libgcc by default, so they run standalone — no `libstdc++-6.dll` needs to
86-
travel next to your exe (opt out with `[build] static_stdlib = false`).
87-
`[build] linkage = "static"` upgrades that to a fully static link.
127+
libstdc++'s `bits/std.cc`). The target's default linkage is **static**
128+
the produced `.exe` is fully self-contained (no `libstdc++-6.dll` to ship,
129+
runs directly under wine); `[build] linkage = "dynamic"` opts out.
88130

89131
In a manifest:
90132

91133
```toml
92134
[toolchain]
93-
windows = "mingw@16.1.0"
135+
windows = "gcc@16" # gcc family on Windows = MinGW-w64
136+
# legacy value "mingw@16.1.0" keeps working
94137
```
95138

96139
## MSVC (System Toolchain, Windows)
@@ -157,13 +200,42 @@ macos = "llvm@20"
157200

158201
A project-level declaration takes precedence over the global default configuration.
159202

160-
## Cross-Toolchain Builds
203+
## Targets & Cross Builds
161204

162205
```bash
163-
mcpp build --target x86_64-linux-musl
206+
mcpp build --target x86_64-linux-musl # fully static ELF
207+
mcpp build --target aarch64-linux-musl # cross-arch (aarch64 on x86_64)
208+
mcpp build --target x86_64-windows-gnu # Windows PE from Linux
209+
```
210+
211+
`--target` is validated against the known-target vocabulary (see the README
212+
platform table, which mirrors it): a typo is a **hard error with a
213+
suggestion** (`did you mean 'x86_64-linux-musl'?`) — never a silent host
214+
build. Custom triples outside the vocabulary are allowed when an explicit
215+
`[target.<triple>]` section declares them in `mcpp.toml`.
216+
217+
Each known target carries a convention: its pinned toolchain (installed on
218+
demand) and its default linkage (`*-linux-musl` and `x86_64-windows-gnu`
219+
default to static). An explicit `[target.<triple>]` section overrides both:
220+
221+
```toml
222+
[target.x86_64-linux-musl]
223+
toolchain = "gcc@16.1.0"
224+
linkage = "static"
225+
```
226+
227+
A project can set its *default* build target — this is where "this project
228+
ships fully-static" belongs (static output is a product property, not a
229+
compiler-family property):
230+
231+
```toml
232+
[build]
233+
target = "x86_64-linux-musl" # ≙ cargo's build.target
164234
```
165235

166-
mcpp reads the `[target.x86_64-linux-musl]` section in `mcpp.toml`, overriding the default toolchain and linkage settings. Combined with `mcpp pack --mode static`, this lets you produce a fully static release package; for a complete example, see [`examples/03-pack-static`](../examples/03-pack-static/).
236+
Combined with `mcpp pack --mode static` this produces a fully static release
237+
package; for a complete example, see
238+
[`examples/03-pack-static`](../examples/03-pack-static/).
167239

168240
## Uninstalling
169241

docs/05-mcpp-toml.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,8 @@ cflags = ["-DFOO=1"] # Extra C compile flags
141141
cxxflags = ["-DBAR=2"] # Extra C++ compile flags (do not put -std=... here)
142142
ldflags = ["-lfoo"] # Extra link flags
143143
static_stdlib = true # Statically link libstdc++ (default true)
144+
target = "x86_64-linux-musl" # Default build target when no --target is passed
145+
# (≙ cargo build.target; e.g. "ship fully-static")
144146
macos_deployment_target = "14.0" # Minimum supported OS version for macOS artifacts (macOS only)
145147
```
146148

0 commit comments

Comments
 (0)