Skip to content

Commit d280170

Browse files
committed
2026.9.29.5: a workspace's build programs are reused across selections and run dependencies first, the build database and --configure-only plan by configuration, and the output names what it reports
The validation project's post-release run of 2026.9.29.4 showed five defects in the commands around the workspace build (design document section 17.1). - D1: a member program's graph document listed every requester in the plan, the virtual root included, so the program's re-run key followed the selection and -p, pack and emit reran the programs a --workspace build ran. The document lists the requests made inside the program's closure (graph_package_entry takes the closure's packages). - The members' programs run dependencies first (depth-first over the plan's requests; a cycle skips its closing edge); they ran in discovery order. - D2: `mcpp emit build-database` and `mcpp build --configure-only` plan a workspace by configuration, each member's tests included (BuildOverrides::member_targets), so a package the members share is described once per configuration; members that are programs and their tests are described as such. A configuration whose plan fails is planned member by member, so a member's failure affects that member only. Set names carry a configuration prefix only in a document of several configurations; a set and a compile command (file and output) are described once (SPEC-005 v1.6). - A command that plans several configurations publishes the root compile_commands.json once, as the union of their databases; each configuration replaced it, a race under concurrent groups. - D3: the build program status lines name the package. - D4: a selected member is announced by its directory in a --workspace build. - D5: `mcpp pack` reports more than eight outputs by the entry each lies in below their common directory, with a count; --verbose and --message-format json name every output. - e2e 839, 840, 841; docs/07, docs/10, docs/30 in both languages; SPEC-005 v1.6; version 2026.9.29.5.
1 parent 793221e commit d280170

34 files changed

Lines changed: 858 additions & 115 deletions

‎.agents/docs/2026-09-29-workspace-build-graph-design.md‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -563,6 +563,10 @@ read from the member, or made a value of the plan:
563563
| the runtime files of a program shipped through `artifacts` (2026.9.29.3) | its link waited for the plan's deploy set, which a workspace plan does not place; its own runtime files were not in the member's directory | the link waits for no plan-level file; a member's runtime set includes the closures its `artifacts` edges reach | e2e 833 G9 |
564564
| the link line of a program shipped through `artifacts` (2026.9.29.4) | the plan's line, which pools the dependencies' flags and not a member's, so a library its package's build program states was missing | a link group of its own closure that places nothing (`LinkGroup::linkOnly`) | e2e 838 |
565565
| `${mcpp.bin_dir}` in a member's action (2026.9.29.4) | the plan's `bin/` | the declaring member's product directory | e2e 838 A4 |
566+
| a member program's graph document (2026.9.29.5) | listed every requester in the plan, the virtual root included, so the program's re-run key followed the selection | the requests made inside the program's closure | e2e 839 B3, B4 |
567+
| the order of the members' programs (2026.9.29.5) | discovery order | dependencies first (a cycle skips its closing edge) | e2e 839 B2 |
568+
| `emit build-database`, `--configure-only` (2026.9.29.5) | one plan per member | one plan per configuration, each member's tests included; a failed configuration planned member by member | e2e 840 |
569+
| the root compile database of several configurations (2026.9.29.5) | the last written configuration's, a race under concurrent groups | the union, published once by the command | e2e 840 B |
566570

567571
Each criterion fails on 2026.9.29.1 and passes on 2026.9.29.2. The resource
568572
case also showed a defect of every build: a quoted `#include` in a script was

‎CHANGELOG.md‎

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,52 @@
44
> Each `## [<version>]` section is that release's notes. Entries are written in English
55
> from 2026.9.28.3 on; earlier entries remain as written.
66

7+
## [2026.9.29.5] - 2026-09-29
8+
9+
This release completes the workspace build graph in the commands around the
10+
build, from the validation project's post-release run of 2026.9.29.4: build
11+
programs are reused across selections and run dependencies first, the build
12+
database and `--configure-only` plan by configuration, and the output names
13+
what it reports.
14+
15+
### Fixed
16+
17+
- **A member's build program is reused whichever members a command selects.**
18+
Its graph document listed every requester in the plan, the virtual root
19+
included, so the program's re-run key followed the selection: `-p`, `mcpp
20+
pack` and `mcpp emit build-database` reran the programs a `--workspace`
21+
build had run (7 to 15 s each in the validation project). A program's
22+
document now lists the requests made inside its own closure (e2e 839).
23+
- **A member's build program runs after those of the members it depends on.**
24+
They ran in discovery order, so a member's program could run before its
25+
dependency's had applied its directives (e2e 839).
26+
- **`mcpp emit build-database` and `mcpp build --configure-only` plan a
27+
workspace by configuration, as the build does.** They planned each member
28+
separately, so a package two members use was described once per member,
29+
each time with other arguments (the validation project's core library three
30+
times). A member that is a program is described as one, and its tests as
31+
tests. A configuration whose plan fails is planned member by member, so a
32+
member's failure still affects that member only (e2e 840; SPEC-005 v1.6).
33+
- **A command that plans several configurations writes the root
34+
`compile_commands.json` once**, as the union of their databases. Each
35+
configuration replaced it, and under `mcpp build --workspace`, whose
36+
configurations build at the same time, the file was the last one's (e2e 840).
37+
38+
### Behaviour changes
39+
40+
- **The build program status lines name the package**:
41+
`build.mcpp compiling <package>`, `running <package>`,
42+
`up to date <package> (cached)` (e2e 839).
43+
- **A selected member is announced by its directory** in a `--workspace`
44+
build, also where another member depends on it (e2e 839).
45+
- **`mcpp pack` summarises many outputs.** A format that reports more than
46+
eight outputs is reported by the entry each lies in below their common
47+
directory, with a count; `--verbose` names every output, and
48+
`--message-format json` lists every one as before (e2e 841).
49+
- **Build database set names (SPEC-005 v1.6).** A set is named by its package;
50+
a document of several configurations prefixes each name with the
51+
configuration's build directory name, instead of `<member>/`.
52+
753
## [2026.9.29.4] - 2026-09-29
854

955
This release links a program that a workspace member ships through

‎docs/07-workspace.md‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,14 @@ member that several members use is compiled once.
441441
- **Resources.** A member's `[resources]` and `windows_code_page` are
442442
compiled against the member's directory and include directories and embedded
443443
into that member's programs and shared libraries only (2026.9.29.2+).
444+
- **Build programs.** The members' build programs run dependencies first, and
445+
a program's result is reused by every command whose inputs to it are
446+
unchanged, whichever members the command selects (2026.9.29.5+).
447+
- **Compile database.** `mcpp build --configure-only` and `mcpp emit
448+
build-database` plan as the build does, one plan per configuration with each
449+
member's tests, so a package the members share is described once per
450+
configuration. A command that planned several configurations writes the root
451+
`compile_commands.json` once, as the union of their databases (2026.9.29.5+).
444452
- **No-op builds.** A command repeated with nothing changed is answered by one
445453
check per configuration, without planning.
446454
- **Module names.** Members built in one graph share one module namespace:

‎docs/10-pack-and-release.md‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,12 @@ the last is the distributable and only it is printed as `Packed`. A format
265265
whose chain ends in two files is refused by `mcpp run --format`, naming both,
266266
because a runner takes one operand.
267267

268+
A format may report many outputs, one per file of a distribution tree. Up to
269+
eight are printed one per line; more are printed by the entry each lies in
270+
below their common directory, with a count (`Packed Release/app (1309
271+
files)`), and `--verbose` prints every one (2026.9.29.5+).
272+
`--message-format json` lists every output in either case.
273+
268274
An unknown `<name>` is refused naming the format set the resolved graph
269275
provides, the same set `mcpp pack --format bogus` reports. `--format` together
270276
with `--no-runner` is refused — an `.apk` or an installed `.app` cannot be

‎docs/30-build-mcpp.md‎

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1045,6 +1045,11 @@ one. `mcpp::graph_file()` names a JSON document that states the resolved graph:
10451045
`""`.** The root decides the graph, and when its program runs every input of
10461046
that decision is final, which is the reason `dep_linkage` is offered to it
10471047
alone.
1048+
- **In a workspace plan each selected member's program receives the document
1049+
of its own closure**, in which it is `root`, and `requested_by` lists the
1050+
requests made inside that closure (2026.9.29.5+). The document, and so the
1051+
program's re-run key, is therefore the same whichever members a command
1052+
selects. The members' programs run dependencies first.
10481053
- **`[package.metadata.<tool>]` is the package's statement about itself.** The
10491054
engine does not interpret the table. A path in it is resolved by the reader
10501055
against the entry's `manifest_dir`, because only the reader knows which values
@@ -1513,8 +1518,9 @@ variable, emit `mcpp:rerun-if-changed=config.h` / `mcpp:rerun-if-env-changed=USE
15131518
This replaces the old "process exited 0, so assume it's fine" guesswork with an
15141519
explicit input/output contract — incremental builds stay correct.
15151520
1516-
When nothing changed the output is `build.mcpp up to date (cached)`; otherwise
1517-
`build.mcpp compiling` / `running`.
1521+
When nothing changed the output is `build.mcpp up to date <package> (cached)`;
1522+
otherwise `build.mcpp compiling <package>` / `running <package>` (the package
1523+
is named from 2026.9.29.5 on).
15181524
15191525
## Host tools from a dependency (mcpp 2026.8.5.1+)
15201526

‎docs/40-baremetal.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -206,8 +206,8 @@ Measured output:
206206
Resolving toolchain
207207
Resolved llvm@22.1.8 → riscv64-none-elf → @mcpp/registry/data/xpkgs/xim-x-llvm/22.1.8/bin/clang++
208208
Resolved host toolchain for build.mcpp: clang 22.1.8 (x86_64-unknown-linux-gnu)
209-
build.mcpp compiling
210-
build.mcpp running
209+
build.mcpp compiling blinky
210+
build.mcpp running blinky
211211
Inferred sources [src/**/*.{cppm,cpp,cc,c,S,s,asm}]
212212
Inferred target blinky (bin from src/main.cpp)
213213
Compiling blinky v0.1.0 (.)

‎docs/specs/README.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
| [SPEC-002](target-side.md) | 目标侧模型与能力声明(`mcpp:` 保留命名空间、五层、三条规则) | 评审中 v1.0 | 2026-08-24 | mcpp >= 2026.8.24.2 |
3535
| [SPEC-003](exit-codes.md) | 退出码契约(分类、语义、稳定性承诺) | 评审中 v1.0 | 2026-09-01 | mcpp >= 2026.9.1.1 |
3636
| [SPEC-004](manifest-semantics.md) | `mcpp.toml` 的平面划分、条件化形状、解析轴与命名规约 | 草案 v1.10 | 2026-09-28 | 条件化形状 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 |
37-
| [SPEC-005](build-database.md) | 构建数据库:`mcpp emit build-database` 的内容、取值规则与不写工程目录的保证 | 评审中 v1.5 | 2026-09-28 | 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 |
37+
| [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 |
3838
| [SPEC-006](toolchain-management.md) | 工具链管理:身份、来源、选择与载荷契约 | 草案 v0.4 | 2026-09-28 | 逐条标注;已实现条款 mcpp >= 2026.9.24.1;§3.7 mcpp >= 2026.9.28.1;§3.7.1 mcpp >= 2026.9.28.2 |
3939
| [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 |
4040
| [SPEC-008](library-interface.md) | 库的接口:公开模块、发布闭包与两种形态的一致 | 草案 v0.1 | 2026-09-28 | 第一阶段(只警告)mcpp >= 2026.9.28.3 |

‎docs/specs/build-database.md‎

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44
|---|---|
55
| 规范编号 | SPEC-005 |
66
| 标题 | mcpp 输出的构建数据库:内容、取值规则与不写工程目录的保证 |
7-
| 状态 | 评审中 v1.5 |
8-
| 版本 | 1.5 |
9-
| 最后修改 | 2026-09-28 |
10-
| 对应实现 | mcpp >= 2026.9.15.1;v1.3 修改的 R2.5、R3.7、R3.8、R4.1、R5.2 为 mcpp >= 2026.9.26.2;v1.4 修改的 R2.5 为 mcpp >= 2026.9.27.1;v1.5 修改的 R3.7、R3.12、R5.1、R5.2 为 mcpp >= 2026.9.28.1 |
7+
| 状态 | 评审中 v1.6 |
8+
| 版本 | 1.6 |
9+
| 最后修改 | 2026-09-29 |
10+
| 对应实现 | mcpp >= 2026.9.15.1;v1.3 修改的 R2.5、R3.7、R3.8、R4.1、R5.2 为 mcpp >= 2026.9.26.2;v1.4 修改的 R2.5 为 mcpp >= 2026.9.27.1;v1.5 修改的 R3.7、R3.12、R5.1、R5.2 为 mcpp >= 2026.9.28.1;v1.6 修改的 R2.1、R3.3、R3.4、R3.5、R4.1、R5.2 为 mcpp >= 2026.9.29.5 |
1111
| 相关设计文档 | `.agents/docs/2026-09-14-636-build-database-and-the-latest-xlings.md`<br>`.agents/docs/2026-09-26-compile-database-and-issue-699-design.md` |
1212
| 相关 issue | #636, #648, #655, #699, #702, #707 |
1313
| 依据的外部规范 | S1「C++ Build Database: IDE Profile」profile 0.3.0(§7.2 的 `generated`,Sunrisepeak/mcpp-language-server#28;此前为 0.2.0)与 S2 0.2.0 §3.4,取自 https://github.com/Sunrisepeak/lsp-mcpp-private 提交 `b82859d`(schema 自提交 `28ecd6e` 起未变);S2 0.3.0 §3.4 的部分回答(S2-3.4-12、S2-3.4-13,Sunrisepeak/mcpp-language-server#25);JSON Compilation Database |
@@ -42,7 +42,7 @@ Database 定义,本规范不重复它们的字段定义,只规定 mcpp 作为生
4242
## 2. 不写工程目录
4343

4444
- **R2.1** 命令**禁止**写入工程目录,即根包、工作区成员与 path 依赖的源码树。规划
45-
写入 `$MCPP_HOME/cache/build-database/<key>`,`<key>` 由工程根与成员决定。该目录
45+
写入 `$MCPP_HOME/cache/build-database/<key>`,`<key>` 由工程根与一次规划的成员决定。该目录
4646
是缓存,可以随时删除。**已实现**
4747
- **R2.2** 命令不编译:标准库模块被描述而不被编译,也不生成只供链接使用的输入(GCC 的
4848
`mcpp-clean-link.specs`)。工具链照常被查询(版本、目标三元组、sysroot 等),与
@@ -84,14 +84,18 @@ mcpp 输出的 S1 文档满足 S1 等级 2,不输出 `ide.options`。等级 3
8484

8585
### 3.2 集合
8686

87-
- **R3.3** 每个包一个集合,名为包的限定名(`<namespace>.<name>` 或 `<name>`)。根包
88-
测试目标的源文件归入集合 `<包>:test`,标准库模块的单元归入集合 `mcpp:std`。工作区
89-
文档中,每个集合名带前缀 `<成员>/`。**已实现**
90-
- **R3.4** `visible-sets` 列出同一成员的其余所有集合。引擎在一次调用的一张模块图上
87+
- **R3.3** 每个包一个集合,名为包的限定名(`<namespace>.<name>` 或 `<name>`)。根包与
88+
工作区被选成员的测试目标的源文件归入集合 `<包>:test`,标准库模块的单元归入集合
89+
`mcpp:std`。工作区按配置规划,与 `mcpp build` 相同:每个配置一次规划,成员共用的包
90+
在一个配置中只有一个集合。文档描述多个配置时,每个集合名带前缀 `<配置>/`,`<配置>`
91+
为该配置构建目录的名字;只有一个配置时不带前缀。两次规划描述同一配置的同一集合时
92+
(见 R5.2 的逐成员规划),该集合只出现一次。**已实现**
93+
- **R3.4** `visible-sets` 列出同一次规划的其余所有集合。引擎在一次调用的一张模块图上
9194
解析 import,更窄的闭包会描述一条构建并不执行的规则。**已实现**
9295
- **R3.5** `family-name` 为包名,`mcpp:std` 集合的为 `mcpp:std`;`ide.configuration`
93-
为 profile 名;`ide.kind` 在测试集合为 `test`,在根包集合按其目标为 `library`、
94-
`executable` 或 `other`,在依赖包集合与 `mcpp:std` 为 `library`。**已实现**
96+
为 profile 名;`ide.kind` 在测试集合为 `test`,在根包与工作区被选成员的集合按其
97+
目标为 `library`、`executable` 或 `other`,在依赖包集合与 `mcpp:std` 为 `library`。
98+
**已实现**
9599
- **R3.6** 单元的 `arguments` 依次是驱动、集合的 `baseline-arguments`、单元的
96100
`local-arguments`,以及单元自己结尾的 `-c <source> -o <object>`(若有;两个操作数
97101
相对 `work-directory` 指向 `source` 与 `object`)。`baseline-arguments` 是集合中每个
@@ -170,7 +174,8 @@ mcpp 输出的 S1 文档满足 S1 等级 2,不输出 `ide.options`。等级 3
170174
## 4. `--spec compile-commands`
171175

172176
- **R4.1** 文档为 `mcpp build --configure-only` 在同一组选择器下写入
173-
`compile_commands.json` 的条目,差别只在输出路径位于 §2 的工作目录之下。标准库
177+
`compile_commands.json` 的条目,差别只在输出路径位于 §2 的工作目录之下;同一文件与
178+
同一输出只有一条条目,文档描述多个配置时,一个文件在每个编译它的配置中各有一条。标准库
174179
模块的单元也在其中,遵循 S1-12-1 的导出规则:S1 文档里 `mcpp:std` 集合的每个
175180
单元同样导出为一条 `compile_commands.json` 条目。**已实现**
176181

@@ -179,8 +184,9 @@ mcpp 输出的 S1 文档满足 S1 等级 2,不输出 `ide.options`。等级 3
179184
- **R5.1** `kind` 为 `mcpp.build-database`,`kindVersion` 为 1。`data` 含 `spec`
180185
(`{"name": "s1", "version": "0.3.0"}` 或 `{"name": "compile-commands"}`)、
181186
`database`、`watch` 与 `inputs-fingerprint`。**已实现**
182-
- **R5.2** 命令独立规划每一个被选中的成员:一个成员规划失败只影响它自己,不影响
183-
其余成员的集合(#699 第 1 项)。规划失败的成员不贡献任何集合,只贡献一条 `error`
187+
- **R5.2** 一个成员规划失败只影响它自己,不影响其余成员的集合(#699 第 1 项)。命令
188+
按配置规划被选中的成员;一个配置的规划失败时,该配置的成员逐个规划,因此失败仍归于
189+
各自的成员。规划失败的成员不贡献任何集合,只贡献一条 `error`
184190
诊断,`path` 为该成员的 `mcpp.toml`,相对工作区根目录;诊断码为:不在工程中时
185191
`MCPP_BUILD_DATABASE_NO_PROJECT`;该成员的规划因离线而需要下载时
186192
`MCPP_OFFLINE_DOWNLOAD_REQUIRED`,消息指出需要下载的第一项;其他规划失败为
@@ -226,3 +232,4 @@ mcpp 输出的 S1 文档满足 S1 等级 2,不输出 `ide.options`。等级 3
226232
| 1.3 | 2026-09-26 | R2.5:`emit` 下构建失败的宿主工具是警告。R3.7:`work-directory` 是输出目录,模块接口单元的 `arguments` 带语言 flag。R3.8:标准库单元的 `provides` 指向 std 缓存中的 BMI,工具链带 `build-id`。R4.1:compile-commands 文档包含标准库单元(S1-12-1)。R5.2:成员各自规划,构建程序失败的包不带其指令地被描述(#699,#702)。 |
227233
| 1.4 | 2026-09-26 | R2.5:命令不构建宿主工具;工具库中没有的工具被推迟,输出说明 `MCPP_BUILD_DATABASE_HOST_TOOL_DEFERRED`,取代 1.3 的警告 `MCPP_BUILD_DATABASE_HOST_TOOL_UNBUILT`(#707)。 |
228234
| 1.5 | 2026-09-28 | R3.7:规则声明的设备源不是编译单元,不进入 S1 与 `compile_commands.json`(#724)。新增 R3.12:集合的 `ide.generated` 列出规则生成的文件与目录,给出构建写入的路径与生成它的步骤,S1 0.3.0(#724,Sunrisepeak/mcpp-language-server#28)。R5.1:S1 版本为 0.3.0。R5.2:以构建程序的指令为前提的检查不对其构建程序已失败的包运行,失败路径保留已记录的说明(#724)。 |
235+
| 1.6 | 2026-09-29 | 工作区按配置规划,与 `mcpp build` 相同(R2.1、R3.3、R3.4、R5.2):成员共用的包在一个配置中只描述一次;集合名的前缀由 `<成员>/` 改为只在文档描述多个配置时出现的 `<配置>/`;一个配置的规划失败时逐成员规划。R3.5:被选成员的集合按其目标给出 `ide.kind`。R4.1:同一文件与输出一条条目。 |

‎docs/zh/07-workspace.md‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,12 @@ mcpp test --workspace --workspace-timeout 1800 # whole fan-out (default 0 = no
407407
- **Hooks。** 每个被选成员的 `[hooks]` 按成员顺序在构建前后运行。
408408
- **资源。** 成员的 `[resources]` 与 `windows_code_page` 按该成员的目录与 include 目录编译,
409409
只嵌入该成员自己的程序与共享库(2026.9.29.2+)。
410+
- **构建程序。** 成员的构建程序按依赖在前的顺序运行;只要程序的输入不变,无论命令选中哪些
411+
成员,程序的结果都被复用(2026.9.29.5+)。
412+
- **编译数据库。** `mcpp build --configure-only` 与 `mcpp emit build-database` 按构建的方式
413+
规划,每个配置一次规划并包含各成员的测试,因此成员共用的包在每个配置中只描述一次。规划了
414+
多个配置的命令只写一次根目录的 `compile_commands.json`,内容为各配置数据库的并集
415+
(2026.9.29.5+)。
410416
- **无事可做的构建。** 在没有任何改动时重复执行的命令,每个配置只做一次检查,不重新规划。
411417
- **模块名。** 在同一张图中构建的成员共享一个模块命名空间:两个成员各自提供同名模块时,不能在
412418
同一条 `--workspace` 命令中构建;分别用 `-p` 构建。

0 commit comments

Comments
 (0)