Skip to content

Commit b439fd9

Browse files
authored
2026.9.27.1: #704-#716 fixed, feature tools, artifacts edges, payload revisions and glibc locale data, prepare.cppm decomposed (#719)
Fixes #704, #705, #707, #708, #709, #710, #711, #712, #713, #714, #715 and #716 are verified after release in an xlings subos sandbox before the issues are closed. See CHANGELOG.md for 2026.9.27.1.
1 parent 52549fb commit b439fd9

80 files changed

Lines changed: 19903 additions & 15413 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.github/actions/bootstrap-mcpp/action.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ inputs:
2525
# `package.name`, so one of the two was simply unreachable — and which one
2626
# depended on the machine, which is why CI failed on `compat:lua` on
2727
# Windows and `mcpplibs.capi:lua` on Linux. Never pin below that.
28-
default: '2026.9.26.2'
28+
default: '2026.9.27.1'
2929
cache-target:
3030
description: also restore/save target/ (build artifacts + BMIs)
3131
required: false

‎.github/actions/setup-macos-llvm/action.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ inputs:
1515
# Floor imposed by the index, not a routine bump — see
1616
# .github/actions/bootstrap-mcpp/action.yml for why 0.4.69 is required
1717
# (two packages named `lua` in one repo need openxlings/xlings#381).
18-
default: '2026.9.26.2'
18+
default: '2026.9.27.1'
1919
image:
2020
description: >
2121
The runner label the job runs on (macos-15, xcode-27). It is part of the
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
#!/usr/bin/env bash
2+
#
3+
# Guard: no file under the prepare.cppm decomposition grows past 2,500 lines.
4+
#
5+
# WHY
6+
#
7+
# prepare.cppm was 16,105 lines: one exported function, prepare_build, ~85%
8+
# of the file, ~180 top-level locals sharing a stack frame. It was split into
9+
# a primary interface (src/build/prepare.cppm) holding declarations, an
10+
# implementation partition (src/build/prepare/state.cppm) and implementation
11+
# units, each phase a function taking PrepareState& instead of closing over
12+
# the old locals directly -- see the layout comment at the top of
13+
# prepare.cppm, and mcpp-community/mcpp#721 for the GCC 16.1 constraint that
14+
# shapes it.
15+
#
16+
# A size cap with no gate is a target nobody re-checks. The decomposition's
17+
# whole point was to keep any one file's compile from blocking on the rest —
18+
# a phase file that quietly grows back to several thousand lines is the same
19+
# defect it fixed, arrived at one small commit at a time. This fails the
20+
# build the day that happens, at the commit that did it, rather than leaving
21+
# it for the next person who tries to read the file.
22+
#
23+
# THE RULE
24+
#
25+
# Every file directly under src/build/prepare/, plus src/build/prepare.cppm
26+
# itself, stays at or under 2,500 lines. There is no per-file waiver: a file
27+
# that needs one is a file that needs splitting the way graph.cpp/graph_load.cpp
28+
# and toolchain.cpp/toolchain_decision.cpp already were.
29+
#
30+
# Usage: bash .github/tools/check_file_lengths.sh [repo_dir]
31+
32+
set -uo pipefail
33+
34+
REPO_DIR="${1:-$(pwd)}"
35+
cd "$REPO_DIR" || { echo "FAIL: cannot cd to $REPO_DIR" >&2; exit 1; }
36+
37+
LIMIT=2500
38+
PRIMARY="src/build/prepare.cppm"
39+
DIR="src/build/prepare"
40+
41+
[ -f "$PRIMARY" ] || { echo "FAIL: $PRIMARY does not exist — this guard has gone stale" >&2; exit 1; }
42+
[ -d "$DIR" ] || { echo "FAIL: $DIR does not exist — this guard has gone stale" >&2; exit 1; }
43+
44+
fail=0
45+
checked=0
46+
47+
check_one() {
48+
file="$1"
49+
n=$(wc -l < "$file")
50+
checked=$((checked + 1))
51+
if [ "$n" -gt "$LIMIT" ]; then
52+
echo "FAIL: $file is $n lines (limit $LIMIT)" >&2
53+
fail=1
54+
fi
55+
}
56+
57+
check_one "$PRIMARY"
58+
while IFS= read -r f; do
59+
check_one "$f"
60+
done < <(find "$DIR" -maxdepth 1 -type f \( -name '*.cppm' -o -name '*.cpp' \) | sort)
61+
62+
if [ "$fail" = 1 ]; then
63+
cat >&2 <<EOF
64+
65+
A file over the limit needs splitting, not a raised limit: cut it at a
66+
phase boundary (see the layout comment at the top of $PRIMARY) the way
67+
P4 (graph_load.cpp/graph.cpp) and P1+P2+P5 (toolchain.cpp/
68+
toolchain_decision.cpp) already were. A phase whose closures escape into a
69+
later phase needs its captures promoted to PrepareState members first —
70+
see state.cppm's own comments for the pattern.
71+
EOF
72+
exit 1
73+
fi
74+
75+
echo "ok: $checked file(s) under $PRIMARY / $DIR/, all at or under $LIMIT lines"
76+
exit 0

