Skip to content

freedesktop.egl 1.7.0:libglvnd 源码构建;模块名改跟接口所有者(khronos.egl / freedesktop.wayland.*) - #293

Merged
Sunrisepeak merged 5 commits into
mainfrom
feat/freedesktop-egl
Aug 30, 2026
Merged

freedesktop.egl 1.7.0:libglvnd 源码构建;模块名改跟接口所有者(khronos.egl / freedesktop.wayland.*)#293
Sunrisepeak merged 5 commits into
mainfrom
feat/freedesktop-egl

Conversation

@Sunrisepeak

@Sunrisepeak Sunrisepeak commented Aug 30, 2026

Copy link
Copy Markdown
Member

⚠ 先说一件需要尽快合的事

为了承载模块重命名,mcpplibs/waylandv1.26.0原地重切(上游没有更新版本可跟,而版本号必须与上游对齐)。后果是立即的:

main 上 freedesktop.wayland.lua 的 sha256   0a5dd54a…
tag 上 tarball 的实际 sha256                961a900d…   ← 不匹配

在本 PR 合并之前,freedesktop.wayland@1.26.0 从 main 装不下来。 本 PR 更新了四个 wayland 描述符的 sha256,合并即恢复。正确的次序本该是先改描述符、合并、再重切 tag,这一点已记进设计文档 §19.6。

另有一个更隐蔽的:store 只按 (name, version) 索引,已经装过 1.26.0 的机器不会重新下载,会继续用旧模块名而毫无提示。开发机需要手动清:

rm -rf ~/.mcpp/registry/data/xpkgs/freedesktop-x-wayland*/1.26.0 \
       ~/.mcpp/registry/data/xpkgs/freedesktop-x-egl/1.7.0 \
       ~/.mcpp/build-cache/v1/pkg/freedesktop ~/.mcpp/build-cache/v1/tool/freedesktop

这个 PR 做了什么

1. compat.eglfreedesktop.egl:从绑定改为源码构建。

compat.egl 自己的注释就写着这是错的:

libglvnd is a separable project, so by the criterion this should be a source build; it is still a binding for effort alone

判据里没有「工作量」这一项。上游 fork:mcpplibs/libglvnd v1.7.0,CI 四 job 全绿。

2. 模块命名:跟拥有「接口」的组织。

wayland.client  →  freedesktop.wayland.client      freedesktop 确实拥有 wayland 协议
wayland.server  →  freedesktop.wayland.server
wayland.util    →  freedesktop.wayland.util
egl             →  khronos.egl                     EGL 是 Khronos 的规范

EGL 的包名与模块名故意不一致:包是 freedesktop.egl(freedesktop 确实在发这份代码),模块是 khronos.egl(Khronos 拥有规范,libglvnd 只是实现之一)。

依据不是审美,是 mcpplibs.openkal 已经付过的学费 —— 它的 0.1.0 是被撤回而不是保留的:

It placed the module a consumer imports under the control of the implementation, which contradicts what the specification is for

模块名是全局且长期的,包名不是。换实现不该逼消费者改 import,否则一个「除了 include 那一行什么都不改」的包装层就失去了意义。副作用是好的:两个 EGL 提供方现在会在模块名上硬冲突,而不是静默共存 —— 这正是 GLVND 想要的。

索引既有的惯例本来就是「namespace 不进模块名」(chriskohlhoff.asioimport asiocompat.opencvimport opencv.cv),这次是把它说具体。

3. 两个 fork 的 CI 钉住 xlings。

原先 curl … | bash 拿的是当天最新,红了也分不清是自己坏了还是生态变了。现钉 XLINGS_VERSION: "2026.8.27.5",与 mcpp 的 kXlingsVersion 一致。mcpp 本身仍不钉 —— 这些包依赖的正是生态,钉死的 mcpp tarball 带的是生态的冻结快照。钉住装的工具,放开被测的生态。

(要求里写的是 pin 到 2026.8.27.4,但那比 .5 旧三小时、且缺少「声明压过索引」的行为。详见设计文档 §15 与 §19.5。)

生态真实验证(--sandbox --gpu)

在一个 /home/speak 是合成的沙箱里从零 clone + 装 mcpp + 构建 + 运行。关键是沙箱里 /usr 是宿主的:

host has  /usr/lib/x86_64-linux-gnu/libEGL.so.1
host has  /usr/lib/x86_64-linux-gnu/libgbm.so.1
host has  /usr/lib/x86_64-linux-gnu/libdrm.so.2
host has  /usr/lib/x86_64-linux-gnu/libwayland-client.so.0

所以要证的不是「宿主不在」,而是「宿主在、可达、且依然全部落败」:

libdrm.so.2            => <project>/target/…/bin/libdrm.so.2
libEGL.so.1            => <project>/target/…/bin/libEGL.so.1
libGLdispatch.so.0     => <project>/target/…/bin/libGLdispatch.so.0
libwayland-client.so.0 => <project>/target/…/bin/libwayland-client.so.0
libwayland-server.so.0 => <project>/target/…/bin/libwayland-server.so.0
libffi.so.8            => <project>/target/…/bin/libffi.so.8
libgbm.so.1            => <registry>/xpkgs/compat-x-libgbm/25.0.7/…/libgbm.so.1

PASS: the host's copies were present and reachable, and none of them won

真跑:

EGL_VERSION            1.5 libglvnd            ← 自建 dispatch 在答
/dev/dri/card0         drm driver simpledrm
  gbm_bo_create        256x256 stride=1024     ← 真分配出 buffer object
  eglInitialize        EGL 1.5, vendor Mesa Project

import khronos.egl; 与两个 import freedesktop.wayland.*; 在同一次干净构建里编译链接通过。

测试成员

每条断言在零 vendor 的机器上都成立,这是被 runner 教的:原来那条「扩展串里有 EGL_EXT_」在开发机过、在干净 runner 挂,因为上游在 vendor 列表为空时直接 return ""(libegl.c:928)—— 那条断言测的是机器有没有 GPU 驱动。换成两条更有用的:EGL_VERSION 由 libglvnd 在任何 vendor 之前答成字面量 "1.5 libglvnd"(既是活性也是身份检查),以及 dladdr 确认加载的确实是本包构建的 libEGL.so.1 而不是 xim:libglvnd payload 的同 soname 副本。

镜像

wayland / libglvnd 两个 CN 镜像已重新发布,与 GLOBAL 字节一致。

文档

跨仓设计文档补 §19(模块命名、生成器该放 build.mcpp 还是签进仓、沙箱验证、自己造成的破坏、八角度审视),两份 descriptor-examples 同步。

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 测试里那条同理。
⚠ 这个提交修复 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),这次是把它推进一步:
不是随便一个名字,而是接口所有者的名字。
跨仓主文档补上 §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。
规则:模块名跟拥有**接口**的组织。索引早先的惯例是把 namespace 整个丢掉
(chriskohlhoff.asio → import asio),这一条是把那个惯例说具体 —— 模块名全局且长期,
包名不是,所以它该说清楚谁拥有这份接口。EGL 那一行顺带解释了包名与模块名为什么故意
不一致。
@Sunrisepeak Sunrisepeak changed the title freedesktop.egl 1.7.0:libglvnd 源码构建 + C++23 模块层,替掉 compat.egl 绑定 freedesktop.egl 1.7.0:libglvnd 源码构建;模块名改跟接口所有者(khronos.egl / freedesktop.wayland.*) Aug 30, 2026
之前 §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。
@Sunrisepeak
Sunrisepeak merged commit dc961cc into main Aug 30, 2026
5 of 17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants