docs(examples): 09 —— 系统级图形栈,用推荐方式做完整条链 (#527) - #532
Closed
Sunrisepeak wants to merge 6 commits into
Closed
Conversation
#527 §1 的问法是「宿主库直接动态链接能不能原样用」,拿 `-L/usr/lib -lgbm` 做复现。这个方向是错的:mcpp 运行时不依赖 Host 是设计决策(#527 A3),产物 拿到的是 mcpp 自己算出搜索路径的私有 PT_INTERP,所以 `-L/usr/lib` 不是缺失 的支持,而是错误用法,mcpp 在构建期就会说出来。 该回答的是功能需求本身能不能做到。这个示例就是答案:合成器 / Mesa 面向的 扩展 / GBM 显存管理所需要的那条链,按推荐方式声明依赖跑通。 [target.'cfg(linux)'.dependencies.compat] libgbm = "2026.08.29" libdrm = "2026.08.30" egl = "2026.08.30" wayland = "2026.08.30" 这是全部配置。src/main.cpp 用的是上游原样的头和 API,没有任何 mcpp 特有的 东西 —— 别处照着这些库写的代码搬过来就能编。 它做的是真事而不是「符号能链上」:打开 /dev/dri/renderD128,由该 fd 建出真 的 gbm_device,交给 eglGetPlatformDisplay(EGL_PLATFORM_GBM_KHR, ...) 并初始 化 EGL。实测两个节点(nvidia-drm / simpledrm)都到 EGL 1.5, vendor Mesa Project。对照 §1.2 里的 gbm_create_device(-1) 返回 NULL —— 那个用例即使在 宿主上跑通也没证明栈可用。 零 Host 是核过的,不是断言的:用产物自己的私有加载器解析完整闭包,11 条全部 落在 registry 内,没有一条在 /usr/lib 或 /lib64。其中 libexpat、libffi、 libGLdispatch 是传递依赖,mcpp.toml 里谁都没写 —— 而 §1.4 断言的正是这层 级联在私有加载器里解不开。声明四个依赖把 11 条都解掉了。 README 另外如实记了一处缺口:Vulkan 不在本示例内,形态也不同 —— compat.vulkan-runtime 仍从 /usr/lib/*、/lib64 收割宿主 ICD,因为 Vulkan 驱动 属于 GPU 厂商,生态里还没有可绑的 payload。GBM/KMS/EGL/Wayland 这条没有这 个边。
mcpplibs/mcpp-index#289 replaced the date-stamped versions with the upstream projects' own release numbers, and made compat.libdrm a source build. The example follows: libdrm 2026.08.30 -> 2.4.134 (now built from source) libgbm 2026.08.29 -> 25.0.7 (Mesa's version) egl 2026.08.30 -> 1.7.0 (libglvnd's version) The README's 'The packages' section said none of them vendors a source tree, which is no longer true, and the closure listing is re-measured against the published index. The interesting line is the first one: libdrm.so.2 resolves to the project's OWN build output rather than the payload copy Mesa was linked against — a soname already in the link map is reused, so the consumer's copy wins and Mesa's GBM allocates through it. That is why a library the payload also carries can still be built from source.
mcpplibs/mcpp-index#290 replaced compat.wayland with freedesktop.wayland and freedesktop.wayland-server, built from source out of mcpplibs/wayland. They are two packages because they are two SONAMEs and Mesa's libEGL_mesa has DT_NEEDED on both, and because mcpp links every library target in a package against all of that package's sources — one package cannot emit two libraries with disjoint contents. So the -lwayland-server escape hatch this example used to demonstrate is gone: a compositor asks for the server package by name. The closure is re-measured. Four of the twelve entries are now this project's own build output — libdrm, libffi and both wayland libraries — and the first of those is the interesting one: Mesa's libgbm has an absolute RUNPATH into the payload's libdrm and still binds to ours, because a soname already in the link map is reused.
compat.egl bound xim:libglvnd, and its own comment recorded why that was wrong: libglvnd IS a separable project, so by the criterion it should have been a source build; it stayed a binding for effort alone. It is now freedesktop.egl, out of mcpplibs/libglvnd, and GBM is the only binding left in this example -- which is the honest picture, since GBM is the one that genuinely fails the test. That package also carries libGLdispatch.so.0, as a sibling workspace member reached by a path dependency rather than a second index entry, because being the one dispatch point in a process is what GLVND is for. The program now prints __EGL_VENDOR_LIBRARY_DIRS beside GBM_BACKENDS_PATH. Both loaders in this stack dlopen something the environment has to point them at, and the EGL package compiles in an EMPTY default rather than upstream's: a wrong compiled-in path is worse than none, because it would make a missing declaration load the HOST's driver into a sandboxed process, silently and successfully. Measured end to end, with every library attributed through the binary's own loader -- libEGL.so.1, libGLdispatch.so.0, libdrm.so.2 and both libwayland libraries come from this project's build output, libgbm.so.1 from compat-x-libgbm (the binding), and nothing from a host path. eglInitialize reaches "EGL 1.5, vendor Mesa Project" through the source-built dispatch.
import khronos.egl / import freedesktop.wayland.{client,server}. A module name
is global and permanent in a way a package name is not, so it names the
INTERFACE's owner: freedesktop owns the wayland protocol, Khronos owns EGL and
libglvnd merely implements it. That is why freedesktop.egl the PACKAGE exports
khronos.egl the MODULE, and the mismatch is deliberate.
The closure listing was re-measured rather than edited: libEGL.so.1 and
libGLdispatch.so.0 now come from this build too, where before they came from
compat-x-egl and the xim:libglvnd payload. Also records that the same program
was built and run from scratch inside `xlings subos use … --sandbox --gpu`,
where /usr is still the host's and its libEGL/libgbm/libdrm/libwayland are all
present and reachable -- and lost anyway. "Nothing from the host" is a claim
about what WINS, not about what exists, and only the second version of that
claim matches a user's machine.
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.
examples/09-graphics-stack—— 系统级图形栈按 mcpp 推荐方式做完整一条链。为什么是示例而不是特性
#527 §1 的问法是「宿主库直接动态链接能不能原样用」,复现用的是:
这个方向是错的。mcpp 运行时不依赖 Host 是设计决策(#527 A3:保证可验证/可复现 +
跨发行版),产物拿到的是 mcpp 自己算出搜索路径的私有
PT_INTERP。所以-L/usr/lib -lgbm不是缺失的支持,而是错误用法,mcpp 在构建期就明说了。toolchain = "system"/sysroot = "system"这两个提案按 A1/A3 暂不做。该回答的是功能需求本身能不能做到 —— §1 点名的合成器、Mesa 面向的扩展、GBM 显存
管理。能,这个 PR 就是那个答案。
内容
这是全部配置。
src/main.cpp用上游原样的头和 API(<gbm.h>、<xf86drm.h>、<EGL/egl.h>、<wayland-client.h>),没有任何 mcpp 特有的东西 —— 别处照着这些库写的代码搬过来就能编。
它做的是真事,不是「符号能链上」:打开
/dev/dri/renderD128,由该 fd 建出真的gbm_device,交给eglGetPlatformDisplay(EGL_PLATFORM_GBM_KHR, ...)并初始化EGL。
对照 §1.2 的
gbm_create_device(-1)返回0(即NULL)—— 那个用例即使在宿主上跑通也没证明栈可用。
零 Host 是核过的
用产物自己的私有加载器解析完整闭包,11 条全部落在 registry 内,没有一条在
/usr/lib或/lib64:其中
libexpat、libffi、libGLdispatch是传递依赖,mcpp.toml里谁都没写—— 而 §1.4 断言的正是这层级联在私有加载器里解不开(「
libgbm.so.1依赖的libdrm.so.2... 程序仍会启动失败」)。声明四个依赖把 11 条都解掉了。如实记的一处缺口
README 里写明:Vulkan 不在本示例内,形态也不同 ——
compat.vulkan-runtime仍从/usr/lib/*、/lib64收割宿主 ICD,因为 Vulkan 驱动属于 GPU 厂商,生态里还没有可绑的 payload。GBM/KMS/EGL/Wayland 这条没有这个边。
依赖
四个包已在 mcpp-index(mcpplibs/mcpp-index@21d8dd0e),
xim:mesa的GBM_BACKENDS_PATH发现层已在 xim-pkgindex(#713, bb97b614)。本 PR 只有examples/和docs/,不动构建代码。Refs #527