‎.github/workflows/bootstrap-macos.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ jobs:
1717
# Dormant (workflow_dispatch only), but kept in step with the rest —
1818
# check_version_pins.sh holds it there. Floor: 0.4.69, below which the
1919
# index cannot resolve two packages that share a short name.
20-
XLINGS_VERSION: '2026.9.26.2'
20+
XLINGS_VERSION: '2026.9.27.1'
2121
steps:
2222
- uses: actions/checkout@v4
2323

‎.github/workflows/ci-fresh-install.yml‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ jobs:
152152
env:
153153
XLINGS_NON_INTERACTIVE: '1'
154154
run: |
155-
curl -fsSL https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh | bash -s v2026.9.26.2
155+
curl -fsSL https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh | bash -s v2026.9.27.1
156156
echo "$HOME/.xlings/subos/current/bin" >> "$GITHUB_PATH"
157157
158158
- name: Install mcpp and config mirror
@@ -312,7 +312,7 @@ jobs:
312312

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

‎.github/workflows/ci-linux-e2e.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,7 @@ jobs:
384384
385385
- name: Bootstrap xlings + released mcpp
386386
run: |
387-
curl -fsSL https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh | bash -s v2026.9.26.2
387+
curl -fsSL https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh | bash -s v2026.9.27.1
388388
export PATH="$HOME/.xlings/subos/current/bin:$PATH"
389389
xlings update
390390
xlings install mcpp -y -g

‎.github/workflows/ci-linux.yml‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,12 @@ jobs:
6262
- name: Check modules/ wiring
6363
run: bash .github/tools/check_modules_wiring.sh
6464

65+
# Same placement, same reason: pure text, no toolchain, under a second.
66+
# Catches the prepare.cppm decomposition growing back into one huge
67+
# file one commit at a time — see the script's header.
68+
- name: Check src/build/prepare* file lengths
69+
run: bash .github/tools/check_file_lengths.sh
70+
6571
# Same placement, same reason: pure text, no toolchain, under a second.
6672
#
6773
# This one is a HARD gate (unlike lint-ci-assertions.sh below) because it

‎.github/workflows/cross-build-test.yml‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ jobs:
135135
# release assets were uploaded in a broken state (records present,
136136
# blobs missing → 404 on GET); re-uploaded clean. The stale-INDEX
137137
# half is handled by the marker-clear below.
138-
XLINGS_VERSION: '2026.9.26.2'
138+
XLINGS_VERSION: '2026.9.27.1'
139139
run: |
140140
tarball="xlings-${XLINGS_VERSION}-linux-x86_64.tar.gz"
141141
bash "$GITHUB_WORKSPACE/.github/tools/fetch_release.sh" \
@@ -289,7 +289,7 @@ jobs:
289289
- name: Bootstrap mcpp via xlings
290290
env:
291291
XLINGS_NON_INTERACTIVE: '1'
292-
XLINGS_VERSION: '2026.9.26.2'
292+
XLINGS_VERSION: '2026.9.27.1'
293293
run: |
294294
tarball="xlings-${XLINGS_VERSION}-linux-x86_64.tar.gz"
295295
bash "$GITHUB_WORKSPACE/.github/tools/fetch_release.sh" \

