Skip to content

Commit f5a7742

Browse files
authored
fix: preserve image resources and stable planning inputs (2026.10.21.1)
Bind Windows resources to the package that owns each executable or shared library. Keep unchanged lockfile bytes and timestamps, propagate lock I/O errors, and exclude synthesized host outputs from build-database inputs. Document the default scanner boundary and verify visible transitive imports without introducing include-expansion compatibility. Update both documentation trees, specifications and regression coverage, and prepare release 2026.10.21.1. Closes #826 Closes #807
1 parent cdc8daa commit f5a7742

26 files changed

Lines changed: 935 additions & 50 deletions

‎.agents/docs/2026-10-21-resource-ownership-module-scan-and-lock-write-design.md‎

Lines changed: 357 additions & 0 deletions
Large diffs are not rendered by default.

‎.agents/docs/README.md‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,16 @@ superseded_by: 2026-09-07-....md # when status is superseded
1818
---
1919
```
2020

21-
334 records.
21+
335 records.
2222

2323
## By subject
2424

2525
Records that declare one. Everything else is listed by date below.
2626

27+
### build
28+
29+
- [依赖 image 的资源归属、模块扫描边界与锁文件稳定写入](2026-10-21-resource-ownership-module-scan-and-lock-write-design.md) — active
30+
2731
### build-program
2832

2933
- [构建依赖的一条管线:配置与产物两轴、包的实例、库接口、兼容系统与工作空间收尾(#797)](2026-10-11-build-dependencies-one-pipeline-design.md) — active
@@ -134,6 +138,7 @@ Records that declare one. Everything else is listed by date below.
134138

135139
### 2026-10
136140

141+
- [依赖 image 的资源归属、模块扫描边界与锁文件稳定写入](2026-10-21-resource-ownership-module-scan-and-lock-write-design.md) — active
137142
- [首次初始化、home 重定向与网络诊断优化设计](2026-10-19-first-run-home-and-network-design.md) — landed
138143
- [升级的连续性:打包修订不在使用路径上替换载荷、替换失败不拆掉可用状态、home 中的悬空记录自愈、真实的升级 lane](2026-10-17-upgrade-continuity-design.md) — active
139144
- [mcpp 对 xlings 的依赖:Provider 端口、归属与位置、上游复用、系统级安装、payload 不可变、文件系统能力与长路径(#809)](2026-10-16-xlings-provider-port-and-shared-store-design.md) — active

‎.github/tools/upgrade_lane.sh‎

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,15 +103,33 @@ new_project() { # <dir> <bin>
103103
# ── the previous release builds the home ───────────────────────────────
104104
run old-env "$W" "$OLD" self env || fail "the previous release does not start"
105105
if [ "$VARIANT" = snapshot ]; then
106+
# self env is read-only since 2026.10.19.1. Establish the old home
107+
# explicitly before replacing its index; otherwise tar's empty -C argument
108+
# leaves the live index in use and this lane never installs old packaging.
109+
run old-init "$W" "$OLD" self init || { fail "the previous release cannot initialize its home"; exit 1; }
106110
git clone -q --filter=blob:none https://github.com/openxlings/xim-pkgindex "$W/xpi" \
107111
&& git -C "$W/xpi" checkout -q "$SNAPSHOT" || { echo "::error::cannot fetch the snapshot index"; exit 1; }
108112
idx="$REG/data/xim-pkgindex"
109113
[ -d "$idx" ] || idx=$(find "$MCPP_HOME" -type d -name xim-pkgindex | head -1)
114+
[ -n "$idx" ] && [ -d "$idx/pkgs" ] \
115+
|| { fail "the previous release created no index directory"; exit 1; }
110116
find "$idx" -mindepth 1 -maxdepth 1 ! -name .xlings-index-version -exec rm -rf {} +
111-
(cd "$W/xpi" && git archive HEAD) | tar x -C "$idx"
117+
(cd "$W/xpi" && git archive HEAD) | tar x -C "$idx" \
118+
|| { fail "the snapshot index was not materialized"; exit 1; }
119+
[ -f "$idx/pkgs/l/llvm.lua" ] \
120+
|| { fail "the snapshot has no LLVM descriptor"; exit 1; }
112121
echo "llvm.lua revisions now: $(grep -o 'revision = [0-9]*' "$idx/pkgs/l/llvm.lua" | sort -u | tr '\n' ' ')"
113122
fi
114123
run old-tc "$W" "$OLD" toolchain install "$TC" || fail "the previous release cannot install $TC"
124+
if [ "$VARIANT" = snapshot ]; then
125+
"$PY" - "$REG/data/xpkgs/xim-x-llvm/23.1.3/.xpkg-install.json" <<'PY' \
126+
|| { fail "the snapshot did not install LLVM revision zero"; exit 1; }
127+
import json, sys
128+
with open(sys.argv[1]) as f:
129+
installed = json.load(f)
130+
assert installed.get("revision", 0) == 0, installed
131+
PY
132+
fi
115133
[ "$VARIANT" = orphan ] && { run old-tc-gcc "$W" "$OLD" toolchain install gcc@16.1.0 || fail "the previous release cannot install gcc"; }
116134
new_project p-old "$OLD"
117135
run old-run "$W/p-old" "$OLD" run || fail "the previous release cannot run a new project"

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,7 @@ jobs:
368368
run: |
369369
export MCPP_VENDORED_XLINGS="$XLINGS_BIN"
370370
bash tests/e2e/198_windows_resources_cross.sh
371+
bash tests/e2e/923_cross_dependency_images_keep_their_resources.sh
371372
372373
# Packaging a Windows program FROM LINUX — and this job is the only
373374
# place that can happen, for the same reason as the two above.

‎CHANGELOG.md‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,26 @@
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.10.21.1] - 2026-10-21
8+
9+
### Fixed
10+
11+
- Dependency-owned executable artifacts and shared libraries embed their own
12+
Windows resources. Resource ownership follows package identity, including
13+
targets with the same name in different packages; consumer resources no
14+
longer enter dependency images.
15+
- Repeated planning preserves the contents and modification time of unchanged
16+
lockfiles, including read-only files and either LF or CRLF line endings.
17+
Lockfile read and write failures are reported to the caller.
18+
- Build-database watch lists and input fingerprints exclude synthesized host
19+
manifests and lockfiles while retaining editable build-dependency inputs.
20+
21+
### Documentation
22+
23+
- Clarify that the default module scanner reads source files without expanding
24+
includes. Visible imports retain their transitive module mappings; no new
25+
implicit-import compatibility mode is introduced.
26+
727
## [2026.10.19.1] - 2026-10-19
828

929
### Added

‎docs/04-mcpp-toml.md‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1399,6 +1399,10 @@ set `MCPP_VERIFY_MODGRAPH=1` when generating the build.
13991399

14001400
### 2.8.4 What The Default Scanner Reads
14011401

1402+
The default scanner reads each source file without expanding `#include`. Imports
1403+
that it discovers belong in the scanned source file itself. A header containing
1404+
`import` does not add an edge to this default module graph.
1405+
14021406
The scanner answers two questions per file — what does this unit provide, and
14031407
what does it require — and nothing else decides them.
14041408

