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
456 changes: 456 additions & 0 deletions .agents/docs/2026-07-15-toolchain-target-naming-unification-design.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion .github/workflows/ci-linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ jobs:
- name: "Toolchain: musl-gcc — build mcpp (--target)"
run: |
"$MCPP" clean
"$MCPP" build --target x86_64-linux-musl 2>&1 | tee build.log; grep -q "Resolved gcc@16.1.0-musl" build.log
"$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

- name: "Toolchain: LLVM — build mcpp"
run: |
Expand Down
47 changes: 47 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,53 @@
> 本文件追踪 `mcpp-community/mcpp` 公开仓的版本演进。
> 格式参考 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/)。

## [0.0.93] — 2026-07-15

### 变更(命名统一,全部旧拼写永久兼容)

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

## [0.0.92] — 2026-07-15

### 新增
Expand Down
47 changes: 32 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -231,22 +231,39 @@ import mcpplibs.cmdline;

## Platform Support

| OS / arch | GCC (glibc) | GCC (musl) | Clang / LLVM | MSVC |
|------------------|:-----------:|:----------:|:------------:|:----:|
| Linux x86_64 | ✅ | ✅ *default* | ✅ | — |
| Linux aarch64 | 🔄 | ✅ *default* | 🔄 | — |
| macOS arm64 | — | — | ✅ *default* | — |
| macOS x86_64 | — | — | 🔄 | — |
| Windows x86_64 | — | — | ✅ ¹ *default* | 🔄 |

✅ supported | 🔄 planned

> *default*: the default toolchain on Linux is musl-gcc; release binaries are fully static musl builds.
> The default toolchain on macOS ARM64 / Windows x86_64 is LLVM/Clang.
mcpp's identity model has two orthogonal axes: a **toolchain** is
`family@version` (family ∈ gcc | llvm | msvc), a **target** is a triple
`arch-os[-env]`. Cross-compiling is just `mcpp build --target <triple>` —
the right toolchain payload is resolved and installed automatically.
`mcpp toolchain list` shows live status on your machine.

**Hosts** (where mcpp itself runs): Linux x86_64 / aarch64, macOS arm64, Windows x86_64.

**Targets** (what `--target` accepts; this table mirrors the in-code vocabulary):

| Target | Convention toolchain | Status |
|---|---|:---:|
| `x86_64-linux-gnu` | gcc *(Linux default)* or llvm | ✅ |
| `x86_64-linux-musl` | gcc 16, fully static | ✅ |
| `aarch64-linux-musl` | gcc 16, fully static — cross from x86_64 (qemu-verified) or native | ✅ |
| `x86_64-windows-gnu` | gcc 16 MinGW-w64 — native on Windows, cross from Linux (wine-verified) | ✅ |
| `x86_64-windows-msvc` | `msvc@system` (detected VS/BuildTools) or llvm ¹ *(Windows default)* | ✅ |
| `aarch64-macos` | llvm *(macOS default)* | ✅ |
| `riscv64-linux-musl` | — | 🔄 |
| `aarch64-linux-gnu` | — | 🔄 |
| `x86_64-macos` | — | 🔄 |

✅ verified — CI builds **and executes** the artifact end-to-end (qemu/wine included) | 🔄 planned

