@@ -10,16 +10,29 @@ mcpp run
1010```
1111== the graphics stack, resolved from the index ==
1212 GBM_BACKENDS_PATH = …/subos/default/usr/lib/gbm
13- wl_display_create 0x2e8d8be0
13+ wl_display_create 0x3f798be0
1414-- DRM node -> GBM device -> EGL display --
1515 /dev/dri/renderD128
1616 drm driver nvidia-drm
17- gbm_create_device 0x2e942f30
18- eglGetPlatformDisplay 0x2e9bd390
17+ gbm_create_device 0x3f802f30
18+ gbm_bo_create (driver declined this format/usage)
19+ eglGetPlatformDisplay 0x3f87d5b0
20+ eglInitialize EGL 1.5, vendor Mesa Project
21+ /dev/dri/card0
22+ drm driver simpledrm
23+ gbm_create_device 0x3f802f30
24+ gbm_bo_create 256x256 stride=1024 modifier=0xffffffffffffff
25+ eglGetPlatformDisplay 0x3f87d5b0
1926 eglInitialize EGL 1.5, vendor Mesa Project
2027done.
2128```
2229
30+ That is one real run on a two-node machine, kept unabridged because the
31+ difference between the nodes is the point: ` simpledrm ` allocated the buffer and
32+ reported the driver's own stride and modifier, while NVIDIA's GBM backend
33+ declined that format/usage combination. Both are the libraries answering — this
34+ is the stack working, not a smoke test.
35+
2336## What this example is for
2437
2538System-level graphics work — a Wayland compositor, a Mesa-facing extension,
@@ -37,9 +50,9 @@ answer: the whole chain, done the recommended way, declaring dependencies.
3750
3851``` toml
3952[target .'cfg(linux)' .dependencies .compat ]
40- libgbm = " 2026.08.29 "
41- libdrm = " 2026.08.30 "
42- egl = " 2026.08.30 "
53+ libdrm = " 2.4.134 "
54+ libgbm = " 25.0.7 "
55+ egl = " 1.7.0 "
4356wayland = " 2026.08.30"
4457```
4558
@@ -48,29 +61,30 @@ That is the entire configuration. `src/main.cpp` then includes `<gbm.h>`,
4861upstream APIs — nothing in it is mcpp-specific, so code written against these
4962libraries anywhere else compiles here unchanged.
5063
51- And it does the real thing rather than proving a symbol resolves: it opens
52- ` /dev/dri/renderD128 ` , builds a genuine ` gbm_device ` from that fd, hands it to
53- ` eglGetPlatformDisplay(EGL_PLATFORM_GBM_KHR, …) ` and initializes EGL against a
54- real driver. A ` gbm_create_device(-1) ` on an invalid fd returns ` NULL ` and
55- tells you nothing about whether the stack works; this reaches
56- ` EGL 1.5, vendor Mesa Project ` .
64+ And it does the real thing rather than proving a symbol resolves: it opens a
65+ DRM node, builds a genuine ` gbm_device ` from that fd, ** allocates actual GPU
66+ memory** with ` gbm_bo_create ` and reads back the stride and modifier the driver
67+ chose, then hands the device to
68+ ` eglGetPlatformDisplay(EGL_PLATFORM_GBM_KHR, …) ` and initializes EGL. A
69+ ` gbm_create_device(-1) ` on an invalid fd returns ` NULL ` and tells you nothing
70+ about whether the stack works; this reaches ` EGL 1.5, vendor Mesa Project ` .
5771
5872## Checking the claim
5973
60- "Host-free" is easy to assert, so it is worth resolving the artifact's closure
61- through the private loader it actually uses and looking at every path:
74+ "Host-free" is easy to assert, so resolve the artifact's closure through the
75+ private loader it actually uses and look at every path:
6276
6377``` bash
6478BIN=target/x86_64-linux-gnu/* /bin/graphics-stack
6579" $( readelf -p .interp $BIN | grep -o ' /.*ld-linux[^ ]*' ) " --list $BIN
6680```
6781
6882```
69- compat-x-egl/2026.08.30/…/libEGL .so.1
70- compat-x-libdrm/2026.08.30 /…/libdrm .so.2
71- compat-x-libgbm/2026.08.29 /…/libgbm .so.1
72- compat-x-wayland/2026.08.30/ …/libwayland-client.so.0
73- compat-x-wayland/2026.08.30/ …/libwayland-server.so.0
83+ <project>/target/.../bin/libdrm .so.2 <- built from source, by this build
84+ compat-x-libgbm/25.0.7 /…/libgbm .so.1
85+ compat-x-egl/1.7.0 /…/libEGL .so.1
86+ compat-x-wayland/…/libwayland-client.so.0
87+ compat-x-wayland/…/libwayland-server.so.0
7488xim-x-expat/2.6.2/lib/libexpat.so.1
7589xim-x-gcc/16.1.0/lib64/libgcc_s.so.1
7690xim-x-glibc/2.44/lib64/libc.so.6
@@ -79,29 +93,55 @@ xim-x-libffi/3.4.4/lib/libffi.so.8
7993xim-x-libglvnd/1.7.0.1/lib/libGLdispatch.so.0
8094```
8195
82- Every entry is under the registry; none is under ` /usr/lib ` or ` /lib64 ` . Note
83- the bottom half especially — ` libexpat ` , ` libffi ` and ` libGLdispatch ` are
84- * transitive* : nothing in ` mcpp.toml ` names them. They are what a directly
85- linked ` libgbm.so.1 ` cascades into, and resolving that cascade is exactly what
86- the host path cannot do from inside a private loader. Declaring the four
87- dependencies resolved all eleven.
96+ Nothing is under ` /usr/lib ` or ` /lib64 ` . Two things in that list are worth
97+ reading closely.
98+
99+ ** The first line.** ` libdrm.so.2 ` resolves to this project's own build output,
100+ not to the ` xim-x-libdrm ` the Mesa payload was linked against — even though
101+ ` libgbm.so.1 ` has a DT_NEEDED on that soname and an absolute RUNPATH pointing
102+ into the payload. The consumer links libdrm directly, so it is mapped first,
103+ and Mesa's GBM binds to it: the ` gbm_bo_create ` above ran through it.
104+
105+ ** The bottom half.** ` libexpat ` , ` libffi ` and ` libGLdispatch ` are * transitive* —
106+ nothing in ` mcpp.toml ` names them. They are what a directly linked
107+ ` libgbm.so.1 ` cascades into, and resolving that cascade is exactly what a host
108+ ` -L/usr/lib ` cannot do from inside a private loader.
88109
89110## The packages
90111
91- None of them vendors a source tree. Mesa, libdrm, libglvnd and wayland are
92- already in the ecosystem (` xim:mesa ` , ` xim:libdrm ` , ` xim:libglvnd ` ,
93- ` xim:wayland ` ), so each package is a thin binding: it declares the ecosystem
94- package it needs and exposes that payload's headers and libraries to the
95- compiler. Building second copies would put two ` libgbm.so.1 ` — or two
96- ` libdrm.so.2 ` , or a second EGL dispatch library — in a process that already
97- loads Mesa's.
98-
99- | package | what it gives you |
100- | ---| ---|
101- | ` compat.libgbm ` | ` gbm_create_device ` , ` gbm_bo_create ` — buffers out of a DRM device |
102- | ` compat.libdrm ` | ` drmModeGetResources ` , ` drmModeAddFB2 ` , ` drmModeSetCrtc ` — the KMS side |
103- | ` compat.egl ` | ` eglGetPlatformDisplay(EGL_PLATFORM_GBM_KHR, …) ` — rendering onto them |
104- | ` compat.wayland ` | client and server libraries for the display protocol |
112+ Two of them are built from source and two bind the ecosystem's Mesa, and the
113+ split is not arbitrary. A library is built from source when upstream ships it
114+ as a ** separable unit** ; it is bound when it is an internal build target of a
115+ project the ecosystem already owns, where building it would mean forking that
116+ project.
117+
118+ | package | | what it gives you |
119+ | ---| ---| ---|
120+ | ` compat.libdrm ` | source | ` drmModeGetResources ` , ` drmModeAddFB2 ` , ` drmModeSetCrtc ` — the KMS side |
121+ | ` compat.libgbm ` | binds ` xim:mesa ` | ` gbm_create_device ` , ` gbm_bo_create ` — buffers out of a DRM device |
122+ | ` compat.egl ` | binds ` xim:libglvnd ` | ` eglGetPlatformDisplay(EGL_PLATFORM_GBM_KHR, …) ` — rendering onto them |
123+ | ` compat.wayland ` | binds ` xim:wayland ` | client and server libraries for the display protocol |
124+
125+ libdrm passes the test — an independent freedesktop project with its own
126+ releases — so it is compiled here, five translation units with no dependencies
127+ at all. GBM fails it: ` src/gbm/meson.build ` is ` link_with: [libloader] ` , and
128+ ` libloader ` wants ` idep_mesautil ` , roughly 120 TUs of Mesa's internal utility
129+ library for one function. It is also a * loader* , and the backends it dlopens
130+ are Mesa's own, so built apart from Mesa it would have nothing to load.
131+
132+ ** A payload carrying the same library is not a reason to bind** , which is worth
133+ saying because it looks like one. Mesa's ` libgbm.so.1 ` has a DT_NEEDED on
134+ ` libdrm.so.2 ` and an absolute RUNPATH into the payload's copy — and in this
135+ program that RUNPATH loses. A soname already in the link map is reused, so
136+ ld.so never searches for it again: the ` libdrm.so.2 ` this project linked is
137+ mapped first, exactly one is loaded, and Mesa's GBM allocated the buffer above
138+ through it. That only holds because the package builds a * shared* library with
139+ the canonical soname; merged into the consumer as objects there would be two
140+ copies of libdrm's internal state over one set of file descriptors.
141+
142+ ` compat.egl ` is a binding for a duller reason: libglvnd IS separable, but
143+ ` libEGL.so ` also needs its Python-generated dispatch stubs, ` winsys_dispatch `
144+ and the whole of ` libGLdispatch.so ` , so it has not been done yet.
105145
106146One honest gap, since "Mesa/Vulkan" usually get named together: Vulkan is not
107147part of this example and is not in the same state. ` compat.vulkan-runtime `
0 commit comments