‎.github/workflows/release.yml‎

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ jobs:
9696
# Pin xlings to a known-good version. The upstream install
9797
# script always grabs `latest` (no version override), so we
9898
# download + self-install manually to avoid broken releases.
99-
XLINGS_VERSION: '2026.9.26.2'
99+
XLINGS_VERSION: '2026.9.27.1'
100100
run: |
101101
if [ ! -x "$HOME/.xlings/subos/default/bin/xlings" ]; then
102102
tarball="xlings-${XLINGS_VERSION}-linux-x86_64.tar.gz"
@@ -314,7 +314,7 @@ jobs:
314314
- name: Bootstrap mcpp via xlings
315315
env:
316316
XLINGS_NON_INTERACTIVE: '1'
317-
XLINGS_VERSION: '2026.9.26.2'
317+
XLINGS_VERSION: '2026.9.27.1'
318318
run: |
319319
tarball="xlings-${XLINGS_VERSION}-linux-x86_64.tar.gz"
320320
bash "$GITHUB_WORKSPACE/.github/tools/fetch_release.sh" \
@@ -385,7 +385,7 @@ jobs:
385385
# below are pinned to the same version as XLINGS_VERSION; they are
386386
# NOT interpolated from it, so check_version_pins.sh scans for them
387387
# explicitly (they were absent from the old lock-step comment).
388-
XLA="xlings-2026.9.26.2-linux-aarch64.tar.gz"
388+
XLA="xlings-2026.9.27.1-linux-aarch64.tar.gz"
389389
# NOT fetch_release.sh: this asset is OPTIONAL and the `if` is the
390390
# point — an arch with no prebuilt xlings must fall through quietly,
391391
# while the helper retries a 404 five times before giving up. The one
@@ -394,9 +394,9 @@ jobs:
394394
# cover it.
395395
if curl -fsSL --retry 3 --retry-delay 2 --retry-all-errors \
396396
--connect-timeout 20 --max-time 600 -o "/tmp/$XLA" \
397-
"https://github.com/openxlings/xlings/releases/download/v2026.9.26.2/$XLA"; then
397+
"https://github.com/openxlings/xlings/releases/download/v2026.9.27.1/$XLA"; then
398398
tar -xzf "/tmp/$XLA" -C /tmp
399-
XLBIN=$(find /tmp/xlings-2026.9.26.2-linux-aarch64 -path '*/bin/xlings' -type f | head -1)
399+
XLBIN=$(find /tmp/xlings-2026.9.27.1-linux-aarch64 -path '*/bin/xlings' -type f | head -1)
400400
if [ -n "$XLBIN" ]; then
401401
mkdir -p "$STAGING/$WRAPPER/registry/bin"
402402
cp "$XLBIN" "$STAGING/$WRAPPER/registry/bin/xlings"
@@ -474,7 +474,7 @@ jobs:
474474
- name: Bootstrap mcpp via xlings
475475
env:
476476
XLINGS_NON_INTERACTIVE: '1'
477-
XLINGS_VERSION: '2026.9.26.2'
477+
XLINGS_VERSION: '2026.9.27.1'
478478
run: |
479479
if [ ! -x "$HOME/.xlings/subos/default/bin/xlings" ]; then
480480
WORK=$(mktemp -d)
@@ -657,7 +657,7 @@ jobs:
657657
shell: bash
658658
env:
659659
XLINGS_NON_INTERACTIVE: '1'
660-
XLINGS_VERSION: '2026.9.26.2'
660+
XLINGS_VERSION: '2026.9.27.1'
661661
run: |
662662
# Captured before the `cd` below, in POSIX form: this step never
663663
# returns to the workspace, and GITHUB_WORKSPACE is a backslash

‎CHANGELOG.md‎

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,81 @@
33
> 本文件追踪 `mcpp-community/mcpp` 公开仓的版本演进。
44
> 格式参考 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/)。
55

