docs: 闭环已对已发布的 main 复验,§19.6 的破坏确认修复 - #294
Merged
Merged
Conversation
#293 合并后又跑了一遍沙箱验证,这次 BRANCH=main,并先清空沙箱里上一轮的 store —— 所以 是真从已发布索引取,不是复用分支那次的产物(日志里五个包都是 "Compiling" 而非 "Cached")。闭包与分支那次逐条一致,结果 PASS。 按 §18.2 自己立的规矩,对着已发布 artifact 的这一次才是权威的,所以放在完整输出之前。 同时复验并记录:main 上两个描述符的 sha256 与各自 tag 上的 tarball 一致(§19.6 那处 我先重切 tag 后改描述符造成的破坏已随合并修复),compat.egl.lua 返回 404。 §19.8 更新:#293 已合并;示例 09 的 PR #532 CI 20/20 通过。
§19 证明了 GBM/DRM/EGL/Wayland 这条栈在沙箱里从零构建能跑通。但 #527 问的是能不能 满足系统级开发,而「跑通」和「够用」是两回事,之前没有把这个区分写下来。 三个场景逐个给结论: GBM 显存管理 ✅ 完全覆盖,已实测 Wayland 合成器⚠️ 只覆盖了协议库那一层 Mesa/Vulkan 扩展 ❌ Vulkan 侧仍伸手够宿主 缺口逐个点名而不是含糊带过。最要命的一个是 libGLESv2:合成器是拿到 EGL context 之后 用 GLES2 画的,而 libglvnd 的 GL/GLES 系列一个都没建 —— 也就是 EGL 能初始化,但拿到 context 之后没有 GL 可调。索引里 grep GLESv2 返回空。其余缺 wayland-protocols、 libxkbcommon、libinput、libudev/libseat、pixman。 Vulkan 那条 host 边(compat.vulkan-runtime 把宿主 /usr/lib 的 ICD 做成符号链接农场) 是当时有意为之的权宜,因为没有可绑的 payload。§17.2 已查明前提变了,现在可以照 compat.libgbm / freedesktop.egl 的同一形态拆掉:让环境声明,包自己什么都不设。 补齐的形态不需要再论证 —— 全部由这一轮已确立的判据(可独立分发 → 源码构建)直接推出。 排序 G1(GLES,补上渲染链)→ G5(拆掉最后一条 host 边)→ 其余。 同时更正 §19.8:mcpp 的示例 PR #532 已关闭且本就不需要合并,示例不是生态的一部分。
回答 §20 提出但没有展开的那个问题:从「能跑通」到「能写一个合成器」,具体要做什么。 每一条都调研到能直接动手,不是列愿望: G1 读了 libglvnd 的 meson,拿到五个库的精确构成,并发现一个决定规模的分层 —— GLESv2/GLESv1/OpenGL 不需要 X11,只有 GLX/GL 需要。所以只做前三个就覆盖合成器的全部 需要。四张生成表已经实跑通过(gl 78373 行 / opengl 30197 / glesv2 15788 / glesv1 11292)。 也读出了「为什么必须拆成员」的硬理由:stub.c 和 entry 文件被用两套不同的宏编译两次, 一个 mcpp 包做不到。 G2 的原假设被实测推翻。沙箱里不装 vulkan-runtime,Vulkan 其实已经能跑 —— 但落到 llvmpipe,因为 /usr/share 也在 XDG_DATA_DIRS 里,宿主 ICD 一并可见、部分能加载。真正 的问题不是 compat.vulkan-runtime,是 discovery 层怎么拼 XDG_DATA_DIRS;建议改用 VK_DRIVER_FILES 精确指定。另外专有驱动是永久边界,不该假装能覆盖。 G3 wayland-protocols 判据指向全量预生成 + 签进仓,做成 wayland fork 的第五个成员而不是 新建仓。G4 里 pixman 的 SIMD 自带门控,不需要 build.mcpp —— 与 GLdispatch 的 entry stub 正相反,是判据的一个好对照。 附任务依赖图(三条可并行)、八角度评估、六条验证矩阵,以及明确不做的四件事。 核心验证是 V3:glClear + glReadPixels 读回像素,那才是「能画」的定义。
三处更新。
1. G2 的方案换掉了,原因是调研发现生态里早就有一套完整设计。EGL 侧的形态是:一个共享
的 vendor 目录,mesa 和 nvidia-gl-host-link 各写一份 JSON 进去,靠 10_/50_ 文件名前缀
定优先级 —— 和发行版的约定一致。graphics.lua 的注释还记录了改成共享目录之前跨 vendor
优先级是「correct by alphabetical accident」。
Vulkan 侧缺的就是这一半:sentinel 已经把 libGLX_nvidia.so.0 软链进来(注释写着
"GLX vendor AND Vulkan ICD: same file")、已经供给 libX11/libXext、已经有写 ICD JSON
的代码路径,但只调了 declare_egl_vendor,没调 declare_vulkan_icd。于是 loader 退回去
扫 /usr/share,读到宿主那份裸 soname 的 JSON,缺 libXext 而放弃,再落到 lvp(llvmpipe)
—— 静默变成软件渲染。
原提案的 VK_DRIVER_FILES 作废:那是在既有机制之外另起一套。
2. V1 在写任何代码之前先验过,非破坏性(不动 subos 共享目录,用 VK_DRIVER_FILES 指一份
等效 JSON):
A 现状 devices = 1 → llvmpipe (LLVM 20.1.2)
B V1 假设 devices = 1 → NVIDIA GeForce RTX 4080
差别只有「那份 JSON 在不在、路径是不是绝对的」。顺带发现第二处更小的泄漏:宿主的
Vulkan layer(libVkLayer_MESA_device_select)同样被扫到,不影响结果但值得单独清理。
3. 补第四条判据:上游源码能直接用的走 compat 内联,需要 fork 的才走 mcpp 原生模块化。
操作性问题是「解开 tarball 能不能只靠一份 mcpp.toml 编出来」。并写明模块层是选 B 的
结果而不是理由 —— 不要为了加模块层把 A 推成 B。
另:最小 host 面写成设计而不是妥协。sentinel(nvidia-gl-host-link / libcuda-host-link /
wsl-gl-host-link)把宿主面收敛到「几个具名文件 + 一份 vendor 声明」,而且在没有该硬件的
机器上 install() 成功且什么都不链 —— 「"no NVIDIA on this machine" is a normal state」。
compat.vulkan-runtime 应归入这一类说清楚,而不是删掉。
EGL 能初始化,然后没有 GL 可调 —— 合成器是拿到 context 之后用 GLES2 画的,所以这一条
链之前是断的。这三个包接上它。
⚠ 本提交同时更新 freedesktop.egl 的 sha256:承载 GL 家族需要重切 libglvnd 的 v1.7.0,
于是 main 上那个描述符的 sha256 再次失效,合并即恢复。次序问题已记在
2026-08-30-gbm-cross-repo-closed-loop-plan.md §19.6。
只做不需要 X11 的三个。libGLX 和 libGL 才是拉 X11 的那两个(dep_x11/dep_xext/
dep_glproto,libGL 经 libGLX 间接依赖),建它们会把 Xorg 塞进每个消费者的依赖图,
包括根本没有显示器的 headless GBM 项目。这三个不碰窗口系统,而且正好是合成器要用的。
与 payload 逐符号核对过:
libGLESv2 358 个 GL 入口 == payload 的 358,逐个符号一致
libOpenGL 1044 == payload 的 1044,逐个符号一致
libGLESv1_CM 145 -- payload 根本不带这个库,是新增能力
测试成员做的是 V3「真能画」,不是符号存在性:GBM → EGL → surfaceless context →
FBO → glClear → glReadPixels,读回 64 128 191 255,与清的颜色分毫不差。
GL_VERSION 报 OpenGL ES 3.2 Mesa 25.0.7。
三个坑写进了注释:
* GBM 平台没有 pbuffer config,headless 要走 EGL_KHR_surfaceless_context + FBO;
* libGLdispatch 导出全量 GL 面(包括 glMatrixMode),所以「dlsym 找不到某名字」
永远不成立,断言必须基于 dladdr 的归属;
* 三个 GL flavour 符号面重叠(都导出 glClear),同一进程链两个会让名字绑到先加载
的那个 —— 实测:一个想用 GLESv2 的程序里 glClear 落到了 libGLESv1_CM.so.1,
毫无提示。所以测试成员只依赖一个 flavour,并断言 glClear 确实解析在它里面。
可达不等于对。内容过期的镜像资产照样返回 200,而这不是假设 —— 只要 fork 在同一个上游 版本上重切 tag 就会发生:gitcode 不能覆盖同名资产(release 的 DELETE 还返回 405),于是 旧 tarball 留在那里、GLOBAL 已经往前走了,CN 用户静默拿到上一版。在 mcpplibs/libglvnd v1.7.0 上连着遇到两次。 tests/list_cn_urls.lua 本来就在输出 `url<TAB>sha256`,这次是用上第二列而不是丢掉它。 body 本来也要下载(gitcode 的 release 页面可以 200 而资产已经没了),所以顺手做个哈希不 增加成本。 空流单独判:curl 失败时管道给出的是空输入,它的 sha256 是个固定常量,当成不可达处理而 不是当成「内容不符」——后者的报错会把人指向错误的方向。 本地验证过这条检查确实会抓到当前 libglvnd 的 CN 不一致。
合成器要的不只是核心协议 —— xdg-shell 决定窗口怎么存在,linux-dmabuf 决定
gbm_bo 怎么交给客户端。上游只发 XML,所以生成器在 mcpplibs/wayland-protocols 里
跑一次、产物签进仓,消费者构建期不跑 scanner。
三个包而不是一个,因为一个链不起来 —— 这是实测不是猜:
multiple definition of `zwp_linux_dmabuf_v1_interface'
按导出的 wl_interface 数:stable∩staging=0,stable∩unstable=13,
staging∩unstable=0,任一 tier 内=0。tier 正好是它们能共存的边界,而且这个边界是
上游自己的目录结构。
三个 unstable 协议不发:xdg-shell-unstable-v5、linux-dmabuf-unstable-v1、
tablet-unstable-v2 —— 它们**就是**那 13 个重叠符号,而且各自都已被同名的 stable
协议取代。上游留着旧写法只为兼容,一个包不可能两个都发。
staging/unstable 依赖 stable 也是实测的:两者都引用 xdg_toplevel_interface,
staging 还引用 zwp_tablet_tool_v2_interface。fork 内部用 path 依赖,所以
tarball 自洽 —— 但这带来一条消费者必须知道的规则:要 staging 就只写 staging,
同时写 stable 会报「既是 version dep 又是 path dep」。已写进 stable 的描述符。
体积在决定之前量过:65 个协议全部编出来 270KB 的 wl_interface 表,一个 4KB;
仓里那 3.5MB 几乎全是头文件,不 include 就不花钱。按协议拆会变成 65 个包换 270KB。
合成器不是所有东西都交给 GPU —— 损伤区域、光标混合、没有 EGL 时的回退路径,都走
pixman。cairo / X / Mesa 也都坐在它上面。
内联描述符,不需要 fork,而这一点值得说清楚:pixman 上游是**每个指令集一个静态库**,
各自用那个指令集的标志编一个 .c(meson.build:63 的 foreach)。包级 cflags 表达不了 ——
"-mssse3" 加到所有文件上,编译器就可能在 pixman-x86.c 的 CPUID 检查**之前**发出 SSSE3
指令,在老 CPU 上是非法指令异常,而这个库的全部设计就是为了避免这件事。
[build] flags 带 glob 正好表达它,而且不是新机制 —— compat.sdl2 早就用它把 -msse3
限定到单个文件。所以既不用 fork 也不用 build.mcpp。与 freedesktop.gldispatch 对照:
那边按架构变的是**编哪些文件**,这边变的是**给哪个文件什么标志**,前者才需要 build.mcpp。
实测确认标志没有外溢:
pixman-ssse3.o SSSE3 指令 2 ← 应当有
pixman-sse2.o SSSE3 指令 0
pixman.o SSSE3 指令 0
pixman-fast-path.o SSSE3 指令 0
pixman-x86.o SSSE3 指令 0
踩到一个静默的坑:PIXMAN_API 定义在 pixman-version.h.in 里,不在编译器头里。生成
version.h 时漏掉它,pixman.h 里每个 "PIXMAN_API void pixman_fill(...)" 都会解析成
未知标识符、声明整个丢失 —— 而报出来的错误是某个 SIMD 文件里的
"implicit declaration of function pixman_fill",与真正的原因隔了十万八千里。
测试做真合成:256x256 全部 65536 个像素与合成色一致,外加区域并集运算 —— 后者是
合成器每帧都要调的损伤跟踪,纯 C、无 SIMD。
Sunrisepeak
force-pushed
the
docs/closed-loop-verified-on-main
branch
from
August 30, 2026 08:22
4fd1948 to
ac93354
Compare
设计写完就动手了,§10 记录做出来的东西和**被实现推翻的部分** —— 后者更重要,每一条都是 被实测否掉的: G3「新增仓 0」错了一半。wayland-protocols 是另一个上游、另一个版本(1.49),而 mcpplibs/wayland 的 upstream/ 是 wayland 1.26.0 且 CI 逐字节 diff。一个仓一个上游一个 版本,所以必须独立 fork。新增仓 = 1。 G3「一个包装 65 个协议」也错了,而且原因不是体积是链接:staging 与 unstable 携带同一 协议的不同成熟度,scanner 生成同名符号。stable∩unstable=13,其余两两为 0,tier 内为 0 —— 所以是三个包,边界是上游自己的目录结构。由此还带出「三个已被取代的 unstable 协议 不能发」和「staging/unstable 依赖 stable,于是消费者不能同时写两个」。体积也量了,与 担心相反:65 个协议的 .c 只有 5910 行编出 270KB,3.5MB 几乎全是头文件。 G2 的形态被推翻两次。接上既有共享目录机制之后 GPU 到位了,但 NVIDIA 枚举两次 —— sentinel 补上 libXext 之后宿主那份 ICD 也能加载了。VK_DRIVER_FILES 能消掉重复(实测 恰好 1 个设备,而且它接受目录),但现在不能做:xim:mesa 只带一个 radeon ICD,声明它 等于拿「NVIDIA 重复」换「Intel 上完全没有 Vulkan」。 G4 pixman 的分类对了理由错了。文件确实自带 ifdef 门控,但编译标志是逐文件的,包级 cflags 表达不了。真正的答案是 [build] flags 带 glob。由此把 build.mcpp 的边界划细了 一层:按目标变的是「编哪些文件」用 build.mcpp,变的是「给哪个文件什么标志」用 glob。 沙箱脚本加了 GLES2 渲染并重跑:整条链从打开 DRM 节点走到读回自己画的像素,两个节点 都 64 128 191 255 分毫不差,而宿主的图形库在场且可达却一条都没赢。这是本轮之前做不到 的那一步 —— §19.4 那次止于 eglInitialize,能初始化不等于能画。
那张表是 2026-08-30 上午盘点时的状态,当天下午 G1/G2/G3/G4a 都实现了 —— 渲染链 (GLESv2)、wayland-protocols 三个 tier、pixman 都已进索引。表里留着盘点时的判断 是有价值的(它是当时的真实结论),但不标注就会误导,所以并排给出现状并指向 覆盖面设计 §10。 仍缺的是输入链:libxkbcommon、libinput、libudev/libseat。
那张表是当天上午盘点时的状态,下午 G1/G2/G3/G4a 都实现了。左列保留不是懒 —— 「当时缺什么」这个判断本身准确,而且它决定了后来做什么;右列给现状并指向覆盖面 设计 §10 的实现记录。 结论也从「渲染链和输入链都缺」变成「缺的是输入链」:libxkbcommon、libinput、 libudev/libseat。
libinput 链这三个,所以合成器的输入链从它们开始。 compat.mtdev(1.1.7)是判据最简单的那一档:五个 C 文件、三个公开头、没有生成物、 Linux 上没有需要探测的配置。内联描述符。 compat.libudev 用的是 **libudev-zero 1.0.5**,不是 systemd 的也不是 eudev 的。三个 实现里只有它同时【活着】且【可独立分发】:systemd 的不可分离,eudev 是 Gentoo 的 fork 但 2021 年就停更了。libudev-zero 直接读 /sys 而不是跟 udevd 说话 —— 这在 subos 里正是对的,因为那里没有 udevd,一个需要守护进程的实现只能在开发者机器上跑。 代价写在描述符里:没有 netlink 热插拔,udev_monitor 只给打开时 /sys 里的设备。 kind = "shared" 且用【规范 soname】libudev.so.1,是有意的:宿主的 libinput 或 payload 一旦已经链了这个 soname,就会复用链接图里的那一份 —— 与 compat.libdrm 依赖的 是同一条 soname 复用性质 —— 于是进程里恰好有一个 libudev,而且是这一个。 USB_IDS_PATH 定义为【空】。上游指向 <prefix>/share/hwdata/usb.ids,重定位后那是宿主的 文件;与 libgbm 的后端路径、libglvnd 的 vendor 目录同形,答案也一样。上游自己就是优雅 降级的(udev.c:95 打不开就 return 0),而 libinput 需要的【枚举】根本不碰它。 freedesktop.libevdev 是 fork,因为 event-names.h 是生成的 —— 1692 行,Python 脚本。 而且生成的确定性【只来自上游自带内核头】:meson.build:43 用的是 tarball 里那份 linux/input.h,不是 /usr/include。实测宿主头会给出不同的表(1664 行对 1692), 也就是说 libevdev_event_code_get_name 的答案会取决于编译它的机器。fork 的 CI 也按 自带头重新生成再 diff,理由相同。 三个测试都做真事:mtdev 走 slot 状态机,libudev 从 /sys 枚举到 20 个真实输入设备 并断言加载的不是宿主的那份,libevdev 查五张不同的生成表并做反向名字解析。
合成器要打开 DRM 和输入设备、还要成为 DRM master。桌面上这通常是 logind 的活; libseat 是「这台机器上由谁干」的抽象,wlroots 及其上的一切都链它。 上游三个后端里只建两个:seatd(跟 seatd 守护进程通信)和 builtin(自己当 seat manager)。**logind 刻意不建** —— 理由和 systemd 的 libudev 不进这个索引一样:不可 分离,建它意味着依赖 libsystemd,为一次 D-Bus 对话拖进一个发行版的构建输入。 代价点名而不是留给别人发现:在会话由 logind 管的机器上,链这份 libseat 的合成器不会 用它,而是退到 seatd 守护进程(SEATD_SOCK)或 builtin —— 那正是从 TTY 起合成器的 文档做法,也是这个索引能端到端支持的配置。 两处实现中发现的事: wscons.c 必须编。我第一版按「这是 NetBSD/OpenBSD 的控制台驱动」把它排除了 —— 它确实 是,但它自身按 __NetBSD__ 门控、在其他平台提供桩,而 seatd/seat.c:351 无条件调用 path_is_wscons。漏掉的表现是一个跟 BSD 控制台毫无关系的文件报 undefined reference。 libseat.h 没有 extern "C" 守卫(实测零处),所以 C++ 消费者必须自己包一层,否则每个 声明拿到 C++ 链接、每次调用都以 mangled 名字链接失败。测试里显式写出来,让这个要求 可见而不是等人踩。 源码列表是上游两张表的并集:private_files 与 server_files 重叠三个文件,meson 会去重 而 mcpp 不会 —— 重复列出就是重复符号的链接错误。
freedesktop.libxkbcommon 是 fork,因为 xkbcomp 的 parser 由 bison 从 parser.y 生成 (3960 行),而上游构建期就要求 bison >= 3.6。输出是 .y 文件的纯函数,所以签进仓、 CI 重生成再 diff,消费者构建不需要 bison。 生成时的 `-p _xkbcommon_` 前缀是承重的,不是装饰:它重命名 bison 发出的每一个符号。 不加它,这个 parser 会导出 bison 的默认名字,和同进程里任何另一个生成的 parser 撞车。 DFLT_XKB_CONFIG_ROOT 留空。libxkbcommon 只编译 keymap、自身不含任何布局;上游把 xkeyboard-config 的前缀烤进去,重定位后那是宿主的数据集。xkb_context_getenv 先查 环境变量,所以留空能让「数据集缺失」表现为「找不到 keymap」而不是悄悄用宿主的 —— 与 libgbm 的后端路径、libglvnd 的 vendor 目录同一立场。 HAVE_EACCESS 刻意不定义。utils.h 在这个宏下调用 eaccess(),但它自己不 include <unistd.h>,声明在不在作用域里取决于调用方碰巧先包了什么;上游的探测带 <unistd.h> 前缀所以答「有」。实测五个 TU 报 implicit declaration。不定义时 check_eaccess 返回 true —— 那是上游自己给「两个都没有的平台」准备的回退。 compat.libinput 是内联描述符,不需要 fork(源码在 meson 里列着,没有代码生成), 它是四包链的顶:libinput → libevdev / libudev / mtdev。Lua 插件和 libwacom 都关掉, 两者上游都是可选;LIBINPUT_QUIRKS_DIR 留空,理由同上。 三个测试都做真事:libxkbcommon 从字符串编译 keymap(正好跑通那个生成的 parser), keycode 24 → keysym q → UTF-8 "q",9 → Escape。 compat.libinput 的测试成员本轮先不登记:它同时需要 compat.*(自身/libudev/mtdev) 和 freedesktop.libevdev,而两者都在这个 checkout 里 —— 成员级 [indices] 是替换而非 合并,一个 path 也只能挂一个 namespace。等本 PR 合并、libevdev 发布之后再接上。
做到输入链最后一环时浮出一条与 Vulkan ICD 同形的结论:libxkbcommon 只编译 keymap、
自身不含布局,而一个【没有源码的纯数据包】怎么让消费者知道路径 —— mcpp-index 没有
这个机制,而且不该有。图形栈里所有运行期发现路径(GBM_BACKENDS_PATH、
__EGL_VENDOR_LIBRARY_DIRS、Vulkan 的 ICD 目录)一律由环境声明。
实测缺口:生态里已有 xim:libxkbcommon,但它的 payload 只有 bin/include/lib 和
share/{bash-completion,man} —— 不带 xkb 数据。所以 XKB_CONFIG_ROOT 无处可指,按名字
查 keymap 只能落到宿主的 /usr/share/X11/xkb,与 Vulkan 静默落到 llvmpipe 完全同构。
索引侧自己那一半已经做对:freedesktop.libxkbcommon 的 DFLT_XKB_CONFIG_ROOT 是空的,
数据集缺失会说「找不到 keymap」而不是悄悄用宿主的。
G4b/G5/G6 的状态一并更新:libxkbcommon 已做,libinput 描述符已做(测试成员待
libevdev 发布),libudev/libseat 已做且没有碰 systemd。
三处过时: §20.2 的缺口表还写着 libxkbcommon / libinput / libudev+libseat 仍缺 —— 当天都做完了。 结论也从「缺的是输入链」变成「渲染链和输入链都补齐了,只剩 xkeyboard-config 的数据集, 而它属于生态」。 覆盖面设计 §0.1 那句「新增仓 0」当时就写在判据旁边,实现推翻了它 —— 而且不止 G3: libevdev 的 event-names.h 和 libxkbcommon 的 bison parser 各自是必须先跑的生成器, 两者又都是独立上游独立版本。新增仓数量 = 3。判据本身没错,错的是「已有的 fork 装得下」 这个假设,而装不下的原因很具体:一个仓一个上游一个版本,因为 CI 要对着一份 release tarball 逐字节 diff upstream/。 交付表补上输入链五个包和九份 CN 镜像。
同一个干净房间里,渲染链走到读回像素之后,再问输入链两个问题:libevdev 能不能把 KEY_A 解析成名字(那是它 1692 行生成表的用途),xkbcommon 能不能把 keycode 24 编译 成 "q"(那是它 3960 行 bison parser 的用途)。两条都过。 只纳入 freedesktop.* 的两个:这个项目声明单一索引键,compat.libinput / libudev / mtdev / libseat 从已发布索引解析 —— 那是对的,也正是它们要等发布后才能进这个脚本 的原因。 顺带记一次诊断:上一次跑这个脚本时 freedesktop.libevdev 报 'download artifact missing',下载明明成功了 180 KB。本地清空 store 复现后真因是 'No space left on device' —— 磁盘 100% 满。差一点就去改一个没有问题的描述符。
Sunrisepeak
added a commit
that referenced
this pull request
Aug 30, 2026
* feat(libinput): 让输入链的顶端第一次真的被编译 compat.libinput 随 #294 进了索引,而它从未被编译过——没有测试成员消费它, 而没人编译的包不会编译失败。加上 tests/examples/libinput 之后一次构建暴露出 四类问题,都是"上游用 meson,我们不用"才会有的: 1. 缺 libinput-version.h。meson 从 .h.in 生成,libinput-private.h:45 无条件 include 它,所以 40 个源文件全挂。补成 generated_files。 2. config.h 只写了一半。HTTP_DOC_LINK / LIBINPUT_QUIRKS_OVERRIDE_FILE / LIBINPUT_PLUGIN_{LIB,ETC}DIR / HAVE_VERSIONSORT / HAVE_MTDEV 都缺。 HAVE_VERSIONSORT 尤其关键:不定义它,libinput-versionsort.h 会给出自己的 static strverscmp,而 glibc 已经 extern 声明过——是硬错误不是遮蔽。 3. include_dirs 少了包根。全树只有 libinput-plugin-mouse-wheel-lowres.c:31 写 `#include "src/evdev-frame.h"`,上游因为从项目根编译而免费拿到这个拼法。 4. typeof。util-mem.h:180 的 (typeof(*ptr_))_steal(ptr_) 是 GNU 关键字, -std=c11 下被当成未声明函数调用,cast 塌成 int,伤害落在十几个根本没提 typeof 的文件里,报成 -Wint-conversion。 c_standard = "gnu11" 不是解法:mcpp 收下这个字符串,仍然发 -std=c11。 这次是实测的——设过 gnu11,上面这些错误原样还在。所以走 -Dtypeof=__typeof__。 测试成员断言的是四包交接处(libudev 起 context、udev 枚举 seat、dispatch、 可 poll 的 fd),不断言能打开 /dev/input/event*——那需要权限,设 MCPP_RUN_INPUT_DEVICES=1 才要求。6 项全过。 顺带把 quirks 那段注释改准:LIBINPUT_QUIRKS_DIR 是有环境变量出口的 (libinput.c:1911),和 GBM_BACKENDS_PATH 同一形状,缺的是提供方而不是机制。 * docs: 记录 xkeyboard-config 跨索引闭环与 libinput 的四个 bug §10.9.1 xkeyboard-config 已落地(xim-pkgindex#732),含实现中改的两处 discovery 形状:XKB_CONFIG_ROOT 是标量所以用 op=set(表里第一个非列表项),以及 declare_xkb —— 声明变量和放置内容是两件事,只声明的那一版让变量指向不存在的目录。 §10.9.2 新增:libinput quirks 是同一形状的第三处。之前注释里写的「编译期路径」 不准确,libinput.c:1911 是 getenv 优先。所以不是死路,是缺提供方。 §10.10 G5 从「待接上」改为已做,并把测试成员抓出的四个 bug 列出来——它们全都是 「包进了索引但从没被编译过」造成的。另加一张发现变量总表,标出哪两行仍是空的。 * docs(libinput): 对齐两处与改动后不符的注释 c_standard 从 gnu11 改回 c11 之后,config.h 里 HAVE_C23_AUTO 那段还写着 「builds as gnu11」。 以及 config.h 顶部对 LIBINPUT_QUIRKS_DIR 的说明还停在「编译期路径」, 与文件头已改准的版本不一致——libinput.c:1911 是 getenv 优先、编译期值兜底。 * docs: 补记从已发布索引的复验,以及它抓到的 store 撞名陷阱 合并 xim#732 后又从「已发布索引 + 全新 subos + 沙箱」复验一遍——上一次用的是 --add-xpkg 的本地副本,证明力不同。 第一次复验数据没放进去,差点得出「包坏了」。真因是 store 里还留着本地验证时的 local:xkeyboard-config@2.48,而 store 查找忽略 namespace,(name, version) 撞上 就把 install() 静默跳过、payload 为空,config() 照常跑。 顺带记下:declare_xkb 的 os.isdir 守卫确实触发了,但那条 log.warn 在 install 输出里没出现(同一次输出里 xlings 自己的 [warn] 是打出来的)。所以 declare_dri / declare_gbm / declare_xkb 的警告都不能当诊断依赖。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
纯文档。#293 合并后补上「对着已发布的 main」那一次验证,并确认 §19.6 记的那处破坏已修复。
为什么要再跑一次
§19.4 原本记的是对分支
feat/freedesktop-egl的验证。按这份文档 §18.2 自己立的规矩——对着已发布的 artifact 验证,而不是本地打补丁的副本——那次不算权威。所以 #293 合并(
dc961cc)之后又跑了一遍,BRANCH=main,并且先把沙箱里上一轮的 store 清空:闭包与分支那次逐条一致。
破坏已修复,已复验
§19.6 记的是我自己造成的:为承载模块重命名先重切了 wayland 的 tag、后改描述符,于是在 #293 合并前 main 上
freedesktop.wayland@1.26.0装不下来。合并后复验:其他
§19.8 更新:#293 已合并;示例 09 的 mcpp PR #532 CI 20/20 通过(它只是示例,不阻塞任何东西)。