@@ -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,188 @@ 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 ` ,打印两个发现变量 | 待 #293 合并后推 |
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** 。这一轮验证的是** 整条链** ,而且在一个 ` /home/speak ` 是合成的、
1196+ 开发机上任何 checkout / 缓存 / 构建树都进不来的沙箱里,** 从零 clone + 安装 + 构建** 。
1197+
1198+ 关键在于:** 沙箱里 ` /usr ` 是宿主的** 。
1199+
1200+ ```
1201+ host has /usr/lib/x86_64-linux-gnu/libEGL.so.1
1202+ host has /usr/lib/x86_64-linux-gnu/libgbm.so.1
1203+ host has /usr/lib/x86_64-linux-gnu/libdrm.so.2
1204+ host has /usr/lib/x86_64-linux-gnu/libwayland-client.so.0
1205+ ```
1206+
1207+ 所以要证的** 不是** 「宿主不在」,而是「宿主在、可达、且依然全部落败」—— 后者才是用户机器
1208+ 上会发生的情形。用二进制自己的 loader 列闭包:
1209+
1210+ ```
1211+ libgbm.so.1 => <registry>/xpkgs/compat-x-libgbm/25.0.7/.../libgbm.so.1
1212+ libdrm.so.2 => <project>/target/.../bin/libdrm.so.2
1213+ libEGL.so.1 => <project>/target/.../bin/libEGL.so.1
1214+ libGLdispatch.so.0 => <project>/target/.../bin/libGLdispatch.so.0
1215+ libwayland-client.so.0 => <project>/target/.../bin/libwayland-client.so.0
1216+ libwayland-server.so.0 => <project>/target/.../bin/libwayland-server.so.0
1217+ libffi.so.8 => <project>/target/.../bin/libffi.so.8
1218+
1219+ PASS: the host's copies were present and reachable, and none of them won
1220+ ```
1221+
1222+ 真跑(` --gpu ` ):
1223+
1224+ ```
1225+ EGL_VERSION 1.5 libglvnd ← 自建 dispatch 在答
1226+ /dev/dri/renderD128 drm driver nvidia-drm
1227+ eglInitialize EGL 1.5, vendor Mesa Project
1228+ /dev/dri/card0 drm driver simpledrm
1229+ gbm_bo_create 256x256 stride=1024 ← 真分配出 buffer object
1230+ eglInitialize EGL 1.5, vendor Mesa Project
1231+ ```
1232+
1233+ ` import khronos.egl; ` 与两个 ` import freedesktop.wayland.*; ` 一起编译链接通过 ——
1234+ 模块层与 C 库在同一次干净构建里都成立。
1235+
1236+ 复现脚本见提交历史;三个坑值得记下:
1237+
1238+ 1 . ** ` [indices] ` 同一个 path 不能挂两个键** 。写 ` compat ` 和 ` freedesktop ` 都指向同一个
1239+ checkout,会注册成两个独立 project,之后每次查找都报
1240+ ` package 'compat:libdrm@2.4.134' is ambiguous, candidates: … 'compat' … 'freedesktop' ` 。
1241+ 只重定向被测的那个 namespace,其余走已发布索引。
1242+ 2 . ** 沙箱里 ` find ~/.xlings -name mcpp ` 会抓到别的 subos 的二进制** ,它们的 interpreter
1243+ 不在,失败信息是干巴巴的 ` not found ` ,读起来像「mcpp 没装上」。要先试本 subos 的 ` bin/ ` 。
1244+ 3 . ** 沙箱不挂 cwd** ,落点是合成的 ` /home/speak ` (只有 dotfile)。脚本要放进 subos 目录
1245+ 才进得去。
1246+
1247+ ### 19.5 xlings pin:§15 的结论仍然成立,但它指出的缺口是真的
1248+
1249+ 任务里再次出现「pin 内部依赖的 xlings 到 ` 2026.8.27.4 ` 」。** §15 已经查过并否掉了** :
1250+ ` .4 ` 比 ` .5 ` ** 旧** 三小时,三仓的 ` kXlingsVersion ` 已经都在 ` .5 ` ,而 ` .5 ` 有 ` .4 ` 没有的
1251+ 行为(声明在解析时压过索引)。下调等于让生态退回一个能力更弱的版本。
1252+
1253+ 但这条要求指出的** 缺口是真的,只是位置不对** :两个 fork 的 CI ** 根本没钉** ,
1254+ ` curl … | bash ` 拿的是当天最新。已改为钉 ` XLINGS_VERSION: "2026.8.27.5" ` ,与
1255+ ` kXlingsVersion ` 一致。
1256+
1257+ ** mcpp 本身仍不钉** ,这是刻意的:这些包依赖的正是** 生态** (` xim:mesa ` 声明
1258+ ` GBM_BACKENDS_PATH ` / ` __EGL_VENDOR_LIBRARY_DIRS ` ),而钉死的 mcpp tarball 带的是生态的
1259+ 冻结快照。** 钉住装的工具,放开被测的生态** —— 这个切分才让失败可归因。
1260+
1261+ ### 19.6 一个自己造成的破坏,记下来
1262+
1263+ 为了承载模块重命名,` mcpplibs/wayland ` 的 ` v1.26.0 ` 被** 原地重切** (上游没有更新版本
1264+ 可跟,而版本号必须与上游对齐)。后果是立即的:
1265+
1266+ ```
1267+ main 上 freedesktop.wayland.lua 的 sha256 0a5dd54a…
1268+ tag 上 tarball 的实际 sha256 961a900d… ← 不匹配
1269+ ```
1270+
1271+ 在 PR #293 合并之前,` freedesktop.wayland@1.26.0 ` 从 main 装不下来。** 正确的次序应当是
1272+ 先改描述符、合并,再重切 tag** ,而不是反过来。
1273+
1274+ 还有一个更隐蔽的: store 只按 ` (name, version) ` 索引,所以** 已经装过 1.26.0 的机器不会
1275+ 重新下载** ,会继续用旧模块名而毫无提示 —— 这正是
1276+ ` stale-global-index-masks-descriptor-bugs ` 那条。开发机上需要手动清:
1277+
1278+ ``` bash
1279+ rm -rf ~ /.mcpp/registry/data/xpkgs/freedesktop-x-wayland* /1.26.0 \
1280+ ~ /.mcpp/registry/data/xpkgs/freedesktop-x-egl/1.7.0 \
1281+ ~ /.mcpp/build-cache/v1/pkg/freedesktop ~ /.mcpp/build-cache/v1/tool/freedesktop
1282+ ```
1283+
1284+ ### 19.7 多角度审视
1285+
1286+ | 角度 | 这一轮的结果 |
1287+ | ---| ---|
1288+ | ** 架构** | 五个包里只剩 GBM 一个绑定,而它是唯一真正过不了「可否独立分发」的。判据终于和实现一致 |
1289+ | ** 稳定性** | CI 新增「符号内容 + obj 计数」——SONAME 检查对** 空库** 也会绿。两个 fork 都钉了 xlings |
1290+ | ** 优雅/简洁** | 一个索引条目出两个库(` libGLdispatch ` 走 path 依赖),消费者只写一行 |
1291+ | ** 用户体验** | ` import khronos.egl; ` 换实现不用改代码;` EGL_* ` 宏仍需 include,这一点写进了描述符 |
1292+ | ** 兼容性** | 模块重命名是** 破坏性** 的。选在 wayland 合并当天做,消费者只有示例 09 |
1293+ | ** 跨平台** | 按架构选 stub 移进 ` build.mcpp ` ,aarch64/ppc64 由构造成立而非靠改代码 |
1294+ | ** 一致性** | 模块命名规则统一为「接口所有者」,与 openkal 的教训对齐 |
1295+ | ** 无感升级** | ⚠ ** 没做到** ,见 §19.6:同版本重切 tag 会被 store 掩盖。这是本轮唯一的真缺陷 |
1296+
1297+ ### 19.8 仍未闭合
1298+
1299+ - ** PR #293 必须合并** 才能修好 main 上 wayland 的 sha256(§19.6)。
1300+ - 示例 09 的更新(mcpp PR #532 )在本地待推,依赖 #293 先合。
1301+ - ` libGL ` / ` libGLX ` / ` libGLESv{1,2} ` 未构建。各自是 fork 里一个成员加一张
1302+ ` mcpp/generated/ ` 里的 dispatch 表;索引里目前没有消费者。
1303+ - ` freedesktop.egl ` 的 ` libEGL.so.1 ` 比 payload 的多三条 ` DT_NEEDED `
1304+ (libstdc++/libm/libgcc_s),因为模块接口单元被编译进库里。` freedesktop.wayland ` 完全
1305+ 同形,是「模块层随库一起发」的既定结果,已写进描述符。
0 commit comments