6+
## [2026.9.27.1] - 2026-09-27
7+
8+
### 缺陷修复(#704、#705、#710、#712 至 #716)
9+
10+
- **宿主构建读取宿主三元组的行(#704)。** 不带 `--target` 的构建此前不读取
11+
`[target.<宿主三元组>]`,其中的 `cxx_runtime` 没有效果。现在宿主构建应用这一行,与
12+
`--target <宿主三元组>` 相同,行的查找与拼写无关;`--toolchain` 仍优先于行的 `toolchain`
13+
(SPEC-004 §4.6)。
14+
- **`xpkg_dir` 回答 xlings 装下的载荷(#712、#716)。** 版本位按 xlings 的版本文法求值,
15+
`libglvnd@1.7` 回答 `1.7.0.1`。xlings 在 `install_targets` 事件中报告每个请求解析到的载荷,
16+
mcpp 按地址记录并优先读取。安装记录仍在而载荷已被删除时,联网构建重新安装,离线构建拒绝并
17+
点名缺失的地址;构建缓存记录读取过的载荷目录,任一目录缺失时快路径不复用缓存。mcpp 以
18+
xlings 发布的版本选择向量测试同一规则(SPEC-001 §10.1)。
19+
- **宿主工具的工具链由请求方决定一次(#710)。** 顺序为 `--toolchain`、工具包自己的声明(工作
20+
空间成员先继承根位置的键)、请求方的宿主工具链;结果传给子构建并写入工具库的键。工具包的源树
21+
摘要跳过带自己 `mcpp.toml` 的子目录,并以 UTF-8 计算路径(#705)。
22+
- **工作空间(#713、#714)。** 成员隐式继承根的 `[xlings.workspace]` 条目与条件行,自己声明的
23+
同一个包优先。未解析的 `workspace = true` 在根包、`-p` 成员与各类依赖处都被点名拒绝;带
24+
`[package]` 的工作空间根解析自己的条目。`[build] sources = []` 不再推断库目标。
25+
- **规则只经其声明的扩展名到达(#715)。** 一个规则只在包含它声明的设备源扩展名时进入包的合成
26+
构建程序;状态行只列出实际生效的规则。
27+
28+
### 规划不构建宿主工具(#707)
29+
30+
`mcpp emit build-database` 不再构建依赖提供的宿主工具。工具库中已有的工具照常使用;没有的工具被
31+
推迟,报告为 note `MCPP_BUILD_DATABASE_HOST_TOOL_DEFERRED`,请求它的构建程序收到该工具将被发布的
32+
路径。它取代 2026.9.26.2 的警告 `MCPP_BUILD_DATABASE_HOST_TOOL_UNBUILT`(SPEC-005 v1.4 R2.5)。
33+
`mcpp build` 不受影响。
34+
35+
### 构建程序与依赖边(#708、#709、#711)
36+
37+
- **action 的 `env` 与 `cwd`(协议 13,#708)。** `mcpp::action::env(name, value)` 与
38+
`cwd(dir)` 由引擎的 action 包装器应用;`cwd` 按包根解析,声明的输入、输出与 stamp 不随它
39+
移动;变量值改变时 action 重新运行。两者都未声明的 action 命令行与协议 12 逐字节相同。
40+
- **特性的 `tools`(#709)。** `[features.<f>] tools = ["<bin>"]` 陈述特性需要本包的程序在
41+
构建机器上运行;启用该特性的消费方得到该工具,与边上写 `tools` 相同。
42+
- **`artifacts` 依赖边(#711)。** `x = { path = "...", artifacts = ["<bin>"] }` 以消费方的
43+
目标与 profile 构建依赖的程序,输出到消费方的 `bin/`,不链接依赖的代码;action 以
44+
`${mcpp.artifact:<x>/<bin>}` 引用它;`mcpp pack` 把它放在程序旁(SPEC-004 §10、
45+
SPEC-007 R6.4)。
46+
47+
### 载荷的打包修订与自包含的 locale(xlings#620、#621)
48+
49+
- 依赖的索引条目的 `revision` 进入依赖完整性判断:修订号不同的已安装依赖按未安装处理。修订号
50+
大于 0 的运行时载荷进入运行时契约(`revision=<n>`),修订号变化使依赖它的产物重新链接;修订号
51+
为 0 时契约文本不变(SPEC-001 §10.2)。
52+
- `mcpp pack` 的 bundle-all 形态随 glibc 载荷复制 `lib/locale` 与 `lib/gconv`,启动脚本设置
53+
`LOCPATH` 与 `GCONV_PATH`(用户已设置时保留用户的值)。
54+
55+
### 兼容性
56+
57+
以下变化对已有工程可见:
58+
59+
- 未解析的 `workspace = true` 此前静默成为空版本依赖,现在在加载时报错并点名条目(#714)。
60+
修正方法是在工作空间根的 `[workspace.dependencies]` 中声明该包,或在条目上写明版本。
61+
- `[build] sources = []` 不再推断库目标。依赖这一推断的包在 `[targets]` 中声明库目标。
62+
- note 代码 `MCPP_BUILD_DATABASE_HOST_TOOL_UNBUILT` 由 `MCPP_BUILD_DATABASE_HOST_TOOL_DEFERRED`
63+
取代,不保留旧代码。
64+
65+
### 其他
66+
67+
- 测试:e2e 804 覆盖不属于任何工作空间的路径宿主工具包的工具链选择(#710);e2e 802 固定 gcc
68+
工具链,使其断言不依赖机器的默认工具链;单元测试 `test_prepare_helpers` 覆盖各阶段共用的纯函数
69+
(`--features` 请求语法、宏名、git 远端是否本地等)。
70+
- ELF 检查以一次读取载入文件。此前逐字节读入,`mcpp test` 的链接后检查在测试程序较多时耗时
71+
数十分钟。
72+
- **`src/build/prepare.cppm` 的内部分解。** 原文件 16,105 行,其中函数 `prepare_build` 占 85%。
73+
它拆为按阶段划分的函数,跨阶段的状态集中在 `PrepareState`(取代原来约 180 个共用一个栈帧的
74+
局部变量)。主接口 `prepare.cppm` 只保留导出的类型、内联函数与声明;实现位于 `src/build/prepare/` 下的
75+
实现单元与实现分区 `:state`,各单元只导入自己用到的模块,每个文件不超过 2,500 行,由 CI 检查。
76+
代码逐段移动,不重排语句;公开接口、导出符号与默认参数不变,七个场景的规划输出与分解前逐字节
77+
一致。修改一个阶段只重新编译该实现单元:本机修改 P13 中的一处字符串,增量构建 12 s,分解前
78+
71 s。模块组织受 GCC 16.1 的内部编译器错误约束,见 #721。
79+
- 规范:SPEC-001 v1.5、SPEC-004 v1.8、SPEC-005 v1.4、SPEC-007 v0.3。
80+
681
## [2026.9.26.2] - 2026-09-26
782

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

0 commit comments

Comments
 (0)