Skip to content

Commit dc961cc

Browse files
freedesktop.egl 1.7.0:libglvnd 源码构建;模块名改跟接口所有者(khronos.egl / freedesktop.wayland.*) (#293)
* freedesktop.egl 1.7.0:libglvnd 源码构建 + C++23 模块层,替掉 compat.egl 绑定 compat.egl 绑的是 xim:libglvnd,而它自己的注释就写着这是错的: libglvnd **is** a separable project, so by the criterion this should be a source build; it is still a binding for effort alone 判据里没有「工作量」这一项。工作量的部分是生成的 dispatch(约 1000 行 Python 处理 2.7MB gl.xml)加上整个 libGLdispatch.so —— mcpplibs/libglvnd 这个 fork 把生成物签进仓、两个库都建出来,于是构建期不跑 Python、不跑第二套构建系统, mcpp build 就是全部工具链。upstream/ 是 freedesktop 发布物原样,fork 加的东西 全在 mcpp/ 下,CI 两边都 diff。 一个索引条目,两个库。libGLdispatch.so.0 由同 workspace 的兄弟成员构建,用 path 依赖引入而不是走索引:「进程里只有一个 dispatch 点」是 GLVND 存在的全部 理由,两个索引条目会让消费者把两个都写上、解析出两个包实例,而 soname 复用 只映射其中一个、另一个被静默丢弃。 按架构选文件放在 build.mcpp 里。GLdispatch 的 entry stub 既分架构又分线程存储 模型,而且和 libffi 的不同,它们自身没有任何门控 —— 在 sources 里写死 x86_64 会让包只能在 x86_64 上用而且哪儿都不写明;build.mcpp 用 mcpp::target_arch() 做的正是上游 gl_dispatch_type 的那个选择。 编译进去的 vendor 搜索路径刻意留空。上游烤进 <prefix>/share/glvnd/egl_vendor.d, 重定位之后那就是 host 的目录。留空能让「生态没声明」表现为「找不到 vendor」, 而不是悄悄把宿主驱动装进沙箱进程 —— 与 compat.libgbm 对 GBM_BACKENDS_PATH 的 立场一致,真正的路径由 xim:mesa 通过 discovery 层声明(xim-pkgindex#713)。 测试成员的每条断言在零 vendor 的机器上都成立,这是被 runner 教的:原来那条 「扩展串里有 EGL_EXT_」在我这台过、在干净 runner 挂,因为上游在 vendor 列表 为空时直接返回空串(libegl.c:928)—— 那条断言测的是机器有没有 GPU 驱动。 换成两条更好的:EGL_VERSION 在任何 vendor 之前由 libglvnd 自己答成字面量 "1.5 libglvnd"(既是活性检查也是身份检查),以及 dladdr 确认加载的确实是本包 构建的 libEGL.so.1 而不是 xim:libglvnd payload 的同 soname 副本 —— 后者在装了 图形栈的机器上是真实可达的,和 compat.libdrm 测试里那条同理。 * 模块名带上拥有接口的组织,并修好 wayland 因重切 tag 而失效的 sha256 ⚠ 这个提交修复 main 上的一处失效:mcpplibs/wayland 的 v1.26.0 被重切以承载模块 重命名,于是已合并描述符里的 sha256 不再匹配,freedesktop.wayland@1.26.0 目前 装不下来。四个 wayland 描述符的 sha256 都已更新,合并即恢复。 模块重命名: wayland.client → freedesktop.wayland.client wayland.server → freedesktop.wayland.server wayland.util → freedesktop.wayland.util egl → khronos.egl 规则是「模块名跟拥有**接口**的组织,而不是发实现代码的人」。freedesktop 确实拥有 wayland 协议;EGL 则是 Khronos 的规范,libglvnd 只是实现之一、freedesktop 只是托管方 —— 所以包仍叫 freedesktop.egl,导出的模块叫 khronos.egl。 mcpplibs.openkal 已经为这条规则付过学费:它的 0.1.0 是被撤回而不是保留的,原因写在 描述符里 —— "placed the module a consumer imports under the control of the implementation, which contradicts what the specification is for"。 模块名是全局且长期的,包名不是。换实现不该逼消费者改 import,否则一个「除了 include 那一行什么都不改」的包装层就失去了意义。副作用是好的:两个 EGL 提供方现在会在模块名 上硬冲突,而不是静默共存 —— 这正是 GLVND「一个进程一个 dispatch 点」想要的。 索引里既有的惯例本来就是「namespace 不进模块名」(chriskohlhoff.asio → import asio, fmtlib.fmt → import fmt,compat.opencv → import opencv.cv),这次是把它推进一步: 不是随便一个名字,而是接口所有者的名字。 * docs: 第四轮记录 —— EGL 源码化、模块命名归属、沙箱干净房间验证 跨仓主文档补上 §19,涵盖这一轮的四件事: §19.2 模块命名。规则定为「跟拥有**接口**的组织,不跟发实现的人」,依据是 mcpplibs.openkal 已经付过的学费(0.1.0 被撤回,因为它把消费者 import 的模块放在了 实现的控制之下)。于是 wayland 三个模块加 freedesktop 前缀,EGL 的模块叫 khronos.egl —— 包名与模块名故意不一致,因为 freedesktop 发这份代码而 Khronos 拥有这份规范。 §19.3 生成器该放哪。判据是「依不依赖目标平台」:能预先算定的签进仓 + CI diff(两个 fork 的构建路径上都没有 Python),依赖架构算不出来的才进 build.mcpp(GLdispatch 的 entry stub)。把 genmod.py 改写成 build.mcpp 反而会把生成器塞进每个消费者的构建。 §19.4 沙箱干净房间验证。合成 home、从零 clone + 装 + 构建,而沙箱里 /usr 是宿主的 —— 所以证的不是「宿主不在」,而是「宿主在、可达、且全部落败」。整条链跑通, eglInitialize 拿到 EGL 1.5 vendor Mesa Project,gbm_bo_create 真分配出 256x256。 顺带记了三个坑,其中 [indices] 同一 path 挂两个键会产生二义那条最耗时间。 §19.6 记一处自己造成的破坏:为承载模块重命名原地重切了 wayland 的 v1.26.0,于是在本 PR 合并前 main 上的 sha256 对不上。正确次序应当是先改描述符再重切 tag。同版本重切还 会被 store 掩盖(只按 name+version 索引),清理命令一并记下。 §19.5 xlings pin:§15「不下调到 .4」的结论仍然成立,但那条要求指出的缺口是真的 —— 两个 fork 的 CI 根本没钉,现已钉到与 kXlingsVersion 一致的 .5。 * docs: 模块命名规则写进两份 descriptor-examples,并修掉描述符首行的旧模块名 规则:模块名跟拥有**接口**的组织。索引早先的惯例是把 namespace 整个丢掉 (chriskohlhoff.asio → import asio),这一条是把那个惯例说具体 —— 模块名全局且长期, 包名不是,所以它该说清楚谁拥有这份接口。EGL 那一行顺带解释了包名与模块名为什么故意 不一致。 * 沙箱验证脚本签进仓,§19.4 换成完整记录 之前 §19.4 只有方法论和输出摘录,脚本躺在一个 subos 目录里 —— 那既不可复现也不算记录 下来了。现在: * tests/verify_graphics_closed_loop_sandbox.sh 签进仓,与 check_graphics_install_side_effects.sh 同处 tests/,带复现命令与参数说明; * §19.4 收录**完整**输出(七个步骤全文),外加一张「这份输出证明了什么」的断言→证据 对照表,以及两条不是缺陷的输出各自的解释; * 三个坑写进文档:[indices] 同一 path 挂两个键会二义、沙箱里 find 会抓到别的 subos 的 mcpp、沙箱不挂 cwd。 签进仓的这一版是重新跑过的,不是把之前的输出誊抄过来 —— 分支 feat/freedesktop-egl @ 2f4458d,结果 PASS。 §19.1 与 §19.8 同步:示例 09 已推到 mcpp PR #532。之前扣着不推的理由是「会把已绿的 CI 弄红」,那是假设、没查 —— mcpp 的 CI 根本不构建 examples/09-graphics-stack。 --------- Co-authored-by: Sunrisepeak <x.d2learn.org@gmail.com>
1 parent 83ddd4a commit dc961cc

13 files changed

Lines changed: 718 additions & 309 deletions

.agents/docs/2026-08-30-gbm-cross-repo-closed-loop-plan.md

Lines changed: 259 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ Date: 2026-08-30 · 起因:`compat.libgbm`(mcpp-index PR #281)· 状态:待 revi
99

1010
| 想知道 | 看哪节 | 注意 |
1111
|---|---|---|
12+
| **最新一轮(EGL 源码化 + 模块命名)** | **§19** | 最权威;§19.6 记了一处自己造成的破坏 |
13+
| **沙箱干净房间验证** | **§19.4** | 宿主库在场且可达却全部落败 |
14+
| 模块该叫什么名字 | §19.2 | 跟接口的所有者,不跟发实现的人 |
15+
| 生成器放 build.mcpp 还是签进仓 | §19.3 | 判据是「依不依赖目标平台」 |
16+
| xlings 该 pin 哪个版本 | §15 + §19.5 | §15 的结论仍成立,§19.5 补了它指出的真缺口 |
1217
| **最终结论与交付** | §12(实现结果)、§13(状态)、§14(要不要做 mesa 包) | 权威 |
1318
| 为什么 `compat.libgbm` 该独立存在 | §3、§10.1 | 理由换过三次,结论没变 |
1419
| 任务拆分与依赖 | §11 | |
@@ -1113,3 +1118,257 @@ backends dir: <registry>/subos/default/usr/lib/gbm ← subos 给的,不是
11131118
`index.toml``min_mcpp = 2026.8.3.3`**假的**,而且是本包证明的 —— 详见提交
11141119
`feat(libgbm): the package sheds its workaround; index floor corrected`
11151120
已上调到 `2026.8.27.2`,同时把「floor 与 CI pin 一起动」这条早已漂移的不变量恢复了。
1121+
1122+
---
1123+
1124+
## 19. 第四轮:EGL 从绑定改为源码构建,并统一模块命名(2026-08-30 下午)
1125+
1126+
§18 之后栈里还剩一处不自洽:`compat.egl` 是绑定,而它**自己的注释**写着这是错的 ——
1127+
「libglvnd **is** a separable project,按判据本该源码构建,现在仍是绑定纯粹是工作量问题」。
1128+
判据里没有「工作量」这一项。这一节把这笔账还上,并顺带解决了模块命名的归属问题。
1129+
1130+
### 19.1 交付物
1131+
1132+
|| 变更 | 状态 |
1133+
|---|---|---|
1134+
| **mcpplibs/libglvnd**(新建) | libglvnd v1.7.0 + mcpp 构建支持,出 `libEGL.so.1``libGLdispatch.so.0` | `v1.7.0`,CI 四 job 全绿 |
1135+
| **mcpplibs/wayland** | 三个模块重命名;CI 钉 xlings | `v1.26.0` 重切,CI 全绿 |
1136+
| **mcpp-index** | `compat.egl``freedesktop.egl`;5 个描述符 sha256;测试成员;文档 | PR #293 |
1137+
| **mcpp-community/mcpp** | 示例 09 改用 `freedesktop.egl`,模块改名,打印两个发现变量,闭包实测重新测量 | PR #532,已推 |
1138+
| mcpp-res(gitcode) | wayland / libglvnd 两个 CN 镜像 | 已发布,与 GLOBAL 字节一致 |
1139+
1140+
### 19.2 模块命名:跟**接口的所有者**,不跟发实现的人
1141+
1142+
索引既有的惯例是「namespace 不进模块名」,这一点有反例可证:
1143+
1144+
|| 模块 |
1145+
|---|---|
1146+
| `chriskohlhoff.asio` | `import asio` |
1147+
| `fmtlib.fmt` | `import fmt` |
1148+
| `boost-ext.ut` | `import boost.ut` |
1149+
| `opencv.opencv` | `import opencv.cv` |
1150+
1151+
这一轮把它推进一步:模块名不是随便挑的,而是**拥有那份接口的组织**。于是
1152+
1153+
```
1154+
wayland.client → freedesktop.wayland.client freedesktop 确实拥有 wayland 协议
1155+
wayland.server → freedesktop.wayland.server
1156+
wayland.util → freedesktop.wayland.util
1157+
egl → khronos.egl EGL 是 Khronos 规范
1158+
```
1159+
1160+
**注意 EGL 的包名与模块名故意不一致**:包是 `freedesktop.egl`(freedesktop 确实在发
1161+
这份代码),模块是 `khronos.egl`(Khronos 拥有这份规范,libglvnd 只是实现之一)。
1162+
1163+
依据不是审美,是 `mcpplibs.openkal` 已经付过的学费 —— 它的 0.1.0 是**被撤回**而不是保留的:
1164+
1165+
> It placed the module a consumer imports **under the control of the
1166+
> implementation**, which contradicts what the specification is for
1167+
1168+
模块名是全局且长期的,包名不是。换实现不该逼消费者改 `import`,否则一个「除了 include
1169+
那一行什么都不改」的包装层就失去了意义。副作用是好的:两个 EGL 提供方现在会在模块名上
1170+
**硬冲突**,而不是静默共存 —— 这正是 GLVND「一个进程一个 dispatch 点」想要的。
1171+
1172+
### 19.3 build.mcpp 与「签进仓的生成物」的分界
1173+
1174+
这一轮两次遇到「生成器该放哪」,答案不一样,规则是同一条:
1175+
1176+
> **build.mcpp 管的是「依赖目标平台、算不出来」的决定;能预先算定的生成物就签进仓 + CI diff。**
1177+
1178+
| 生成物 | 依赖目标? | 放哪 |
1179+
|---|---|---|
1180+
| libglvnd 的 dispatch 表(~1000 行 Python × 2.7MB gl.xml) || `mcpp/generated/`,CI 重生成并 diff |
1181+
| wayland 的协议代码 + 模块包装(`genmod.py`) || `mcpp/generated/`,CI 重生成并 diff |
1182+
| GLdispatch 的 **entry stub 选择** | ****(架构 × 线程存储模型) | `build.mcpp`,用 `mcpp::target_arch()` |
1183+
1184+
两个 fork 的**构建路径上都没有 Python**(`mcpp.toml` / `build.mcpp` / 根清单都不提它),
1185+
消费者只需要 mcpp。把 `genmod.py` 改写成 build.mcpp 反而会**把生成器塞进每个消费者的
1186+
构建**,并且会撞上 **mcpp#534**(build.mcpp 的 action 产物与本包编译之间没有 order-only 边)
1187+
—— wayland 的协议代码当初签进仓正是因为这个。
1188+
1189+
GLdispatch 那条则相反:entry stub 分架构****分线程存储模型,而且和 libffi 的不同,
1190+
**它们自身没有任何门控**。在 `sources` 里写死 x86_64 会让包只能在 x86_64 上用、而且哪儿
1191+
都不写明;`build.mcpp``mcpp::target_arch()` 做的正是上游 `gl_dispatch_type` 的选择。
1192+
1193+
### 19.4 生态真实验证:沙箱干净房间(`--sandbox --gpu`)—— 已完成并记录
1194+
1195+
§12.3 验证过的是 **GBM**。这一节验证的是**整条链**,包含这一轮新增的源码构建 EGL 与
1196+
重命名后的模块,而且是**从零安装 + 从零构建**
1197+
1198+
**脚本已签进仓**:[`tests/verify_graphics_closed_loop_sandbox.sh`](../../tests/verify_graphics_closed_loop_sandbox.sh)
1199+
1200+
复现:
1201+
1202+
```bash
1203+
# 一个装了图形栈的 subos,例如 xlings install xim:mesa@25.0.7.2
1204+
cp tests/verify_graphics_closed_loop_sandbox.sh ~/.xlings/subos/<subos>/verify.sh
1205+
xlings subos use <subos> --sandbox --gpu \
1206+
--cmd "BRANCH=<ref> sh /home/speak/.xlings/subos/<subos>/verify.sh"
1207+
```
1208+
1209+
拷贝那一步不是多余的:**沙箱不挂当前工作目录**,放在别处的脚本在里面根本看不到。
1210+
1211+
#### 为什么这个沙箱有说服力
1212+
1213+
关键不是「隔离得干净」,而是**沙箱里 `/usr` 仍然是宿主的**。所以要证的**不是**「宿主
1214+
不在」—— 一个把 `/usr` 藏起来的沙箱对用户的机器什么也证明不了 —— 而是「宿主在、可达、
1215+
且依然全部落败」。后者才是真实机器上会发生的情形。
1216+
1217+
#### 完整输出(2026-08-30,`eco-gbm-20260830`,分支 `feat/freedesktop-egl` @ 2f4458d)
1218+
1219+
```
1220+
===== 0. where we are =====
1221+
home contents: . .. .bashrc closed-loop .config .mcpp mcpp-index .profile .xlings .zshrc
1222+
host has /usr/lib/x86_64-linux-gnu/libEGL.so.1
1223+
host has /usr/lib/x86_64-linux-gnu/libgbm.so.1
1224+
host has /usr/lib/x86_64-linux-gnu/libdrm.so.2
1225+
host has /usr/lib/x86_64-linux-gnu/libwayland-client.so.0
1226+
GBM_BACKENDS_PATH = <subos>/usr/lib/gbm
1227+
__EGL_VENDOR_LIBRARY_DIRS = <subos>/share/glvnd/egl_vendor.d
1228+
1229+
===== 1. install mcpp through xlings =====
1230+
mcpp: <subos>/bin/mcpp
1231+
mcpp 2026.8.29.1
1232+
1233+
===== 2. clone the index under test =====
1234+
branch feat/freedesktop-egl @ 2f4458d
1235+
1236+
===== 3. a project that names the whole stack =====
1237+
1238+
===== 4. build from scratch =====
1239+
build.mcpp compiling
1240+
build.mcpp running
1241+
Target x86_64-linux-gnu → x86_64-unknown-linux-gnu
1242+
Inferred sources [src/**/*.{cppm,cpp,cc,c,S,s,asm}]
1243+
Inferred target closed-loop (bin from src/main.cpp)
1244+
Compiling closed-loop v0.1.0 (.)
1245+
Cached compat.libdrm v2.4.134 (5 units)
1246+
Cached compat.libgbm v25.0.7 (1 unit)
1247+
Compiling freedesktop.egl v1.7.0
1248+
Cached freedesktop.wayland v1.26.0 (1 unit)
1249+
Cached freedesktop.wayland-server v1.26.0 (1 unit)
1250+
Finished dev [unoptimized + debuginfo] in 0.31s
1251+
1252+
===== 5. what the loader actually resolved =====
1253+
libgbm.so.1 => <registry>/xpkgs/compat-x-libgbm/25.0.7/mcpp_generated/libgbm/lib/libgbm.so.1
1254+
libdrm.so.2 => <project>/target/x86_64-linux-gnu/78e15402517d6f84/bin/libdrm.so.2
1255+
libEGL.so.1 => <project>/target/x86_64-linux-gnu/78e15402517d6f84/bin/libEGL.so.1
1256+
libwayland-client.so.0 => <project>/target/x86_64-linux-gnu/78e15402517d6f84/bin/libwayland-client.so.0
1257+
libwayland-server.so.0 => <project>/target/x86_64-linux-gnu/78e15402517d6f84/bin/libwayland-server.so.0
1258+
libexpat.so.1 => <registry>/xpkgs/xim-x-expat/2.6.2/lib/libexpat.so.1
1259+
libGLdispatch.so.0 => <project>/target/x86_64-linux-gnu/78e15402517d6f84/bin/libGLdispatch.so.0
1260+
libffi.so.8 => <project>/target/x86_64-linux-gnu/78e15402517d6f84/bin/libffi.so.8
1261+
1262+
===== 6. did anything come from the host? =====
1263+
PASS: the host's copies were present and reachable, and none of them won
1264+
1265+
===== 7. run it =====
1266+
KMS: DRM_IOCTL_MODE_CREATE_DUMB failed: Permission denied
1267+
kmsro: driver missing
1268+
-- the modules carry the API --
1269+
EGL_VERSION 1.5 libglvnd
1270+
wl_display_create 0x2bd0dbf0
1271+
-- DRM node -> GBM device -> EGL display --
1272+
/dev/dri/renderD128
1273+
drm driver nvidia-drm
1274+
gbm_create_device 0x2bd65e60
1275+
gbm_bo_create (driver declined)
1276+
eglInitialize EGL 1.5, vendor Mesa Project
1277+
/dev/dri/card0
1278+
drm driver simpledrm
1279+
gbm_create_device 0x2bd65e60
1280+
gbm_bo_create 256x256 stride=1024
1281+
eglInitialize EGL 1.5, vendor Mesa Project
1282+
1283+
reached EGL on a real device: yes
1284+
1285+
===== RESULT =====
1286+
PASS
1287+
```
1288+
1289+
#### 这份输出证明了什么
1290+
1291+
| 断言 | 证据 |
1292+
|---|---|
1293+
| 模块层在干净构建里成立 | `import khronos.egl;` + 两个 `import freedesktop.wayland.*;` 编译链接通过 |
1294+
| 加载的是**自建**的 EGL 而非 payload | `libEGL.so.1 => <project>/target/…`,且 `EGL_VERSION` 由它答出 |
1295+
| 自建 dispatch 真能加载 vendor | `eglInitialize → EGL 1.5, vendor Mesa Project` |
1296+
| GBM 真分配了显存 | `gbm_bo_create 256x256 stride=1024`(card0) |
1297+
| 宿主一条都没赢 | 第 6 步:四个宿主库在场且可达,闭包里零条来自 `/usr/lib` |
1298+
| 发现路径来自生态而非包 | 两个变量都由 `xim:mesa` 声明,包自己什么都不设 |
1299+
1300+
两条**不是**缺陷的输出:`renderD128``gbm_bo_create` 被驱动拒绝,是 NVIDIA 后端不接受
1301+
该 format/usage 组合;`DRM_IOCTL_MODE_CREATE_DUMB failed: Permission denied` 是 render node
1302+
的权限边界(dumb buffer 需 KMS 权限)。`card0` 上两者都成功。
1303+
1304+
#### 三个坑(留给下一个人)
1305+
1306+
1. **`[indices]` 同一个 path 不能挂两个键**。写 `compat``freedesktop` 都指向同一个
1307+
checkout,会注册成两个独立 project repo,之后每次查找都报
1308+
`package 'compat:libdrm@2.4.134' is ambiguous, candidates: … 'compat' … 'freedesktop'`
1309+
只重定向被测的那个 namespace,其余走已发布索引。
1310+
2. **沙箱里 `find ~/.xlings -name mcpp` 会抓到别的 subos 的二进制**,它们的 interpreter
1311+
不在,失败信息是干巴巴的 `not found`,读起来像「mcpp 没装上」。要先试本 subos 的 `bin/`
1312+
3. **沙箱不挂 cwd**,落点是合成的 `/home/speak`(只有 dotfile)。脚本必须拷进 subos 目录。
1313+
1314+
### 19.5 xlings pin:§15 的结论仍然成立,但它指出的缺口是真的
1315+
1316+
任务里再次出现「pin 内部依赖的 xlings 到 `2026.8.27.4`」。**§15 已经查过并否掉了**:
1317+
`.4``.5` ****三小时,三仓的 `kXlingsVersion` 已经都在 `.5`,而 `.5``.4` 没有的
1318+
行为(声明在解析时压过索引)。下调等于让生态退回一个能力更弱的版本。
1319+
1320+
但这条要求指出的**缺口是真的,只是位置不对**:两个 fork 的 CI **根本没钉**,
1321+
`curl … | bash` 拿的是当天最新。已改为钉 `XLINGS_VERSION: "2026.8.27.5"`,与
1322+
`kXlingsVersion` 一致。
1323+
1324+
**mcpp 本身仍不钉**,这是刻意的:这些包依赖的正是**生态**(`xim:mesa` 声明
1325+
`GBM_BACKENDS_PATH` / `__EGL_VENDOR_LIBRARY_DIRS`),而钉死的 mcpp tarball 带的是生态的
1326+
冻结快照。**钉住装的工具,放开被测的生态** —— 这个切分才让失败可归因。
1327+
1328+
### 19.6 一个自己造成的破坏,记下来
1329+
1330+
为了承载模块重命名,`mcpplibs/wayland``v1.26.0`**原地重切**(上游没有更新版本
1331+
可跟,而版本号必须与上游对齐)。后果是立即的:
1332+
1333+
```
1334+
main 上 freedesktop.wayland.lua 的 sha256 0a5dd54a…
1335+
tag 上 tarball 的实际 sha256 961a900d… ← 不匹配
1336+
```
1337+
1338+
在 PR #293 合并之前,`freedesktop.wayland@1.26.0` 从 main 装不下来。**正确的次序应当是
1339+
先改描述符、合并,再重切 tag**,而不是反过来。
1340+
1341+
还有一个更隐蔽的:store 只按 `(name, version)` 索引,所以**已经装过 1.26.0 的机器不会
1342+
重新下载**,会继续用旧模块名而毫无提示 —— 这正是
1343+
`stale-global-index-masks-descriptor-bugs` 那条。开发机上需要手动清:
1344+
1345+
```bash
1346+
rm -rf ~/.mcpp/registry/data/xpkgs/freedesktop-x-wayland*/1.26.0 \
1347+
~/.mcpp/registry/data/xpkgs/freedesktop-x-egl/1.7.0 \
1348+
~/.mcpp/build-cache/v1/pkg/freedesktop ~/.mcpp/build-cache/v1/tool/freedesktop
1349+
```
1350+
1351+
### 19.7 多角度审视
1352+
1353+
| 角度 | 这一轮的结果 |
1354+
|---|---|
1355+
| **架构** | 五个包里只剩 GBM 一个绑定,而它是唯一真正过不了「可否独立分发」的。判据终于和实现一致 |
1356+
| **稳定性** | CI 新增「符号内容 + obj 计数」——SONAME 检查对**空库**也会绿。两个 fork 都钉了 xlings |
1357+
| **优雅/简洁** | 一个索引条目出两个库(`libGLdispatch` 走 path 依赖),消费者只写一行 |
1358+
| **用户体验** | `import khronos.egl;` 换实现不用改代码;`EGL_*` 宏仍需 include,这一点写进了描述符 |
1359+
| **兼容性** | 模块重命名是**破坏性**的。选在 wayland 合并当天做,消费者只有示例 09 |
1360+
| **跨平台** | 按架构选 stub 移进 `build.mcpp`,aarch64/ppc64 由构造成立而非靠改代码 |
1361+
| **一致性** | 模块命名规则统一为「接口所有者」,与 openkal 的教训对齐 |
1362+
| **无感升级** |**没做到**,见 §19.6:同版本重切 tag 会被 store 掩盖。这是本轮唯一的真缺陷 |
1363+
1364+
### 19.8 仍未闭合
1365+
1366+
- **PR #293 必须合并**才能修好 main 上 wayland 的 sha256(§19.6)。这是唯一真正阻塞的一条。
1367+
- 示例 09 的更新已推到 mcpp PR #532。曾以为「推上去会把已绿的 CI 弄红」而扣着不推,
1368+
**那是假设、没查**:mcpp 的 CI 根本不构建 `examples/09-graphics-stack`(只有
1369+
`openkal-cross.yml` 碰一个无关示例)。扣着不推让工作停在本地,比推上去更糟。
1370+
- `libGL` / `libGLX` / `libGLESv{1,2}` 未构建。各自是 fork 里一个成员加一张
1371+
`mcpp/generated/` 里的 dispatch 表;索引里目前没有消费者。
1372+
- `freedesktop.egl``libEGL.so.1` 比 payload 的多三条 `DT_NEEDED`
1373+
(libstdc++/libm/libgcc_s),因为模块接口单元被编译进库里。`freedesktop.wayland` 完全
1374+
同形,是「模块层随库一起发」的既定结果,已写进描述符。

0 commit comments

Comments
 (0)