> Release binaries for Linux are fully static musl builds (`x86_64-linux-musl`).
> Legacy spellings — `x86_64-w64-mingw32`, `gcc@16.1.0-musl`, `mingw-cross@…`,
> `musl-gcc@…` — stay permanently accepted as aliases and normalize to the
> canonical forms above.
>
> ¹ On Windows, Clang/LLVM currently requires an existing **MSVC BuildTools or Visual Studio** installation
> (providing the UCRT, Windows SDK, and MSVC STL). A zero-MSVC `llvm-mingw` route is planned
> ([discussion](https://github.com/mcpp-community/mcpp/issues)).
> ¹ On Windows, llvm requires an existing **MSVC BuildTools or Visual Studio**
> (UCRT, Windows SDK, MSVC STL). The MinGW route (`--target x86_64-windows-gnu`,
> or `mcpp toolchain default gcc@16 --target x86_64-windows-gnu`) needs no
> Visual Studio at all.

## Documentation

Expand Down
43 changes: 28 additions & 15 deletions README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -231,22 +231,35 @@ import mcpplibs.cmdline;

## 平台支持

| OS / arch | GCC (glibc) | GCC (musl) | Clang / LLVM | MSVC |
|------------------|:-----------:|:----------:|:------------:|:----:|
| Linux x86_64 | ✅ | ✅ *默认* | ✅ | — |
| Linux aarch64 | 🔄 | ✅ *默认* | 🔄 | — |
| macOS arm64 | — | — | ✅ *默认* | — |
| macOS x86_64 | — | — | 🔄 | — |
| Windows x86_64 | — | — | ✅ ¹ *默认* | 🔄 |

✅ 已支持 | 🔄 计划中

> *默认*:Linux 默认工具链为 musl-gcc,release 二进制走 musl 全静态;
> macOS ARM64 / Windows x86_64 默认工具链均为 LLVM/Clang。
mcpp 的身份模型是两条正交轴:**工具链** = `family@version`(family ∈ gcc | llvm | msvc),
**目标** = 三段 triple `arch-os[-env]`。交叉编译只需 `mcpp build --target <triple>`——
对应的工具链包会自动解析并安装。`mcpp toolchain list` 查看本机实时状态。

**宿主**(mcpp 本身运行在哪):Linux x86_64 / aarch64、macOS arm64、Windows x86_64。

**目标**(`--target` 接受什么;本表与代码内词汇表同源):

| Target | 约定工具链 | 状态 |
|---|---|:---:|
| `x86_64-linux-gnu` | gcc(*Linux 默认*)或 llvm | ✅ |
| `x86_64-linux-musl` | gcc 16,全静态 | ✅ |
| `aarch64-linux-musl` | gcc 16,全静态——x86_64 交叉(qemu 实测)或原生 | ✅ |
| `x86_64-windows-gnu` | gcc 16 MinGW-w64——Windows 原生,Linux 交叉(wine 实测) | ✅ |
| `x86_64-windows-msvc` | `msvc@system`(探测 VS/BuildTools)或 llvm ¹(*Windows 默认*) | ✅ |
| `aarch64-macos` | llvm(*macOS 默认*) | ✅ |
| `riscv64-linux-musl` | — | 🔄 |
| `aarch64-linux-gnu` | — | 🔄 |
| `x86_64-macos` | — | 🔄 |

✅ 已验证——CI 端到端构建**并真实执行**产物(含 qemu/wine)| 🔄 计划中

> Linux release 二进制为 musl 全静态构建(`x86_64-linux-musl`)。
> 旧拼写——`x86_64-w64-mingw32`、`gcc@16.1.0-musl`、`mingw-cross@…`、`musl-gcc@…`——
> 作为别名**永久接受**,归一到上表的 canonical 形式。
>
> ¹ Windows 上 Clang/LLVM 当前依赖系统已安装 **MSVC BuildTools 或 Visual Studio**
> (提供 UCRT、Windows SDK、MSVC STL)。零-MSVC 依赖的 `llvm-mingw` 路线在规划中
> ([讨论](https://github.com/mcpp-community/mcpp/issues))
> ¹ Windows 上 llvm 依赖已安装的 **MSVC BuildTools 或 Visual Studio**(UCRT、Windows
> SDK、MSVC STL)。MinGW 路线(`--target x86_64-windows-gnu`,或
> `mcpp toolchain default gcc@16 --target x86_64-windows-gnu`)完全不需要 Visual Studio

## 文档

Expand Down
136 changes: 104 additions & 32 deletions docs/03-toolchains.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,45 @@ Downloading xim:musl-gcc@15.1.0 [====> ] 312 MB / 808 MB 3.7 MB/s
Default set to gcc@15.1.0-musl
```

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

Subsequent builds do not trigger this process again.

> [!TIP]
> 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.

## The Identity Model: Toolchain × Target

Two orthogonal axes name everything:

- **toolchain** = `family@version`, family ∈ `gcc | llvm | msvc` — *who compiles*
- **target** = a triple `arch-os[-env]` (e.g. `x86_64-linux-musl`,
`x86_64-windows-gnu`, `aarch64-macos`) — *what it produces for*

Variants live in the target's `env` segment (`gnu | musl | msvc`), never in
the toolchain name. "Cross" is not a name either — it's just the relation
`host ≠ target`, and the same command works for both. Legacy spellings
(`musl-gcc`, `gcc@15.1.0-musl`, `mingw`, `mingw-cross`, `clang`,
`x86_64-w64-mingw32`) are **permanently accepted aliases** that normalize to
this model with a one-line `note:` hint.

## Manual Installation

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

Explicit installation is mostly for CI cache warm-up and offline prep —
`mcpp build --target <triple>` auto-installs whatever the target needs.

Version numbers support partial matching:

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

## Switching the Default Toolchain

The default is a *pair* — toolchain axis + target axis (target omitted = host):

```bash
mcpp toolchain default gcc@16.1.0
mcpp toolchain default gcc 15 # with a partial version, picks the highest installed match
mcpp toolchain default gcc 15 # partial version → highest installed match
mcpp toolchain default gcc@16 --target x86_64-linux-musl # "default to fully-static musl"
```

The pair persists as `[toolchain] default = "gcc@16.1.0"` +
`default_target = "x86_64-linux-musl"` in `~/.mcpp/config.toml`. (Older
configs with combined spellings like `default = "gcc@15.1.0-musl"` keep
working unchanged.)

## Inspecting Toolchain Status

```bash
mcpp toolchain list
```

The output looks like this:
The output has two blocks — one per axis:

```
Installed:
TOOLCHAIN BINARY
gcc 15.1.0-musl @mcpp/registry/data/xpkgs/xim-x-musl-gcc/15.1.0/bin/x86_64-linux-musl-g++
* gcc 16.1.0 @mcpp/registry/data/xpkgs/xim-x-gcc/16.1.0/bin/g++

Available (run `mcpp toolchain install <compiler> <version>`):
TOOLCHAIN
gcc 13.3.0
gcc 11.5.0
...
Toolchains:
* gcc 16.1.0 (default)
gcc 15.1.0
llvm 22.1.8

Targets:
TARGET NOTE TOOLCHAIN STATUS
x86_64-linux-gnu host gcc 16.1.0 installed
* x86_64-linux-musl static gcc 16.1.0 installed
x86_64-windows-gnu PE, static, cross gcc 16.1.0 installed
aarch64-linux-musl static, cross gcc 16.1.0 available
riscv64-linux-musl static, cross — planned

Available toolchains (run `mcpp toolchain install <family> <version>`):
gcc 15.1.0 / 13.3.0 / 11.5.0 / 9.4.0
llvm 20.1.7
```

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

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

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

```bash
mcpp toolchain install mingw 16.1.0
mcpp toolchain default mingw@16.1.0
mcpp build --target x86_64-windows-gnu # from Windows OR Linux
mcpp toolchain default gcc@16 --target x86_64-windows-gnu
# legacy spellings still accepted: mingw@16.1.0, mingw-cross@16.1.0,
# --target x86_64-w64-mingw32
```

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

In a manifest:

```toml
[toolchain]
windows = "mingw@16.1.0"
windows = "gcc@16" # gcc family on Windows = MinGW-w64
# legacy value "mingw@16.1.0" keeps working
```

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

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

## Cross-Toolchain Builds
## Targets & Cross Builds

```bash
mcpp build --target x86_64-linux-musl
mcpp build --target x86_64-linux-musl # fully static ELF
mcpp build --target aarch64-linux-musl # cross-arch (aarch64 on x86_64)
mcpp build --target x86_64-windows-gnu # Windows PE from Linux
```

`--target` is validated against the known-target vocabulary (see the README
platform table, which mirrors it): a typo is a **hard error with a
suggestion** (`did you mean 'x86_64-linux-musl'?`) — never a silent host
build. Custom triples outside the vocabulary are allowed when an explicit
`[target.<triple>]` section declares them in `mcpp.toml`.

Each known target carries a convention: its pinned toolchain (installed on
demand) and its default linkage (`*-linux-musl` and `x86_64-windows-gnu`
default to static). An explicit `[target.<triple>]` section overrides both:

```toml
[target.x86_64-linux-musl]
toolchain = "gcc@16.1.0"
linkage = "static"
```

A project can set its *default* build target — this is where "this project
ships fully-static" belongs (static output is a product property, not a
compiler-family property):

```toml
[build]
target = "x86_64-linux-musl" # ≙ cargo's build.target
```

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/).
Combined with `mcpp pack --mode static` this produces a fully static release
package; for a complete example, see
[`examples/03-pack-static`](../examples/03-pack-static/).

## Uninstalling

Expand Down
2 changes: 2 additions & 0 deletions docs/05-mcpp-toml.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,8 @@ cflags = ["-DFOO=1"] # Extra C compile flags
cxxflags = ["-DBAR=2"] # Extra C++ compile flags (do not put -std=... here)
ldflags = ["-lfoo"] # Extra link flags
static_stdlib = true # Statically link libstdc++ (default true)
target = "x86_64-linux-musl" # Default build target when no --target is passed
# (≙ cargo build.target; e.g. "ship fully-static")
macos_deployment_target = "14.0" # Minimum supported OS version for macOS artifacts (macOS only)
```

Expand Down
Loading
Loading