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

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion .agents/docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ superseded_by: 2026-09-07-....md # when status is superseded
---
```

325 records.
326 records.

## By subject

Expand All @@ -30,6 +30,7 @@ Records that declare one. Everything else is listed by date below.

### design

- [下一个版本的发布方案:标准库模块、原生 MSVC LTO 与导出发现、共享库的链接配置、Windows 参数引号(#768 后续、#770、#771)](2026-10-05-std-module-pair-msvc-lto-and-export-discovery-design.md) — active
- [`mcpp run` hands the terminal to the program, and the follow-ups of #761, #763 and #765 (#766)](2026-10-05-run-terminal-handoff-and-766-follow-ups-design.md) — landed
- [PR CI acceleration and the toolchain specification (#756, #757, #669)](2026-10-02-pr-ci-acceleration-and-the-toolchain-specification-design.md) — active
- [工具与工具链的来源:声明、编程决定、可观察](2026-10-01-tool-and-toolchain-sources-design.md) — landed
Expand Down Expand Up @@ -116,6 +117,7 @@ Records that declare one. Everything else is listed by date below.

### 2026-10

- [下一个版本的发布方案:标准库模块、原生 MSVC LTO 与导出发现、共享库的链接配置、Windows 参数引号(#768 后续、#770、#771)](2026-10-05-std-module-pair-msvc-lto-and-export-discovery-design.md) — active
- [`mcpp run` hands the terminal to the program, and the follow-ups of #761, #763 and #765 (#766)](2026-10-05-run-terminal-handoff-and-766-follow-ups-design.md) — landed
- [PR CI acceleration and the toolchain specification (#756, #757, #669)](2026-10-02-pr-ci-acceleration-and-the-toolchain-specification-design.md) — active
- [工具与工具链的来源:声明、编程决定、可观察](2026-10-01-tool-and-toolchain-sources-design.md) — landed
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,6 @@ examples/*/target/

# `mcpp test` writes a per-invocation scratch dir here.
.mcpp/

# Local review reports (not part of the design record).
/.agents/reviews/
73 changes: 73 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,79 @@
> Each `## [<version>]` section is that release's notes. Entries are written in English
> from 2026.9.28.3 on; earlier entries remain as written.

## [2026.10.5.2] - 2026-10-05

This release closes mcpp#771 and mcpp#770 and the follow-ups of mcpp#768: the
link line of a shared library that is not the root's, native MSVC LTO and its
meeting with export discovery, and `std.compat` on every Default row. It also
fixes the Windows quoting of an argument that ends in a backslash, and makes a
workspace's `[profile.*]` and its own package behave as members do. No default
toolchain changes. The design record is
`.agents/docs/2026-10-05-std-module-pair-msvc-lto-and-export-discovery-design.md`.

### Fixed

