Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
85c9037
Fix #704 #705 #707 #708 #710 #712 #713 #714 #715 #716
claude Sep 26, 2026
aac072c
Add feature tools (#709) and target artifact dependencies (#711)
claude Sep 27, 2026
c136000
Consume the xlings revision and glibc runtime data
claude Sep 27, 2026
bba733a
2026.9.27.1: tests, specs and docs for #704-#716; xlings version vect…
claude Sep 27, 2026
6b6cfbd
2026.9.27.1: e2e 804 for a path host tool's toolchain (#710); e2e 802…
speak-agent Sep 27, 2026
af4c96f
#708: an action's cwd is a plain absolute path on Windows
speak-agent Sep 27, 2026
290bb46
test_workspace_inheritance: compare the #710 toolchain through its value
speak-agent Sep 27, 2026
16c9b67
2026.9.27.1: pin xlings 2026.9.27.1
speak-agent Sep 27, 2026
d921327
prepare.cppm: introduce PrepareState carrying prepare_build's parameters
speak-agent Sep 27, 2026
67b9503
prepare.cppm: promote P0's manifest/workspace locals into PrepareState
speak-agent Sep 27, 2026
2e680c6
prepare.cppm: extract P1 (toolchain spec + target axis) as a phase fu…
speak-agent Sep 27, 2026
76ac9b2
prepare.cppm: extract P2 (toolchain resolver definition) as a phase f…
speak-agent Sep 27, 2026
e3b983c
prepare.cppm: extract P3 (xlings payload before the graph) as a phase…
speak-agent Sep 27, 2026
9260c46
prepare.cppm: fix prose broken by the P0/step-1 renames
speak-agent Sep 27, 2026
936643e
prepare.cppm: extract P4 (the dependency graph) as a phase function
speak-agent Sep 27, 2026
38b1ea5
prepare.cppm: extract P5 (toolchain decision after the graph) as a ph…
speak-agent Sep 27, 2026
5a8e952
prepare.cppm: fix three /* name=*/ argument comments broken by the fi…
speak-agent Sep 27, 2026
34d54ff
prepare.cppm: extract P6-P8 (features, capabilities, target side, host
speak-agent Sep 27, 2026
1a49e25
prepare.cppm: extract P9-P12 (target side, linkage form, scan, finger…
speak-agent Sep 27, 2026
d8447f5
prepare.cppm: extract P13 (BuildContext population) and, finally, P0
speak-agent Sep 27, 2026
e4544f1
prepare.cppm: promote P4's graph-loading half for a future graph_load…
speak-agent Sep 27, 2026
f748c83
prepare.cppm: split phase4 into phase4a_graph_load + phase4b_graph_wo…
speak-agent Sep 27, 2026
827ddf9
prepare.cppm: split phase9 into phase9_target_side + phase11_scan
speak-agent Sep 27, 2026
a65a52c
prepare.cppm: un-anonymize the preamble helpers ahead of the file split
speak-agent Sep 27, 2026
960f0b2
prepare.cppm: split into the primary interface and thirteen implement…
speak-agent Sep 27, 2026
a203bdb
prepare.cppm: add the file-length CI gate and the CHANGELOG entry
speak-agent Sep 27, 2026
3f802e0
state.cppm: restore PrepareState's doc comment, fix a stale one
speak-agent Sep 27, 2026
d0d7bc2
prepare.cppm: the primary interface holds declarations only
speak-agent Sep 27, 2026
1a22790
tests: unit tests for the helpers prepare_build's phases share
speak-agent Sep 27, 2026
5ead2d0
prepare: file headers, phase declarations in order, an accurate layou…
speak-agent Sep 27, 2026
a9ce4a3
prepare: each unit imports what it uses
speak-agent Sep 27, 2026
f582a6c
CHANGELOG: the prepare.cppm decomposition as it landed
speak-agent Sep 27, 2026
bc0527b
prepare: two comments describe the code rather than the refactoring t…
speak-agent Sep 27, 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
2 changes: 1 addition & 1 deletion .github/actions/bootstrap-mcpp/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ inputs:
# `package.name`, so one of the two was simply unreachable — and which one
# depended on the machine, which is why CI failed on `compat:lua` on
# Windows and `mcpplibs.capi:lua` on Linux. Never pin below that.
default: '2026.9.26.2'
default: '2026.9.27.1'
cache-target:
description: also restore/save target/ (build artifacts + BMIs)
required: false
Expand Down
2 changes: 1 addition & 1 deletion .github/actions/setup-macos-llvm/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ inputs:
# Floor imposed by the index, not a routine bump — see
# .github/actions/bootstrap-mcpp/action.yml for why 0.4.69 is required
# (two packages named `lua` in one repo need openxlings/xlings#381).
default: '2026.9.26.2'
default: '2026.9.27.1'
image:
description: >
The runner label the job runs on (macos-15, xcode-27). It is part of the
Expand Down
76 changes: 76 additions & 0 deletions .github/tools/check_file_lengths.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#!/usr/bin/env bash
#
# Guard: no file under the prepare.cppm decomposition grows past 2,500 lines.
#
# WHY
#
# prepare.cppm was 16,105 lines: one exported function, prepare_build, ~85%
# of the file, ~180 top-level locals sharing a stack frame. It was split into
# a primary interface (src/build/prepare.cppm) holding declarations, an
# implementation partition (src/build/prepare/state.cppm) and implementation
# units, each phase a function taking PrepareState& instead of closing over
# the old locals directly -- see the layout comment at the top of
# prepare.cppm, and mcpp-community/mcpp#721 for the GCC 16.1 constraint that
# shapes it.
#
# A size cap with no gate is a target nobody re-checks. The decomposition's
# whole point was to keep any one file's compile from blocking on the rest —
# a phase file that quietly grows back to several thousand lines is the same
# defect it fixed, arrived at one small commit at a time. This fails the
# build the day that happens, at the commit that did it, rather than leaving
# it for the next person who tries to read the file.
#
# THE RULE
#
# Every file directly under src/build/prepare/, plus src/build/prepare.cppm
# itself, stays at or under 2,500 lines. There is no per-file waiver: a file
# that needs one is a file that needs splitting the way graph.cpp/graph_load.cpp
# and toolchain.cpp/toolchain_decision.cpp already were.
#
# Usage: bash .github/tools/check_file_lengths.sh [repo_dir]

set -uo pipefail

REPO_DIR="${1:-$(pwd)}"
cd "$REPO_DIR" || { echo "FAIL: cannot cd to $REPO_DIR" >&2; exit 1; }

LIMIT=2500
PRIMARY="src/build/prepare.cppm"
DIR="src/build/prepare"

[ -f "$PRIMARY" ] || { echo "FAIL: $PRIMARY does not exist — this guard has gone stale" >&2; exit 1; }
[ -d "$DIR" ] || { echo "FAIL: $DIR does not exist — this guard has gone stale" >&2; exit 1; }

fail=0
checked=0

check_one() {
file="$1"
n=$(wc -l < "$file")
checked=$((checked + 1))
if [ "$n" -gt "$LIMIT" ]; then
echo "FAIL: $file is $n lines (limit $LIMIT)" >&2
fail=1
fi
}

check_one "$PRIMARY"
while IFS= read -r f; do
check_one "$f"
done < <(find "$DIR" -maxdepth 1 -type f \( -name '*.cppm' -o -name '*.cpp' \) | sort)

if [ "$fail" = 1 ]; then
cat >&2 <<EOF

A file over the limit needs splitting, not a raised limit: cut it at a
phase boundary (see the layout comment at the top of $PRIMARY) the way
P4 (graph_load.cpp/graph.cpp) and P1+P2+P5 (toolchain.cpp/
toolchain_decision.cpp) already were. A phase whose closures escape into a
later phase needs its captures promoted to PrepareState members first —
see state.cppm's own comments for the pattern.
EOF
exit 1
fi

echo "ok: $checked file(s) under $PRIMARY / $DIR/, all at or under $LIMIT lines"
exit 0
2 changes: 1 addition & 1 deletion .github/workflows/bootstrap-macos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
# Dormant (workflow_dispatch only), but kept in step with the rest —
# check_version_pins.sh holds it there. Floor: 0.4.69, below which the
# index cannot resolve two packages that share a short name.
XLINGS_VERSION: '2026.9.26.2'
XLINGS_VERSION: '2026.9.27.1'
steps:
- uses: actions/checkout@v4

Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/ci-fresh-install.yml
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ jobs:
env:
XLINGS_NON_INTERACTIVE: '1'
run: |
curl -fsSL https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh | bash -s v2026.9.26.2
curl -fsSL https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh | bash -s v2026.9.27.1
echo "$HOME/.xlings/subos/current/bin" >> "$GITHUB_PATH"

- name: Install mcpp and config mirror
Expand Down Expand Up @@ -312,7 +312,7 @@ jobs:

- name: Install xlings + mcpp
run: |
curl -fsSL https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh | bash -s v2026.9.26.2
curl -fsSL https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh | bash -s v2026.9.27.1
# Deliberately NOT writing to $GITHUB_PATH here. On container
# images that declare no PATH in their config (opensuse/
# tumbleweed), appending a single dir to GITHUB_PATH makes the
Expand Down Expand Up @@ -403,7 +403,7 @@ jobs:
# (older ones carry minos=15 and refuse to start).
# v0.4.51+: in-process sha256 — this image has no sha256sum
# binary, so pinned fetches failed before it.
curl -fsSL https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh | bash -s v2026.9.26.2
curl -fsSL https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh | bash -s v2026.9.27.1
echo "$HOME/.xlings/subos/current/bin" >> "$GITHUB_PATH"

- name: Install mcpp and config mirror
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci-linux-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,7 @@ jobs:

- name: Bootstrap xlings + released mcpp
run: |
curl -fsSL https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh | bash -s v2026.9.26.2
curl -fsSL https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh | bash -s v2026.9.27.1
export PATH="$HOME/.xlings/subos/current/bin:$PATH"
xlings update
xlings install mcpp -y -g
Expand Down
6 changes: 6 additions & 0 deletions .github/workflows/ci-linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,12 @@ jobs:
- name: Check modules/ wiring
run: bash .github/tools/check_modules_wiring.sh

# Same placement, same reason: pure text, no toolchain, under a second.
# Catches the prepare.cppm decomposition growing back into one huge
# file one commit at a time — see the script's header.
- name: Check src/build/prepare* file lengths
run: bash .github/tools/check_file_lengths.sh

# Same placement, same reason: pure text, no toolchain, under a second.
#
# This one is a HARD gate (unlike lint-ci-assertions.sh below) because it
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/cross-build-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ jobs:
# release assets were uploaded in a broken state (records present,
# blobs missing → 404 on GET); re-uploaded clean. The stale-INDEX
# half is handled by the marker-clear below.
XLINGS_VERSION: '2026.9.26.2'
XLINGS_VERSION: '2026.9.27.1'
run: |
tarball="xlings-${XLINGS_VERSION}-linux-x86_64.tar.gz"
bash "$GITHUB_WORKSPACE/.github/tools/fetch_release.sh" \
Expand Down Expand Up @@ -289,7 +289,7 @@ jobs:
- name: Bootstrap mcpp via xlings
env:
XLINGS_NON_INTERACTIVE: '1'
XLINGS_VERSION: '2026.9.26.2'
XLINGS_VERSION: '2026.9.27.1'
run: |
tarball="xlings-${XLINGS_VERSION}-linux-x86_64.tar.gz"
bash "$GITHUB_WORKSPACE/.github/tools/fetch_release.sh" \
Expand Down
14 changes: 7 additions & 7 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ jobs:
# Pin xlings to a known-good version. The upstream install
# script always grabs `latest` (no version override), so we
# download + self-install manually to avoid broken releases.
XLINGS_VERSION: '2026.9.26.2'
XLINGS_VERSION: '2026.9.27.1'
run: |
if [ ! -x "$HOME/.xlings/subos/default/bin/xlings" ]; then
tarball="xlings-${XLINGS_VERSION}-linux-x86_64.tar.gz"
Expand Down Expand Up @@ -314,7 +314,7 @@ jobs:
- name: Bootstrap mcpp via xlings
env:
XLINGS_NON_INTERACTIVE: '1'
XLINGS_VERSION: '2026.9.26.2'
XLINGS_VERSION: '2026.9.27.1'
run: |
tarball="xlings-${XLINGS_VERSION}-linux-x86_64.tar.gz"
bash "$GITHUB_WORKSPACE/.github/tools/fetch_release.sh" \
Expand Down Expand Up @@ -385,7 +385,7 @@ jobs:
# below are pinned to the same version as XLINGS_VERSION; they are
# NOT interpolated from it, so check_version_pins.sh scans for them
# explicitly (they were absent from the old lock-step comment).
XLA="xlings-2026.9.26.2-linux-aarch64.tar.gz"
XLA="xlings-2026.9.27.1-linux-aarch64.tar.gz"
# NOT fetch_release.sh: this asset is OPTIONAL and the `if` is the
# point — an arch with no prebuilt xlings must fall through quietly,
# while the helper retries a 404 five times before giving up. The one
Expand All @@ -394,9 +394,9 @@ jobs:
# cover it.
if curl -fsSL --retry 3 --retry-delay 2 --retry-all-errors \
--connect-timeout 20 --max-time 600 -o "/tmp/$XLA" \
"https://github.com/openxlings/xlings/releases/download/v2026.9.26.2/$XLA"; then
"https://github.com/openxlings/xlings/releases/download/v2026.9.27.1/$XLA"; then
tar -xzf "/tmp/$XLA" -C /tmp
XLBIN=$(find /tmp/xlings-2026.9.26.2-linux-aarch64 -path '*/bin/xlings' -type f | head -1)
XLBIN=$(find /tmp/xlings-2026.9.27.1-linux-aarch64 -path '*/bin/xlings' -type f | head -1)
if [ -n "$XLBIN" ]; then
mkdir -p "$STAGING/$WRAPPER/registry/bin"
cp "$XLBIN" "$STAGING/$WRAPPER/registry/bin/xlings"
Expand Down Expand Up @@ -474,7 +474,7 @@ jobs:
- name: Bootstrap mcpp via xlings
env:
XLINGS_NON_INTERACTIVE: '1'
XLINGS_VERSION: '2026.9.26.2'
XLINGS_VERSION: '2026.9.27.1'
run: |
if [ ! -x "$HOME/.xlings/subos/default/bin/xlings" ]; then
WORK=$(mktemp -d)
Expand Down Expand Up @@ -657,7 +657,7 @@ jobs:
shell: bash
env:
XLINGS_NON_INTERACTIVE: '1'
XLINGS_VERSION: '2026.9.26.2'
XLINGS_VERSION: '2026.9.27.1'
run: |
# Captured before the `cd` below, in POSIX form: this step never
# returns to the workspace, and GITHUB_WORKSPACE is a backslash
Expand Down
75 changes: 75 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,81 @@
> 本文件追踪 `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 的版本文法求值,
`[email protected]` 回答 `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`(用户已设置时保留用户的值)。

### 兼容性

以下变化对已有工程可见:

- 未解析的 `workspace = true` 此前静默成为空版本依赖,现在在加载时报错并点名条目(#714)。
修正方法是在工作空间根的 `[workspace.dependencies]` 中声明该包,或在条目上写明版本。
- `[build] sources = []` 不再推断库目标。依赖这一推断的包在 `[targets]` 中声明库目标。
- note 代码 `MCPP_BUILD_DATABASE_HOST_TOOL_UNBUILT` 由 `MCPP_BUILD_DATABASE_HOST_TOOL_DEFERRED`
取代,不保留旧代码。

### 其他

- 测试:e2e 804 覆盖不属于任何工作空间的路径宿主工具包的工具链选择(#710);e2e 802 固定 gcc
工具链,使其断言不依赖机器的默认工具链;单元测试 `test_prepare_helpers` 覆盖各阶段共用的纯函数
(`--features` 请求语法、宏名、git 远端是否本地等)。
- ELF 检查以一次读取载入文件。此前逐字节读入,`mcpp test` 的链接后检查在测试程序较多时耗时
数十分钟。
- **`src/build/prepare.cppm` 的内部分解。** 原文件 16,105 行,其中函数 `prepare_build` 占 85%。
它拆为按阶段划分的函数,跨阶段的状态集中在 `PrepareState`(取代原来约 180 个共用一个栈帧的
局部变量)。主接口 `prepare.cppm` 只保留导出的类型、内联函数与声明;实现位于 `src/build/prepare/` 下的
实现单元与实现分区 `:state`,各单元只导入自己用到的模块,每个文件不超过 2,500 行,由 CI 检查。
代码逐段移动,不重排语句;公开接口、导出符号与默认参数不变,七个场景的规划输出与分解前逐字节
一致。修改一个阶段只重新编译该实现单元:本机修改 P13 中的一处字符串,增量构建 12 s,分解前
71 s。模块组织受 GCC 16.1 的内部编译器错误约束,见 #721。
- 规范: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
Loading
Loading