Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
90 changes: 90 additions & 0 deletions .agents/docs/2026-08-24-graph-target-side-optimization-plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -2033,3 +2033,93 @@ requires = ["mcpp:compiler=llvm"]
← 让一次构建里的 __udivti3 与其它链接不一致(mcpp#426 已论证);
为省一次打包/一层建模而牺牲语义,是本文反对的那类捷径
```

---

## 17. 实测回填 —— 落地之后,本文有哪几处是错的

本节写于 2026.8.24.3 发布之后。只记录**推翻或修正了上文判断**的部分;
按计划做成了的事不在此列,因为它们已经在代码和 docs/14、docs/15 里。

### 17.1 §11「§4.1 改动面有多大」—— 我给出的窄改法阈值定错了方向

上文要求实施前先做纯统计,并说「命中点超过 ~30 处,应改为保留自动填充
另存 `envExplicit` 布尔」。实测命中 **22 处,其中 10 处集中在 `triple.cppm`**。

按本文的规则,22 < 30,应当走「删掉自动填充」的宽改法。**而正确的做法
仍然是窄改法**,理由与命中点数量无关:`x86_64-linux-gnu` 是
`mcpp toolchain list` 打印的东西,因此也是人们照抄的东西,删掉填充会让
这个拼写变成一个**没有 C 库的三元组**。

⭐ 判据从来不是「要改多少处」,而是「哪一个是身份、哪一个是请求」。
两者都要留:规范形式当身份(输出目录、缓存键、`cfg()` 的主语),
`envExplicit` 记住请求。一个用改动面大小来选设计的规则,选出的是省事的
那个,不是对的那个。

### 17.2 §11「gcc 能否消费 libc++ 的 std 模块」—— 仍然没测,而这是对的

本文说「若有人要去证明它可行,那是一次实测,不是一次推理」。落地时没有
去做这次实测,而是让 `openkal-llvm-runtime` 声明
`requires = ["mcpp:compiler=llvm"]`,在编译任何东西之前拒绝这个组合。

保留这条记录是因为**「不去回答一个问题」也是一种设计决定**,而它需要一个
理由:能否让 gcc 编 libc++ 的模块,答案无论是什么都不会改变这个包的正确
配置,所以那次实测的成本不换来任何决策。

### 17.3 §12.3「二进制分发不能声明 provides」—— 已被实验否掉

上文断言二进制分发形态无法声明层能力,并据此推导出一整套需要引擎改动的
方案。**这是错的。** 手写一个 `sources = []` + `provides` + `std-module`
的无源码包,零引擎改动即可占住 c++-abi 层。§12.3 已在本文修正。

⚠️ 这一条与 17.1 是同一种错误:**用「做不到」当推理的前提,而没有去试**。
[[reasons-written-from-memory-kill-good-fixes]]

### 17.4 新层名的发布门槛 —— 本文完全没有涉及,而它决定了能不能发

上文把 `mcpp:compiler-runtime` 当作一个模型问题,没有问「一个已发布的
构建工具读到这个键会怎样」。实测,一个依赖声明一个键:

| 键 | 2026.8.19.4 | 2026.8.24.1 | 2026.8.24.3 |
|---|---|---|---|
| `requires = ["mcpp:compiler=llvm"]` | exit 0 未校验 | exit 0 未校验 | exit 0 解析 |
| `provides = ["mcpp:compiler-runtime=…"]` | exit 0 **未校验** | **exit 2 拒绝** | exit 0 解析 |

⭐ **两个 exit 0 不是同一种成功。** 19.4 早于层词表,整个数组被当作不认识
的键忽略 —— 它既不拒绝也不读。一个 pin 在那里的 CI 会在一份中心主张从未
被检查过的清单上报绿。因此生态包声明新层时,`MCPP_VERSION` 必须同一改动
里上移,理由不是兼容性而是**让断言有人执行**。

拒绝窗口只有 2026.8.24.1 一个版本。判据是**索引服务哪个版本**,不是本包
声明的 floor,也不是「新 mcpp 支持了」。

### 17.5 一次撤回:把规范的机制当成了缺陷

落地过程中,示例程序在 `riscv64-none-elf` 上链接失败:

```
ld.lld: error: undefined symbol: kal_fs_props
>>> referenced by fs.cppm:136
```

据此给 `openkal-opensbi` 补了 `kal_fs_props = 0`,发布 0.1.3 并合入索引。
**全错。** openkal SPEC 6.1:「实现不提供的接口,作为链接期定义是缺席的,
使用它的消费者链接失败。」6.2 的表把时机分开 —— 链接器回答「是否用了它
不提供的接口」,能力字回答「在**它提供的接口内**它如何表现」。

给一个没有任何操作的接口定义能力字,是回答第二个问题而跳过第一个。
已发 0.1.4 撤回,索引里 0.1.3 的条目整个删除。真正错的是**程序**:
一份可移植源码可以问「这个文件系统怎样比较名字」,不可以问「这台机器
有没有文件系统」。示例因此从「一份源码四台机器」改为三台宿主目标。

⚠️ 与 17.1、17.3 同族,而这次更贵:**报错信息告诉你什么坏了,它不是规范。**

### 17.6 落地后的实测数字

| 项 | 值 |
|---|---|
| 单元测试 | 93 通过 / 0 失败 |
| e2e(本机) | 289 通过 / 25 失败,零新增失败,修好 1 条既有失败 |
| `prepare.cppm` 实质改动 | +153 / −25(其余 745 行是 lambda 缩进) |
| 五层中由图供给 | 4 层(仅 compiler 来自载荷) |
| 沙箱行为验证 | 13 断言全通过,mcpp 2026.8.24.3 自索引装出 |
7 changes: 7 additions & 0 deletions .agents/docs/2026-08-24-target-side-design.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
> ✅ **本文已实现并发布**,见 mcpp 2026.8.24.2 与 2026.8.24.3。
> 规范化陈述在 `docs/spec/target-side.md`(SPEC-002),使用者文档在
> `docs/14-target-side.md` 与 `docs/15-openkal-cross.md`。
> **落地过程中被推翻的判断记在**
> `2026-08-24-graph-target-side-optimization-plan.md` §17,读设计之后值得一读:
> 其中三条是本文没有问对的问题,一条是把规范的机制当成了缺陷。

# mcpp 目标侧设计

2026-08-24 · 设计定稿
Expand Down
Loading