Skip to content
Closed
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
55 changes: 55 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,61 @@
> 本文件追踪 `mcpp-community/mcpp` 公开仓的版本演进。
> 格式参考 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/)。

## [2026.9.27.1] - 2026-09-27

### 缺陷修复(#704、#705、#710、#712 至 #716)

- **宿主构建读取宿主三元组的行(#704)。** 不带 `--target` 的构建此前不读取
`[target.<宿主三元组>]`,其中的 `cxx_runtime` 没有效果。现在宿主构建应用这一行,与
`--target <宿主三元组>` 相同,行的查找与拼写无关;`--toolchain` 仍优先于行的 `toolchain`
(SPEC-004 §4.6)。
- **`xpkg_dir` 回答 xlings 装下的载荷(#712、#716)。** 版本位按 xlings 的版本文法求值,
`libglvnd@1.7` 回答 `1.7.0.1`。xlings 在 `install_targets` 事件中报告每个请求解析到的载荷,
mcpp 按地址记录并优先读取。安装记录仍在而载荷已被删除时,联网构建重新安装,离线构建拒绝并
点名缺失的地址;构建缓存记录读取过的载荷目录,任一目录缺失时快路径不复用缓存。mcpp 以
xlings 发布的版本选择向量测试同一规则(SPEC-001 §10.1)。
- **宿主工具的工具链由请求方决定一次(#710)。** 顺序为 `--toolchain`、工具包自己的声明(工作
空间成员先继承根位置的键)、请求方的宿主工具链;结果传给子构建并写入工具库的键。工具包的源树
摘要跳过带自己 `mcpp.toml` 的子目录,并以 UTF-8 计算路径(#705)。
- **工作空间(#713、#714)。** 成员隐式继承根的 `[xlings.workspace]` 条目与条件行,自己声明的
同一个包优先。未解析的 `workspace = true` 在根包、`-p` 成员与各类依赖处都被点名拒绝;带
`[package]` 的工作空间根解析自己的条目。`[build] sources = []` 不再推断库目标。
- **规则只经其声明的扩展名到达(#715)。** 一个规则只在包含它声明的设备源扩展名时进入包的合成
构建程序;状态行只列出实际生效的规则。

### 规划不构建宿主工具(#707)

`mcpp emit build-database` 不再构建依赖提供的宿主工具。工具库中已有的工具照常使用;没有的工具被
推迟,报告为 note `MCPP_BUILD_DATABASE_HOST_TOOL_DEFERRED`,请求它的构建程序收到该工具将被发布的
路径。它取代 2026.9.26.2 的警告 `MCPP_BUILD_DATABASE_HOST_TOOL_UNBUILT`(SPEC-005 v1.4 R2.5)。
`mcpp build` 不受影响。

### 构建程序与依赖边(#708、#709、#711)

- **action 的 `env` 与 `cwd`(协议 13,#708)。** `mcpp::action::env(name, value)` 与
`cwd(dir)` 由引擎的 action 包装器应用;`cwd` 按包根解析,声明的输入、输出与 stamp 不随它
移动;变量值改变时 action 重新运行。两者都未声明的 action 命令行与协议 12 逐字节相同。
- **特性的 `tools`(#709)。** `[features.<f>] tools = ["<bin>"]` 陈述特性需要本包的程序在
构建机器上运行;启用该特性的消费方得到该工具,与边上写 `tools` 相同。
- **`artifacts` 依赖边(#711)。** `x = { path = "...", artifacts = ["<bin>"] }` 以消费方的
目标与 profile 构建依赖的程序,输出到消费方的 `bin/`,不链接依赖的代码;action 以
`${mcpp.artifact:<x>/<bin>}` 引用它;`mcpp pack` 把它放在程序旁(SPEC-004 §10、
SPEC-007 R6.4)。

### 载荷的打包修订与自包含的 locale(xlings#620、#621)

- 依赖的索引条目的 `revision` 进入依赖完整性判断:修订号不同的已安装依赖按未安装处理。修订号
大于 0 的运行时载荷进入运行时契约(`revision=<n>`),修订号变化使依赖它的产物重新链接;修订号
为 0 时契约文本不变(SPEC-001 §10.2)。
- `mcpp pack` 的 bundle-all 形态随 glibc 载荷复制 `lib/locale` 与 `lib/gconv`,启动脚本设置
`LOCPATH` 与 `GCONV_PATH`(用户已设置时保留用户的值)。

### 其他

- ELF 检查以一次读取载入文件。此前逐字节读入,`mcpp test` 的链接后检查在测试程序较多时耗时
数十分钟。
- 规范:SPEC-001 v1.5、SPEC-004 v1.8、SPEC-005 v1.4、SPEC-007 v0.3。

## [2026.9.26.2] - 2026-09-26

### 编译数据库:一个配置一个数据库(#699 的报告;#397 C-1、#677 B1)
Expand Down
1 change: 1 addition & 0 deletions docs/04-mcpp-toml.md
Original file line number Diff line number Diff line change
Expand Up @@ -1780,6 +1780,7 @@ kind = "bin"
|---|---|---|
| Source files | `src/**/*.{cppm,cpp,cc,c,S,s,asm}` | Scanned recursively and automatically |
| Entry point | `src/main.cpp` | If this file exists, a `bin` target is inferred |
| Library target | a module interface under `src/` | Inferred when no `[targets]` table and no `src/main.cpp` exist; `[build] sources = []` states that the default build compiles nothing and infers no library (2026.9.27.1+) |
| Library root | `src/<pkg-tail>.cppm` | Override with `[lib].path` |
| C++ standard | `c++23` | Configure with `[package].standard`; supports `c++20` / `c++26` / `c++2a` / `c++2c` / `gnu++NN` / `c++latest` / `c++fly` (experimental playground) |
| C standard | `c11` | `.c` files go through the C compiler automatically |
Expand Down
61 changes: 61 additions & 0 deletions docs/05-dependencies.md
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,67 @@ and refused, and the refusal says to restate the source. `tools`, `features`,
effect on the row. A restatement that names another source is refused, naming
both sources (mcpp 2026.9.16.1+); before that release it was ignored.

**Which compiler builds a tool (mcpp 2026.9.27.1+).** The build that requests
a tool decides its toolchain once: `--toolchain` when given; otherwise the tool
package's own declaration, read as its own build reads it (for a workspace
member, after the workspace root's `[toolchain]`, `[target.<triple>]` and
`[indices]`), its host row's `toolchain` before `[toolchain]`; otherwise the
host toolchain the requesting build compiles its build programs with. The
choice is passed to the tool's sub-build and recorded in the tool store key, so
`mcpp build -p <tool>` in the workspace and the same tool built for a consumer
use the same compiler. The source digest of a tool package skips directories
that hold their own `mcpp.toml`, so editing a workspace member does not rebuild
a tool the workspace root provides.

### A feature that provides the package's tools (mcpp 2026.9.27.1+)

A package whose feature needs one of its own programs on the build machine
states it on the feature, and a consumer names only the feature:

```toml
# the tool package
[features.codegen]
tools = ["codegen"]

[targets.codegen]
kind = "bin"
main = "src/codegen.cpp"
```

```toml
# the consumer
[dependencies]
toolpkg = { path = "../toolpkg", features = ["codegen"] }
```

Enabling the feature has the effect of `tools = ["codegen"]` on the edge: the
program is built for the host and `mcpp::dep_bin("toolpkg", "codegen")` names
it. A consumer that does not enable the feature builds nothing. An entry that
names no `bin` target of the package is refused when the manifest loads, and the
message lists the package's `bin` targets.

### A dependency's program shipped with the consumer: `artifacts` (mcpp 2026.9.27.1+)

`tools` builds a program for the machine that runs the build. A program that
ships with the consumer and runs on its target (an updater, a helper process)
is requested with `artifacts`:

```toml
[dependencies]
updater = { path = "../updater", artifacts = ["updater"] }
```

- The dependency's `bin` target is built for the consumer's target and profile,
as a link unit of the consumer's plan, into the consumer's `bin/`. Under
`--target x86_64-linux-musl` it is a musl program.
- None of the dependency's code is linked into the consumer through this edge.
A package also reached through an ordinary edge is linked as usual.
- An action of the consumer's build program names the program with
`${mcpp.artifact:updater/updater}`, in its arguments and its inputs; a name
that matches no `artifacts` entry fails planning and names the placeholder.
- `mcpp run` does not choose it, and `mcpp pack` stages it beside the
consumer's program.

> The section has been parsed since early versions and, until 2026.8.29.1, read
> by nothing that made a decision: writing it produced a manifest that loaded,
> no diagnostic, and no effect.
Expand Down
7 changes: 6 additions & 1 deletion docs/06-features-and-capabilities.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ simd = { sources = ["src/simd/**"], flags = [
```

- **The table form accepts exactly** `implies`, `forward`, `defines`, `sources`,
`flags`, `requires`, `provides`. Anything else is reported as a schema warning
`flags`, `requires`, `provides`, `tools`. Anything else is reported as a schema warning
and ignored (mcpp 2026.9.1.1+); `deps` is reported separately as reserved and
points at `[feature-deps.<name>]`. Before that release `[features]` was
the one structured section with no schema check at all, so a misplaced
Expand All @@ -120,6 +120,11 @@ simd = { sources = ["src/simd/**"], flags = [
feature `flags` are **private per-TU build flags** — they never propagate to
consumers (same contract as `[build].flags`), so they stay inside the additive
model: scoped by glob, deterministic order, no cross-package effect.
- `tools` (mcpp 2026.9.27.1+) names `bin` targets of this package that the
feature needs on the build machine. A consumer that enables the feature
receives them as if its dependency edge had written `tools = [...]`
([05, build-time dependencies](05-dependencies.md)); a name that is not a
`bin` target of the package is refused at load.


### A feature that is a build rule (mcpp 2026.9.7.1+)
Expand Down
23 changes: 23 additions & 0 deletions docs/07-workspace.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,13 @@ A member can override an inherited version:
mbedtls = "4.0.0" # override; does not use the workspace version
```

An entry that says `.workspace = true` and that no workspace resolves is
refused wherever the package enters a build (the root, a member selected with
`-p`, a `path`, `git` or index dependency), naming the table and the entry
(mcpp 2026.9.27.1+). It is resolved against the `[workspace.dependencies]` of
the workspace whose `members` list the package; a workspace root that carries
its own `[package]` resolves its own entries the same way.

## 4. Inheriting Toolchain and Build Configuration

The workspace root's `[toolchain]` and `[target.<triple>]` settings are automatically inherited by all members. A member can override them in its own project file.
Expand Down Expand Up @@ -161,6 +168,22 @@ linkage = "static"
default = "llvm@20.1.7"
```

`[toolchain]`, `[target.<triple>]` and `[indices]` choose the compiler, the
target rows and the indices for a whole graph, so a member takes them from the
workspace root only where it is the root of a build: built from the workspace,
with `-p`, or as a host tool of another package (mcpp 2026.9.27.1+ for the
last). A member reached as a dependency takes them from that build's root.

A build without `--target` targets the host, and `[target.<host-triple>]`
applies to it as `--target <host-triple>` would (mcpp 2026.9.27.1+).

The root's `[xlings.workspace]` entries, including its
`[target.<selector>.xlings.workspace]` rows, are inherited implicitly as well
(mcpp 2026.9.27.1+): a payload describes the environment a build runs in, like
`[toolchain]`, so no opt-in is needed. A member's own declaration of the same
package wins. `[feature-xlings.<f>]` entries are not inherited, because a
feature belongs to the package that declares it.

### 4.1 `[workspace.package]` and `[workspace.build]`

Package metadata and build flags shared by every member are declared once at the
Expand Down
51 changes: 51 additions & 0 deletions docs/30-build-mcpp.md
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,16 @@ position was compared against a directory name, so a range installed a payload
and then answered that nothing was installed — which is why a rule package
could not state a floor and every project repeated its rule's package list.

**The answer is the payload xlings installed** *(2026.9.27.1+)*. xlings reports
what each address resolved to, and `xpkg_dir` answers from that record first.
Without one, it selects among the installed version directories by the xlings
version grammar: a bare version of one or two segments is a prefix range, three
or more segments must match as written, so `libglvnd@1.7` answers `1.7.0.1`.
Before this release the Cargo reading of `1.7` could not see a four-segment
directory, and the answer was `""` for a payload on disk. A declared payload
that was removed after it was installed is installed again, or refused
offline, instead of answering `""` (SPEC-001 §10.1).

**A package a DEPENDENCY declared is answered too** *(2026.9.6.6+)*, at the
version this build actually installed rather than the one the local manifest
wrote. One package means one version: where a project and a rule both name it,
Expand Down Expand Up @@ -685,6 +695,47 @@ scan agrees with what the generator will emit — the same assertion-plus-
verification trade `[modules].scan_overrides` makes, and the compiler's own
P1689 output checks it at build time.

#### Environment and working directory: `env` / `cwd` (protocol 13)

An action's command is an argv, not a shell line, so `NAME=value cmd` and
`cd dir && cmd` are not available to it. A generator configured through
environment variables, or one that must run in a particular directory, states
both on the action:

```cpp
mcpp::action a;
a.id = "gen";
a.role = mcpp::roles::source;
a.env("GEN_MODE", "release")
.cwd("tools") // relative to the package root
.arg("./gen").arg(out.c_str())
.output(out.c_str())
.submit();
```

The engine's action wrapper sets them before it runs the command. Declared
inputs, outputs and the stamp are resolved when the plan is made and do not
move with `cwd`; the command's own arguments are passed unchanged, so a
relative path among them is relative to `cwd`. A variable's value is part of
the edge's command line, and changing it re-runs the action. An action that
declares neither keeps the protocol 12 command line byte for byte.

#### A dependency's program in an action: `${mcpp.artifact:}` (2026.9.27.1+)

A dependency edge with `artifacts = ["<bin>"]` builds that program for the
consumer's target ([05](05-dependencies.md)). An action names it with
`${mcpp.artifact:<dependency>/<bin>}`, in its arguments and its inputs:

```cpp
a.arg("cp").arg("${mcpp.artifact:updater/updater}").arg(out.c_str())
.input("${mcpp.artifact:updater/updater}")
.output(out.c_str())
.submit();
```

A placeholder that names no `artifacts` entry fails planning and is named in the
error.

### Deploying what the program generated: `deploy` (2026.9.12.3+, protocol 11)

`[runtime] deploy` (docs/04 §2.11) places a file that already exists in the
Expand Down
17 changes: 9 additions & 8 deletions docs/50-machine-output.md
Original file line number Diff line number Diff line change
Expand Up @@ -489,20 +489,21 @@ program's directives: the manifest's own configuration, the toolchain, the
module graph and the standard-library units are described as usual, and one
`error` diagnostic, `MCPP_BUILD_DATABASE_PROGRAM_FAILED`, names it, with
`path` naming its `build.mcpp`. A later failure that follows from the missing
directives fails the whole member instead, under the rule above. A host tool
a package requested that fails to build is a warning instead,
`MCPP_BUILD_DATABASE_HOST_TOOL_UNBUILT`, naming the tool, its package and the
first line of the failure; planning continues, and a build program that only
names the tool configures as it would after a successful build. `mcpp build`
is unaffected by either: a build program or a host tool that fails there
still fails the build.
directives fails the whole member instead, under the rule above. The command
builds no host tool (mcpp 2026.9.27.1+): a requested tool already in the
global tool store is used, and one that is not is deferred, reported as the
note `MCPP_BUILD_DATABASE_HOST_TOOL_DEFERRED` naming the tool and its package.
The build program that requested it receives the path the tool will be
published at, and configures as it would after the tool was built. `mcpp build`
is unaffected: it builds the tool, and a build program or a host tool that
fails there still fails the build.

| code | severity | |
|---|---|---|
| `MCPP_LOCK_WOULD_CHANGE` | warning | the resolution differs from the project's `mcpp.lock`, which the command does not write |
| `MCPP_GENERATED_FILE_NOT_MATERIALIZED` | warning | a root `[build] generated_files` entry is missing or stale on disk, and the command does not write it |
| `MCPP_BUILD_DATABASE_STD_UNIT_UNDESCRIBED` | warning | no standard-library build command names its module source, so that unit is not listed |
| `MCPP_BUILD_DATABASE_HOST_TOOL_UNBUILT` | warning | a requested host tool failed to build; the tool is still built and its `check` actions still run |
| `MCPP_BUILD_DATABASE_HOST_TOOL_DEFERRED` | note | a requested host tool is not in the tool store and is not built by the command; the plan names the path it will be published at (2026.9.27.1+; replaces the 2026.9.26.2 warning `MCPP_BUILD_DATABASE_HOST_TOOL_UNBUILT`) |
| `MCPP_BUILD_DATABASE_PROGRAM_FAILED` | error | a build program failed; its package is described without its directives |

`--protocol-version` declares `init-mcpp-home`, `read-project`, `network`,
Expand Down
Loading