- **A shared library links with its own package's flags (#771).** A shared
library that is not the root's linked with the root's link line. In a
workspace a member's `build.mcpp` libraries did not reach the member's own
DLL (`LNK2019` on the symbol), and in every plan the root's private
`ldflags`, and an unrelated member's, reached a dependency's image. Such a
library now links with the graph's flags (the profile's `ldflags`, the words
`[target.<selector>.abi]` renders) and those of the packages its owner
reaches. E2E 884 reads the result from the produced images.
- **Arguments ending in a backslash on Windows.** The quoting of a Windows
command line escaped `"` but not the backslashes before it, so an argument
ending in `\` closed no quote and shifted every argument after it. In a
Visual Studio developer environment, whose `WindowsSdkDir` ends in `\`, the
LLVM row's `import std` failed in the std module precompile. The quoting
follows the argv rules of the Windows runtime, and `WindowsSdkDir` is read
without its trailing separator, so one SDK has one cache key inside and
outside a developer environment. E2E 888.
- **`import std.compat` on the GCC row.** libstdc++'s `bits/std.compat.cc` was
not built, and the first unit importing `std.compat` failed. It is built
beside `std` now, as SPEC-009 §6.2 requires of a Default row. E2E 886.
- **`/bigobj` objects take part in export discovery.** The reader of a DLL's
objects reads the `/bigobj` layout. A `/GL` object, which has no symbol table,
and an import object are reported as what they are; both were reported as
`/bigobj` before.
- **A workspace's `[profile.*]` reaches its members.** A virtual root's profiles
reached no member and were ignored without a diagnostic. Profiles are now
root-position keys, inherited by name, and a member's own table of a name
replaces the workspace's. In a workspace with its own `[package]`, the root
file's profile is the same for every selection, so `--workspace` plans one
graph and compiles a shared library once. E2E 885.
- **The unit tests of mcpp run in mcpp.exe's code page.**
`Glob.EscapedSpellingIsUtf8WhateverTheName` constructed a Windows path from
bytes that only a single-byte code page converts, and failed on a machine in
the Chinese region; it passed on CI, whose code page is 1252. The test is
corrected, and mcpp's tests run in UTF-8 as mcpp.exe does.

### Changed

- **`lto = true` on cl.exe.** It compiled nothing differently while the build
summary said `+ lto`. It now compiles with `/GL` and links and archives with
`/LTCG`. A DLL whose exports are discovered cannot hold `/GL` objects: when
`windows_auto_export` is omitted, the packages linked into it compile with
`/GL-` and the build reports this once (`+ lto (partial)`); a stated `true`,
and `/GL` written into those packages' flags, are refused with
`lto-export-discovery`.
- **The root package's `[build] ldflags` no longer reach a dependency's shared
library.** A dependency that needs a search path or a library states it in
its own `ldflags` or `build.mcpp`. When the root names one and the plan holds
a dependency's shared library, the build notes it under `link/root-flags`.
- **A workspace's own package receives `[workspace.package]` and
`[workspace.build]`** once, as every member does.
- **`std.compat` is built only when a unit imports it**, and an import of it
from a standard library that does not provide it is refused before any
compile, naming the library.
- **`mcpp pack` ships static libraries without LTO intermediate code**, which
only the compiler release that wrote it can read.

### Added

- **`[test] windows_code_page`** states the code page of every discovered test
program on Windows, with the values of the target key of the same name.

## [2026.10.5.1] - 2026-10-05

This release gives the program that `mcpp run` starts the terminal, and closes
Expand Down
42 changes: 38 additions & 4 deletions docs/04-mcpp-toml.md
Original file line number Diff line number Diff line change
Expand Up @@ -343,9 +343,24 @@ executables, ELF, Mach-O and MinGW.
MSVC-ABI target is planned, since `exports` narrows the discovered symbols; the
same manifest builds on ELF and Mach-O.

Discovery reads COFF objects directly and LLVM bitcode (FullLTO and ThinLTO,
alone or mixed with COFF objects) with the selected LLVM compiler and the
`llvm-nm` beside it.
Discovery reads COFF objects directly, including `/bigobj` objects
(2026.10.5.2+), and LLVM bitcode (FullLTO and ThinLTO, alone or mixed with COFF
objects) with the selected LLVM compiler and the `llvm-nm` beside it. An object
compiled by cl.exe with `/GL` holds no symbol table and is reported by name.

**With LTO on cl.exe (2026.10.5.2+).** `lto = true` compiles with `/GL`, which
leaves nothing to discover. The three ways of writing the key behave
differently there, because only an omitted key is mcpp's to decide:

| Written | Result under `lto = true` on cl.exe |
|---|---|
| omitted | the packages whose objects the DLL links (its own and the static libraries placed in it) compile with `/GL-`; the DLL still links with `/LTCG`; the build reports this once and its summary reads `+ lto (partial)` |
| `true` | refused when the target is planned (`lto-export-discovery`) |
| `false` | full `/GL` and `/LTCG`; the sources declare the exports with `__declspec(dllexport)` |

`/GL` written into the flags of a package whose objects such a DLL links is
refused in the same way, with or without `lto`. LLVM LTO on the MSVC ABI emits
bitcode, which discovery reads, and is not affected.

#### `windows_subsystem` and `windows_entry` — a Windows GUI executable (mcpp 2026.9.12.2+)

Expand Down Expand Up @@ -550,6 +565,18 @@ root, and a dependency's `ldflags` reach its consumer word by word. An element
escaped for ninja or the shell by hand (`\$ORIGIN`, `'$$ORIGIN'`) now reads as
written; the first plan names such an element under `build/flag-words`.

**Which link a package's `ldflags` reach (2026.10.5.2+).** The root package's
own programs and shared libraries link with its `ldflags` and those of every
package it reaches. A shared library that another package owns links with the
graph's flags (the profile's `ldflags` and the words `[target.<selector>.abi]`
renders for the link) and the `ldflags` of the packages its owner reaches,
`build.mcpp` output included. Before 2026.10.5.2 such a library linked with the
root's line, so the root's private flags and an unrelated workspace member's
reached it, and in a workspace a member's own `build.mcpp` libraries did not
(#771). A dependency that needs a search path or a library states it in its own
`ldflags` or `build.mcpp`; when the root names one and the plan holds a
dependency's shared library, the build notes this under `link/root-flags`.

`compile_commands.json` and `mcpp emit build-database` list the same words in
`arguments`, ready to execute without a shell.

Expand Down Expand Up @@ -1386,7 +1413,7 @@ where it would become a BMI path that nothing reports.
[profile.dist]
opt = 3 # -O level (a number, or the string "s"/"z")
debug = false # -g
lto = true # -flto (note: some packaged gcc builds ship without the LTO plugin)
lto = true # -flto; /GL + /LTCG on cl.exe (note: some packaged gcc builds ship without the LTO plugin)
strip = true # -s at link time
# passthrough escape hatch (fixed keys, open values):
cflags = ["-fno-plt"]
Expand Down Expand Up @@ -1819,6 +1846,7 @@ discover = ["tests/**/*.cpp"] # the default
| Key | Type | Meaning |
|---|---|---|
| `discover` | array of globs | every file a glob matches is one test program; a glob beginning with `!` removes the files it matches; `[]` discovers none |
| `windows_code_page` | `"utf-8"` or `"legacy"` | the ANSI code page of every test program on Windows, in the meaning of the target key of the same name; the default is `"legacy"`, the system's code page *(2026.10.5.2+)* |

The globs use the vocabulary of `[build] sources`. A test's name is its path
relative to the fixed directory of the first glob that matched it, without the
Expand All @@ -1827,6 +1855,12 @@ an array of non-empty strings is an error; any other key in `[test]` is a
warning, and an error under `--strict`. [08 — Testing](08-testing.md) describes
the test model.

A test program exercises the code it links, and that code may run in a
declared code page. `windows_code_page = "utf-8"` lets the tests run in the same
one, so that their result does not depend on the region setting of the machine
that runs them. The test programs receive the application manifest and nothing
else of `[resources]`.


## 3. Worked Examples

Expand Down
24 changes: 24 additions & 0 deletions docs/07-workspace.md
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,30 @@ in the workspace root is already inherited by every member, per triple, with the
member winning. A second spelling for the same capability would be surface with
no function.

**Profiles are inherited by name (2026.10.5.2+).** A `[profile.<name>]` in the
workspace root reaches every member that does not declare a profile of that
name; a member's own table replaces the workspace's whole, as
`[target.<triple>]` does. A profile is one value per graph, so members that
share it are planned and compiled together. Before 2026.10.5.2 a virtual root's
profiles reached no member and were ignored without a diagnostic, and a rooted
workspace's applied only when its own package was the first one selected.

**The root package is a member.** In a workspace whose root carries
`[package]`, the root package receives `[workspace.package]` and
`[workspace.build]` once, as every other member does (2026.10.5.2+), so its
commands are the same in every selection. The root manifest holds three kinds
of keys:

| Keys | Owner | Effect on the root package | Effect on other members |
|---|---|---|---|
| `[workspace]`, `[workspace.dependencies]` | the workspace | through `x.workspace = true` | through `x.workspace = true` |
| `[workspace.package]`, `[workspace.build]` | the workspace | inherited | inherited |
| `[toolchain]`, `[target.<triple>]`, `[indices]`, `[profile.<name>]` | the root position | its own | inherited where the member is the root of a build; the member's own declaration wins |
| `[package]`, `[build]`, `[dependencies]`, `[targets]`, `[features]`, `[resources]`, `[test]` | the root package | its own | none |

The root package's `[build] ldflags` are its own as well: they reach its own
images, and neither the members' images nor a dependency's shared library.

### 4.2 One standard for the whole module graph

A C++ module graph has exactly one standard: BMIs are not compatible across
Expand Down
8 changes: 8 additions & 0 deletions docs/12-binary-distribution.md
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,14 @@ archive is only ever `--strip-debug`ed, because `--strip-all` removes the
archive symbol index and the consumer's link then fails with `archive has no
index; run ranlib to add one`.

### LTO intermediate code is not shipped (2026.10.5.2+)

A profile with `lto = true` compiles a packed static library's objects without
LTO: no `-flto` intermediate code, and no `/GL` objects on cl.exe. Such code is
readable only by the compiler release that wrote it, and a prebuilt archive is
consumed by other releases. The build reports this once and its summary reads
`+ lto (partial)`. Programs and shared libraries in the same build keep LTO.

## Current limitations

| | status |
Expand Down
18 changes: 18 additions & 0 deletions docs/20-toolchains.md
Original file line number Diff line number Diff line change
Expand Up @@ -1034,6 +1034,24 @@ The device row keeps `runner` unset. An artifact cannot be run off an iOS
device without a signature the developer owns, which is not something a build
tool can supply.

## The standard library modules: `std` and `std.compat`

A toolchain provides `import std` when its standard library ships the module
source, and `import std.compat` when it ships the second one beside it. The two
are read from one directory and offered as a pair (2026.10.5.2+):

| Standard library | `std` | `std.compat` |
|---|---|---|
| libstdc++ (GCC 15 and later) | `bits/std.cc` | `bits/std.compat.cc` (2026.10.5.2+) |
| libc++ | `std.cppm` | `std.compat.cppm` |
| MSVC STL (cl.exe and the llvm row on the MSVC ABI) | `modules/std.ixx` | `modules/std.compat.ixx` (llvm row 2026.10.5.1+) |
| a package (`[package] std-module`) | its `std-module` | its `std-compat-module`, or none |

Each module is compiled once per configuration into the global cache, and
`std.compat` only when a unit of the build imports it (2026.10.5.2+). A build
that imports `std.compat` from a library that does not provide it is refused
before any compile, naming the library.

## Project-Level Version Pinning

If a project needs to pin a specific version rather than rely on the global default, declare it in the project's `mcpp.toml`:
Expand Down
1 change: 1 addition & 0 deletions docs/50-machine-output.md
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,7 @@ a program classifying the outcome reads `reason`:
| `managed-only` | `--managed-only` met a source that is not the ecosystem's: the message names each one and where it was stated *(2026.10.1.3+)* |
| `payload-override` | an `[xlings.overrides]` entry names a path that does not exist, a version a requirement refuses, or is stated by a dependency *(2026.10.1.3+)* |
| `payload-request` | a build program asked for a payload no manifest of this build declares `provision = "on-request"`, or asked again in three consecutive runs *(2026.10.1.3+)* |
| `lto-export-discovery` | a PE shared library whose exports are discovered would be compiled by cl.exe into `/GL` objects, which hold no symbol table: `windows_auto_export = true` stated under `lto = true`, or `/GL` written into the flags of a package it links *(2026.10.5.2+)* |
| `local-toolchain` | a toolchain named by path, or stated by a build program's toolchain phase, cannot be used: no driver, a contradicting family, a missing tool or sysroot *(2026.10.1.3+)* |
| `convention-unreplaced` | the convention was overridden and nothing replaced it |
| `os-mismatch` | the requested and resolved triples name different systems |
Expand Down
4 changes: 2 additions & 2 deletions docs/specs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,12 @@
| [SPEC-001](package-identity.md) | 包身份(`package.namespace` / `package.name`)、`[dependencies]` 选择器与匹配机制 | 评审中 v1.1 | 2026-08-03 | mcpp >= 0.0.106 |
| [SPEC-002](target-side.md) | 目标侧模型与能力声明(`mcpp:` 保留命名空间、五层、三条规则) | 评审中 v1.0 | 2026-08-24 | mcpp >= 2026.8.24.2 |
| [SPEC-003](exit-codes.md) | 退出码契约(分类、语义、稳定性承诺) | 评审中 v1.0 | 2026-09-01 | mcpp >= 2026.9.1.1 |
| [SPEC-004](manifest-semantics.md) | `mcpp.toml` 的平面划分、条件化形状、解析轴与命名规约 | 草案 v1.11 | 2026-10-05 | 条件化形状 mcpp >= 2026.8.29.1;目标轴 mcpp >= 2026.9.6.4;`linkage` 默认值 mcpp >= 2026.9.15.2;链接 flag 的词读法 mcpp >= 2026.9.26.2;条件化的 `dialect_cxxflags` 与 `-p` 的包身份 mcpp >= 2026.9.28.1;条件表按具体程度生效 mcpp >= 2026.9.28.2;平台前缀规约 mcpp >= 2026.10.5.1 |
| [SPEC-004](manifest-semantics.md) | `mcpp.toml` 的平面划分、条件化形状、解析轴与命名规约 | 草案 v1.12 | 2026-10-05 | 条件化形状 mcpp >= 2026.8.29.1;目标轴 mcpp >= 2026.9.6.4;`linkage` 默认值 mcpp >= 2026.9.15.2;链接 flag 的词读法 mcpp >= 2026.9.26.2;条件化的 `dialect_cxxflags` 与 `-p` 的包身份 mcpp >= 2026.9.28.1;条件表按具体程度生效 mcpp >= 2026.9.28.2;平台前缀规约 mcpp >= 2026.10.5.1;根包的继承、根位置的 profile、链接 flag 的作用域、链接期优化与导出发现 mcpp >= 2026.10.5.2 |
| [SPEC-005](build-database.md) | 构建数据库:`mcpp emit build-database` 的内容、取值规则与不写工程目录的保证 | 评审中 v1.6 | 2026-09-29 | mcpp >= 2026.9.15.1;v1.3 条款 mcpp >= 2026.9.26.2;v1.4 条款 mcpp >= 2026.9.27.1;v1.5 条款 mcpp >= 2026.9.28.1;v1.6 条款 mcpp >= 2026.9.29.5 |
| [SPEC-006](toolchain-management.md) | 工具链管理:身份、来源、选择与载荷契约 | 草案 v0.6 | 2026-10-02 | 逐条标注;已实现条款 mcpp >= 2026.9.24.1;§3.7 mcpp >= 2026.9.28.1;§3.7.1 mcpp >= 2026.9.28.2;§2.2.1 与 §3.3 的非缺省来源 mcpp >= 2026.10.1.3 |
| [SPEC-007](build-plugins.md) | 构建插件:配置、施工与校验的分工,运行时与规划期的义务 | 草案 v0.6 | 2026-09-28 | 逐条标注;mcpp >= 2026.9.26.2;v0.3 条款 mcpp >= 2026.9.27.1;v0.4 条款 mcpp >= 2026.9.28.1;v0.5 条款 mcpp >= 2026.9.28.2;v0.6(§9)mcpp >= 2026.9.28.3 |
| [SPEC-008](library-interface.md) | 库的接口:公开模块、发布闭包与两种形态的一致 | 草案 v0.1 | 2026-09-28 | 第一阶段(只警告)mcpp >= 2026.9.28.3 |
| [SPEC-009](toolchain-maintenance.md) | 工具链的支持与维护:版本线、默认值、来源、移动与退役 | 草案 v0.2 | 2026-10-05 | 逐条标注;本版只有规范,多数条款未实现 |
| [SPEC-009](toolchain-maintenance.md) | 工具链的支持与维护:版本线、默认值、来源、移动与退役 | 草案 v0.3 | 2026-10-05 | 逐条标注;本版只有规范,多数条款未实现 |

## 文档约定

Expand Down
Loading
Loading