@@ -1778,6 +1782,11 @@ generates the resource script automatically.
17781782
**not** need (and cannot use) a `cfg(windows)` predicate — write it once,
17791783
unconditionally.
17801784

1785+
Resources belong to the package that owns the executable or shared library.
1786+
Dependency-owned executable artifacts and shared libraries embed their own
1787+
resources, including when built through a consumer (2026.10.21.1+). Resources
1788+
do not propagate from a static dependency to its consumer.
1789+
17811790
**The resource object is the target's.** rc.exe and llvm-rc produce a `.res`,
17821791
which carries no machine and is linked as it is. windres produces a COFF object,
17831792
which does: mcpp gives LLVM's windres the target triple and GNU windres the BFD

‎docs/05-dependencies.md‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,11 @@ package declares `[features]` but does not include the requested feature (includ
8383
the result of backend desugaring), a warning is issued by default, and an error
8484
under `mcpp build --strict`.
8585

86+
An unchanged `mcpp.lock` retains its contents and modification time when a build
87+
records the same resolution (2026.10.21.1+). LF and CRLF line endings are accepted
88+
without rewriting an otherwise identical file. This does not skip dependency
89+
resolution or change which dependencies the lock pins.
90+
8691
**Git dependencies and `mcpp.lock`**: a `tag` or `rev` already names a fixed point
8792
in history, but a `branch` moves. The first build resolves the branch to a commit
8893
and records it in `mcpp.lock`, and every later build rebuilds **that** commit — the

