Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
551d747
2026.9.27.1: a build.mcpp can declare a runtime library search direct…
speak-agent Sep 25, 2026
c57c12f
A passing check moves a stamp it did not write past the inputs that c…
Sunrisepeak Sep 25, 2026
e2d0981
docs: the compile database and #699/#701/#702 design record, and SPEC…
speak-agent Sep 25, 2026
8601a38
Link flags are read as words and reach the linker as written (#703)
speak-agent Sep 26, 2026
c5c0b52
A Windows program's runtime DLLs are placed beside it after its link
speak-agent Sep 26, 2026
d4b3d8a
ci: the mingw-cross job runs the DLL placement e2e and asserts each p…
speak-agent Sep 26, 2026
f75c4c6
emit build-database plans every member, and a failing tool or program…
speak-agent Sep 26, 2026
e1d4361
docs: emit build-database's per-member failures and the two new codes
speak-agent Sep 26, 2026
aa0e088
e2e: emit build-database plans every member past a failing one (#699)
speak-agent Sep 26, 2026
1b7b9b2
Merge T4/T5: link flags as words (#703), DLL placement after a PE link
speak-agent Sep 26, 2026
e4fa02b
Merge T2: emit plans every member; host tool and build program failur…
speak-agent Sep 26, 2026
a25d385
emit: the comments cite S2 0.3.0's partial answer
speak-agent Sep 26, 2026
6f0cf59
One compile database per configuration, the output directory, and the…
speak-agent Sep 26, 2026
a228556
docs: the compile database's configuration, redirect and standard-lib…
speak-agent Sep 26, 2026
112cf31
Merge T1: one compile database per configuration; directory, the inte…
speak-agent Sep 26, 2026
9723508
compile database: one function words the foreign-entries warning for …
speak-agent Sep 26, 2026
106aad8
docs: SPEC-005 v1.3 and the spec index rows for SPEC-004 v1.7, SPEC-0…
speak-agent Sep 26, 2026
f4151de
runtime_search_dir, the prepare role, and a stamp newer than every in…
speak-agent Sep 26, 2026
34f4da9
e2e: runtime_search_dir, the prepare role and the stamp rule (mcpp#70…
speak-agent Sep 26, 2026
a93d4bf
docs: configuration/construction/verification, runtime_search_dir, th…
speak-agent Sep 26, 2026
eac684a
e2e: the wine leg of runtime_search_dir is 796
speak-agent Sep 26, 2026
0b5d113
e2e 794 names its wine counterpart, 796
speak-agent Sep 26, 2026
d8fb8e9
Merge T3: runtime_search_dir, the stamp rule, the prepare role and ro…
speak-agent Sep 26, 2026
78e772c
DLL placement: the prepare stamps are inputs, and an earlier placemen…
speak-agent Sep 26, 2026
9e8f283
docs: SPEC-007 v0.2 marks the implemented rules; docs/04 §2.11 states…
speak-agent Sep 26, 2026
1c625eb
ci: the llvm job asserts the compile-database e2e (783-786); the ming…
speak-agent Sep 26, 2026
5c2ddb6
2026.9.26.2: the version, and the CHANGELOG entry
speak-agent Sep 26, 2026
71dcfb6
docs: the design record's implementation section (revision 5), the in…
speak-agent Sep 26, 2026
de534da
tests: native spellings on Windows, the default toolchain on every pl…
speak-agent Sep 26, 2026
117cb8d
e2e 211 compares the fixture by its own name, which the 8.3 and long …
speak-agent Sep 26, 2026
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
948 changes: 948 additions & 0 deletions .agents/docs/2026-09-26-compile-database-and-issue-699-design.md

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
---
```

310 records.
311 records.

## By subject

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

### design

- [The compile database, `emit build-database`, and #701/#702: triage against the specifications, and one design](2026-09-26-compile-database-and-issue-699-design.md) — landed
- [Issues #693 to #696: triage against mcpp's contracts, and one repair plan](2026-09-25-issues-693-696-triage-and-repair-plan.md) — landed
- [Workspace inheritance, flag scoping and the published form: a unified repair plan (#690)](2026-09-25-issue-690-workspace-build-inheritance-consistency.md) — landed
- [MSVC toolset 的选择、#685、#687 与工具链管理规范:总体设计](2026-09-24-toolchain-selection-and-payload-trust-design.md) — active
Expand Down Expand Up @@ -101,6 +102,7 @@ Records that declare one. Everything else is listed by date below.

### 2026-09

- [The compile database, `emit build-database`, and #701/#702: triage against the specifications, and one design](2026-09-26-compile-database-and-issue-699-design.md) — landed
- [Issues #693 to #696: triage against mcpp's contracts, and one repair plan](2026-09-25-issues-693-696-triage-and-repair-plan.md) — landed
- [Workspace inheritance, flag scoping and the published form: a unified repair plan (#690)](2026-09-25-issue-690-workspace-build-inheritance-consistency.md) — landed
- [#690: self-review before release, engine and ecosystem](2026-09-25-issue-690-self-review.md) — landed
Expand Down
46 changes: 46 additions & 0 deletions .github/workflows/ci-linux-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -449,3 +449,49 @@ jobs:
"ok: a program over a C++ shared library runs on one C++ runtime" \
"ok: a stated self-contained program over a coupled C++ shared library is refused" \
"PASS: 700 a program over a C++ shared library has one C++ runtime"

# The compile database (#699 report, design 2026-09-26 §3): the scripts
# whose rows need llvm declare `# requires: llvm`, which no shard has, so
# they run here and each is held to the lines it prints only when the
# property it names was checked.
- name: "Compile database e2e that needs llvm (783, 784, 785, 786)"
run: |
set -o pipefail
# The scripts read the database with python3, which this container
# lacks. It is not a toolchain: the job's property (no host compiler,
# no host C runtime) was asserted before the checkout and still holds.
if ! command -v python3 >/dev/null 2>&1; then
apt-get install -y -qq python3 >/dev/null
if command -v gcc >/dev/null 2>&1; then
echo "::error::installing python3 brought a host compiler"; exit 1
fi
fi
export PATH="$HOME/.xlings/subos/current/bin:$PATH"
export MCPP
run_and_assert() { # $1 = script; the remaining arguments are lines it must print
local script="$1"; shift
local log="$RUNNER_TEMP/$(basename "$script").log"
bash "$script" 2>&1 | tee "$log"
for line in "$@"; do
grep -qxF "$line" "$log" || { echo "::error::$script did not print: $line"; exit 1; }
done
}
run_and_assert tests/e2e/783_cdb_switches_whole_with_the_configuration.sh \
"ok: mcpp test then mcpp build keep the test entry in one configuration" \
"ok: switching toolchain switches the whole root file" \
"ok: switching back restores that configuration's entries, test units included" \
"PASS: 783 one compile database per configuration"
run_and_assert tests/e2e/784_cdb_replays_from_its_directory.sh \
"ok: gcc row replays every entry from its directory, no gcm.cache/ in the project root" \
"ok: llvm row replays every entry from its directory" \
"PASS: 784 the compile database replays from its own directory"
run_and_assert tests/e2e/785_cdb_interface_flag_module_extensions.sh \
"ok: the interface entry carries -x c++-module immediately before -c, and replays" \
"ok: the non-module unit carries no language flag" \
"PASS: 785 the compile database states a module interface's language explicitly"
run_and_assert tests/e2e/786_std_unit_in_the_database_and_build_id.sh \
"ok: the std unit's directory is the shared std cache, not the project's output directory" \
"ok: emit --spec compile-commands renders the same std entry as the build's database" \
"ok: provides['std'] names the std-cache BMI" \
"ok: build-id is present and stable across two runs" \
"PASS: 786 the std unit in the database, emit/build agreement, provides and build-id"
32 changes: 32 additions & 0 deletions .github/workflows/cross-build-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,38 @@ jobs:
export MCPP_VENDORED_XLINGS="$XLINGS_BIN"
bash tests/e2e/248_pack_library_fat_pe_leg.sh

# SPEC-007 R4.3: the engine places a Windows program's runtime DLLs
# beside it after its link, so a program started by hand finds them.
# Named here for the reason the steps above are: the Linux shards skip
# `# requires: mingw-cross wine`. Each property is held to the line the
# script prints only when that property was checked.
# The runtime_search_dir directive on PE (#701): `mcpp run` finds a DLL
# through PATH and `mcpp pack` places it. The native leg is e2e 794 on
# the Windows shards; this is its Linux-hosted counterpart.
- name: "e2e: runtime_search_dir on PE under wine"
run: |
set -o pipefail
export MCPP_VENDORED_XLINGS="$XLINGS_BIN"
log="$RUNNER_TEMP/796.log"
bash tests/e2e/796_runtime_search_dir_on_pe_under_wine.sh 2>&1 | tee "$log"
grep -qxF "PASS: 796_runtime_search_dir_on_pe_under_wine" "$log" \
|| { echo "::error::796 did not print its PASS line"; exit 1; }

- name: "e2e: a Windows program finds its runtime DLLs beside it"
run: |
set -o pipefail
export MCPP_VENDORED_XLINGS="$XLINGS_BIN"
log="$RUNNER_TEMP/797.log"
bash tests/e2e/797_a_windows_program_finds_its_dlls_beside_it.sh 2>&1 | tee "$log"
for line in \
" ok: after the first build the program started by hand finds its DLL" \
" ok: a build with nothing changed neither relinks nor places again" \
" ok: a DLL replaced in its directory replaces the copy" \
" ok: no system DLL is copied" \
"PASS: a Windows program finds its runtime DLLs beside it"; do
grep -qxF "$line" "$log" || { echo "::error::797 did not print: $line"; exit 1; }
done

# ── windows → linux ───────────────────────────────────────────────────────
# The mirror of mingw-cross-wine. Two jobs because a Windows runner cannot
# execute the ELF it produces; the artefact is handed to a Linux job and
Expand Down
79 changes: 79 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,85 @@
> 本文件追踪 `mcpp-community/mcpp` 公开仓的版本演进。
> 格式参考 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/)。

## [2026.9.26.2] - 2026-09-26

### 编译数据库:一个配置一个数据库(#699 的报告;#397 C-1、#677 B1)

`compile_commands.json` 此前是一份跨命令、跨工具链合并的文件:删除后的下一次构建不再写回它,
另一个工具写入的条目与上一个工具链的条目都被保留,`directory` 写的是工程根目录而编译器在输出目录
中运行。现在:

- 每个配置一份数据库,位于 `target/<triple>/<fingerprint>/compile_commands.json`,只在本配置之内
合并,因此 `mcpp test` 之后的 `mcpp build` 保留测试单元的条目。工程根目录的文件是当前配置数据库
的副本,整体替换、从不合并,内容相同时不写;切换工具链或 profile 就切换整个文件,切回时恢复该
配置的条目。根目录的符号链接照旧按其指向写入。
- 根文件被删除后,下一次构建从配置数据库恢复它,快路径也是如此,不需要规划。
- 被替换的根文件含有 mcpp 没有写的条目时(条目的 `output` 不在本工程的 `target/` 或 mcpp 主目录
之下),构建以一条警告说明其数量。
- `directory` 与 S1 的 `work-directory` 是编译器运行的输出目录,与 JSON Compilation Database 格式、
S1-8-2 以及 CMake、ninja 的写法一致;从 `directory` 重放 GCC 的条目不再在源码树中写出
`gcm.cache/`。
- 提供模块的单元在 `-c` 之前带上接口语言 flag(clang 为 `-x c++-module`,GCC 为 `-x c++`),
clangd 因此能处理 `.ixx` 接口;MSVC 的写法待 Windows 实测后再加。
- 导入 `std` 的构建在 `compile_commands.json` 与 `emit --spec compile-commands` 中列出标准库单元
(S1-12-1),另一个版本的 clangd 因此能自己构建 `std`。S1 文档中标准库单元的 `provides` 指向
共享 std 缓存中的 BMI,工具链带 `build-id`,版本与构建身份完全一致的读者可以直接复用。
- `mcpp new` 写出的 `.gitignore` 包含 `compile_commands.json`。

### `emit build-database` 按成员规划(#699)

`emit build-database --workspace` 此前在第一个规划失败的成员处停止,已规划成员的集合全部丢失。
现在每个选中的成员独立规划:规划失败的成员不贡献集合,贡献一条 `error` 诊断,`path` 为它的
`mcpp.toml`;至少一个成员规划成功时文档带 `data`,`watch` 也列出失败成员的 `mcpp.toml` 与
`build.mcpp`;有任何错误时退出码为 1。在 `emit` 下,构建失败的宿主工具是警告
`MCPP_BUILD_DATABASE_HOST_TOOL_UNBUILT`,规划继续,构建程序得到该工具将被发布的路径;构建程序失败
的包不带该程序的指令地被描述,并得到一条 `MCPP_BUILD_DATABASE_PROGRAM_FAILED` 错误,`path` 为它的
`build.mcpp`。`mcpp build` 的行为不变。带错误诊断的 `data` 是 S2 0.3.0 的部分回答
(Sunrisepeak/mcpp-language-server#25)。

### 构建程序:`runtime_search_dir`、`prepare` 角色与 stamp 规则(#701、#702)

- `mcpp::runtime_search_dir(dir)`(`mcpp:runtime-search-dir=`,协议 12)是 `[runtime]
runtime_search_dirs` 的构建程序形态,并入同一个字段:ELF 与 Mach-O 的运行路径、`mcpp run` 的加载
路径、`mcpp pack` 的闭包搜索与运行时校验都照常读取它,依赖的声明到达消费方的可执行文件。目录在
构建程序运行时不必存在。保留字段 `[runtime] library_dirs` 不获得指令。
- 新角色 `prepare` 用于文件名在构建程序运行时未知的施工(安装一个前缀、解开一个 SDK):命令填充
用 `a.output_dir(dir)` 声明的目录,引擎写 stamp。命令成功而目录不存在或除 stamp 外不含文件时,
这条边失败并点名目录。声明包的每条编译边与计划中的每条链接边等待它,构建输出以 `PREPARE`
标注。构建程序的重新运行依据落在某个 `prepare` 目录内时,构建给出警告。
- 角色以常量书写:`mcpp::roles::{source, check, object, artifact, prepare}`。引擎拒绝这五个之外的
角色字符串并列出它们;此前未知的字符串被静默读作 `source`。
- `check` 与 `prepare` 的命令成功后,引擎创建缺失的 stamp,并把已存在的 stamp 更新到当前时间;
此前已存在的 stamp 不被更新,一个输入改变一次之后,该 action 在此后每次构建中都会重新运行。

### Windows 程序的 DLL 在链接后放到程序旁

PE 映像没有运行路径,运行时搜索目录中的 DLL 此前只服务于 `mcpp run` 与 `mcpp pack`,从构建目录直接
启动的程序找不到它。现在计划中带运行时搜索目录的 PE 程序在链接后多一条边 `mcpp place-dlls`:按
`mcpp pack` 的闭包求解与系统规则,把程序直接或间接导入、且在这些目录中解析到的 DLL 放到程序旁,
字节不同时才写;DLL 在其目录中被替换(包括被 `prepare` action 替换)后,同一次构建会再次放置它。
部署到程序旁的 DLL 从链接边的隐式输入改为 order-only 输入,DLL 变化不再使程序重新链接。

### 链接 flag 按词读取(#703)

`[build] ldflags`、`mcpp::link_flag` 与依赖传播的链接 flag 此前只为 ninja 转义,Linux 与 macOS 的
`sh` 展开其中的 `$ORIGIN`,程序的运行路径因此含有 `/../lib`,即宿主的 `/lib`。SPEC-004 §8 的词读法
现在同样适用于链接 flag:每个词原样到达链接器;依赖的链接 flag 按词传播;`link_search`、`link_lib`、
`link_script` 由路径构成的值是一个词,含空格的目录不再被拆开。为 shell 或 ninja 手工转义的写法
(`\$ORIGIN`、`'$$ORIGIN'`)现在按写法读取,首次规划以 `build/flag-words` 指出这样的元素;
索引中没有这样的写法。

### 构建插件规范 SPEC-007

新增 `docs/specs/build-plugins.md`(草案 0.2):插件的配置、施工与校验各用一种机制,环境不完整时
警告而不失败,配置不依赖施工结果,运行时库以 `runtime_search_dir` 声明,构建期的网络访问在离线
构建中不发生。mcpp 只提供通用机制,某一个工具的知识只属于它的插件。

### 兼容性

- 构建程序缓存的 epoch 升到 3,升级后每个构建程序重新运行一次。
- 构建程序协议升到 12;使用新指令、新角色或角色常量的构建程序在旧引擎上编译失败并指出名字。

## [2026.9.26.1] - 2026-09-26

### 路径与文本统一为 UTF-8(#693)
Expand Down
25 changes: 25 additions & 0 deletions docs/01-getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,31 @@ Run it only in a trusted workspace. The process exit code and the resulting
`compile_commands.json` are the stable integration contract; stdout remains
human-readable.

`compile_commands.json` at the project root is a copy of the current
configuration's own database, written at
`target/<triple>/<fingerprint>/compile_commands.json` — the directory the
toolchain, target, profile and features together name, and the directory the
compiler actually runs in. Every command that plans in that configuration
(`build`, `test`, `run`, `--configure-only`) merges its fresh plan into that
one file, so a unit `mcpp test` added stays listed after a plain `mcpp
build`. The root copy is never merged: it is replaced whole with the
configuration's file, and left untouched when the two already agree, so
switching `--toolchain` or `--profile` switches the whole root file and
switching back restores that configuration's entries, test units included. A
symlink at the project root is followed, and the copy lands at its target.
When the replaced root file held entries mcpp did not write, one warning
states how many; the file then holds this project's own configuration.
Deleting the root file is not a way to reset it: the next build (even one
that finds nothing to recompile) restores it from the configuration's
database.

A project that imports `std` also finds an entry for the toolchain's
standard-library units, in both `compile_commands.json` and the S1 document
`emit build-database` prints — see below. Because a BMI is readable only by
the compiler that built it, listing the unit lets a reader whose toolchain
differs from the one mcpp built with compile its own copy of `std` instead of
failing on a version mismatch.

An editor that must not write into the project asks for the same plan on stdout
*(mcpp 2026.9.15.1+)*:

Expand Down
Loading
Loading