‎docs/specs/build-database.md‎

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44
|---|---|
55
| 规范编号 | SPEC-005 |
66
| 标题 | mcpp 输出的构建数据库:内容、取值规则与不写工程目录的保证 |
7-
| 状态 | 评审中 v1.8 |
8-
| 版本 | 1.8 |
9-
| 最后修改 | 2026-10-11 |
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;v1.7 新增的 R3.8a 为 mcpp >= 2026.9.30.2;v1.8 新增的 R3.13 为 mcpp >= 2026.10.11.1 |
7+
| 状态 | 评审中 v1.9 |
8+
| 版本 | 1.9 |
9+
| 最后修改 | 2026-10-21 |
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;v1.7 新增的 R3.8a 为 mcpp >= 2026.9.30.2;v1.8 新增的 R3.13 为 mcpp >= 2026.10.11.1;v1.9 明确的 R6.1a 为 mcpp >= 2026.10.21.1 |
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, #732, #797 |
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 |
@@ -239,6 +239,9 @@ mcpp 输出的 S1 文档满足 S1 等级 2,不输出 `ide.options`。等级 3
239239
`tests/**/*.cpp`);构建程序声明的输入文件与 glob;`$MCPP_HOME/config.toml`。位于
240240
工作区根之下的条目写成相对工作区根、以 `/` 分隔的路径或 glob;之外的条目写成绝对
241241
路径,其 glob 展开为运行时匹配到的文件。**已实现**
242+
- **R6.1a** 合成构建程序图的根与成员清单、锁文件属于规划输出,**禁止**进入 `watch`
243+
与 `inputs-fingerprint` 的文件输入集合。该图引用的真实可编辑包的清单、源文件与声明输入
244+
仍按 R6.1 监视。**已实现**(mcpp >= 2026.10.21.1,#807)
242245
- **R6.2** 不监视:环境变量,包括 `MCPP_TOOLCHAIN`、`MCPP_HOME` 与构建程序声明的
243246
环境变量;存储中的包与 git 依赖的检出,它们的版本或提交写在已监视的清单与锁中。
244247
**已实现**
@@ -261,3 +264,4 @@ mcpp 输出的 S1 文档满足 S1 等级 2,不输出 `ide.options`。等级 3
261264
| 1.6 | 2026-09-29 | 工作区按配置规划,与 `mcpp build` 相同(R2.1、R3.3、R3.4、R5.2):成员共用的包在一个配置中只描述一次;集合名的前缀由 `<成员>/` 改为只在文档描述多个配置时出现的 `<配置>/`;一个配置的规划失败时逐成员规划。R3.5:被选成员的集合按其目标给出 `ide.kind`。R4.1:同一文件与输出一条条目。 |
262265
| 1.7 | 2026-09-30 | 新增 R3.8a:同一配置中两个包提供同一个模块名时,两个单元都列出它,可能导入它的单元的 `arguments` 带有构建所用的绑定(#732)。 |
263266
| 1.8 | 2026-10-11 | 新增 R3.13:构建程序、构建程序实例的库与引擎接口以 `<包>:build`、`<包>:host`、`mcpp:core`、`mcpp:std:host` 集合描述,`ide.configuration` 为 `build-program`,只进入 S1 文档(#797)。 |
267+
| 1.9 | 2026-10-21 | R6.1a 明确合成 host 清单与锁文件不作为 watch 或 fingerprint 输入,保留可编辑依赖输入(#807)。 |

‎docs/specs/manifest-semantics.md‎

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
| **规范编号** | SPEC-004 |
66
| **标题** | `mcpp.toml` 的平面划分、条件化形状、解析轴与命名规约 |
77
| **状态** | **草案(Draft)** |
8-
| **版本** | 1.15 |
9-
| **最后修改** | 2026-10-11 |
8+
| **版本** | 1.16 |
9+
| **最后修改** | 2026-10-21 |
1010
| **最低实现版本** | 条件化形状:mcpp **2026.8.29.1**(`[target.<selector>.build-dependencies]` 起齐备);目标轴:mcpp **2026.9.6.4** |
1111
| **作者/维护** | mcpp-community |
1212
| **相关设计文档** | `.agents/docs/2026-09-07-mcpp-toml-unified-semantics-design.md`<br>`.agents/docs/2026-06-04-manifest-schema-ownership.md`<br>`.agents/docs/2026-09-03-xlings-workspace-as-the-one-table.md`<br>`.agents/docs/2026-09-25-issue-690-workspace-build-inheritance-consistency.md`<br>`.agents/docs/2026-09-27-eight-reports-by-home-and-one-optimisation-plan.md`<br>`.agents/docs/2026-10-05-std-module-pair-msvc-lto-and-export-discovery-design.md`<br>`.agents/docs/2026-10-06-windows-x86-arch-vocabulary-and-rc-follow-ups-design.md`<br>`.agents/docs/2026-10-10-one-source-one-meaning-design.md`<br>`.agents/docs/2026-10-11-build-dependencies-one-pipeline-design.md` |
@@ -707,6 +707,18 @@ mcpp 2026.10.10.1,#785、#786;第 14 至 16 条与第 13 条的依赖位置为 m
707707

708708
**状态:已实现(mcpp 2026.10.11.1,#797)。**
709709

710+
## 13. Windows 资源的归属
711+
712+
1. `[resources]` **必须**只作用于声明包自己拥有的可执行程序与共享库,包括未被直接选择、
713+
通过 `artifacts` 构建的程序以及普通依赖共享库。image 的归属按限定包身份决定,
714+
**禁止**按 target 名称推断或将根包视为所有 image 的拥有者。
715+
2. 依赖资源**禁止**传播到消费者 image。静态库没有自己的 PE image,其资源不自动合并进
716+
消费者。测试 image 只接收现有测试 manifest 规则所允许的内容。
717+
3. 声明文件的存在性校验与资源编译分开:校验对所有目标生效;编译只对 PE 目标生效。
718+
本次计划未生成的 target 不参与 image 的 manifest 冲突检查。
719+
720+
**已实现**(mcpp >= 2026.10.21.1,#826)。
721+
710722
## 变更记录
711723

712724
| 版本 | 日期 | 变更 |
@@ -727,3 +739,4 @@ mcpp 2026.10.10.1,#785、#786;第 14 至 16 条与第 13 条的依赖位置为 m
727739
| 1.13 | 2026-10-06 | mcpp 2026.10.5.3:§4.6 陈述架构段的等同拼写,`x86` 即 `i686`;`i386` 至 `i586` 不与 `i686` 相互替代。 |
728740
| 1.14 | 2026-10-10 | mcpp 2026.10.10.1(#785、#786):§2 陈述键的作用域与来源;§9 新增第 12 条前缀即语义(工作空间层 `[workspace.X]`、按键合并、W7)与第 13 条按位置读取的兼容期;第 7 条发布写出工作空间层;第 8 条改为 `[workspace.xlings]`;第 10 条按求值后的配置分组。 |
729741
| 1.15 | 2026-10-11 | mcpp 2026.10.11.1(#797):新增 §12 依赖的库与配置(两条轴、实例、一个包一个版本、按配置激活特性、`host-module` 的含义与默认值、构建程序图、构建插件、兼容读法);§9 第 13 条的移除版本改为 mcpp 2027.1,并补依赖位置;新增 §9 第 14 至 16 条(`[xlings.overrides]` 属于构建的根、`[workspace.dependencies]` 的继承、虚拟根旁的 `build.mcpp`)。 |
742+
| 1.16 | 2026-10-21 | 新增 §13,明确依赖 EXE、DLL 的资源只进入其所属包的 image,且按计划内目标校验 manifest 冲突(#826)。 |

‎docs/zh/04-mcpp-toml.md‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1305,6 +1305,9 @@ override),在生成构建时设置 `MCPP_VERIFY_MODGRAPH=1`。
13051305

13061306
### 2.8.4 默认扫描器读到的东西
13071307

1308+
默认扫描器逐个读取源文件,不展开 `#include`。需要由它发现的 import 写在被扫描的
1309+
源文件本身;头文件中的 `import` 不为默认模块图增加导入边。
1310+
13081311
扫描器为每个文件回答两个问题——这个单元提供什么、这个单元需要
13091312
什么——没有别的东西决定这两个答案。
13101313

@@ -1663,6 +1666,9 @@ icon = "assets/app.ico"
16631666
没有资源单元、没有诊断、构建逐字节相同。**不需要**(也不能用)一个
16641667
`cfg(windows)` 谓词——写一次,无条件生效即可。
16651668

1669+
资源属于拥有可执行程序或共享库的包。依赖的 executable artifact 与共享库在通过
1670+
消费者构建时也嵌入自己的资源(2026.10.21.1+)。静态依赖的资源不传播给消费者。
1671+
16661672
**资源对象属于目标。** rc.exe 与 llvm-rc 产出 `.res`,它不带机器类型,
16671673
按原样参与链接。windres 产出 COFF 对象,它带机器类型:mcpp 交给 LLVM 的
16681674
windres 目标三元组,交给 GNU windres BFD 格式名(`pe-i386`、`pe-x86-64`),

0 commit comments

Comments
 (0)