gioser

sergio/takana

> Una distribución Linux construida con un laboratorio funcional y hermético en el > sótano, y una terminal mutable, clásica y anárquica en el piso de arriba — diseñada > desde el suelo para que una IA programadora entienda, modifique y co…

TOML 1572Shell 203Rust 109Markdown 993728 Sutichaykuna

⎇ 4148ba4e02310090bb3c844c5942fe7e0251f106 docs/14-mesa-stack.md Markdown · 130 siq'ikuna · 10.0 KB Ñawpa willay ch'uya

takana etapa 5b: los 59 docs de diseño, runbooks y ADR 97ceb7241 · Sergio ·

1# SDD 14 — Stack gráfico (Mesa iris) para el escritorio tawasuyu
2
3> **Estado:** cola importada (2026-06-27). Contraparte en takana del salto
4> demo→producción de arje: el rootfs de producto necesita **Mesa** para que el
5> greeter real de mirada (`mirada-greeter-llimphi`) tome el DRM tras el handoff
6> del splash. Seed de producción: `tawasuyu/03_ukupacha/arje/seeds/arje-tawasuyu.card.json`
7> (ente `display-manager-mesa`). Ver su contrato rootfs en `seeds/README.md`.
8
9## Por qué iris-only (sin LLVM, sin Vulkan) — y por qué Mesa **24.0.9**
10
11> ⚠ **Pin de versión (2026-06-27):** «iris sin LLVM» SÓLO vale hasta **Mesa 24.0.x**. Desde 24.1 el
12> driver `iris` pasó a requerir **intel-clc** (kernels OpenCL-C internos compilados en build-time) ⇒
13> `with_clc` ⇒ libclc + clang/LLVM. Bisección confirmada: 24.0.9 = último con `with_intel_clc =
14> intel-clc=='enabled'` (default disabled) ⇒ con iris-only y sin Vulkan/rusticl, `with_clc=FALSE`,
15> nada de LLVM. Por eso la receta pinea **24.0.9** (no la 26.1.1 importada de Alpine). Para Mesa
16> ≥24.1 habría que construir LLVM+clang+libclc primero — otra rama del track.
17
18El target inmediato es una laptop **Intel Iris Xe**. En Mesa ≤24.0 el driver gallium **`iris`
19NO necesita LLVM** (eso es `radeonsi`/`llvmpipe`). Recortando el build de Alpine
20(que trae el kitchen-sink) a iris-only se elimina la cola pesada — clang, llvm,
21libclc, spirv-llvm-translator, rust-bindgen, Vulkan, X11/glx:
22
23```
24-Dgallium-drivers=iris   -Dvulkan-drivers=   -Dllvm=disabled
25-Dplatforms=wayland      -Dglx=disabled      -Dexpat=enabled
26```
27
28Eso deja un Mesa que sólo arrastra deps que takana ya tiene o son chicas.
29(Para AMD/NVIDIA-nouveau más adelante: `radeonsi`/`nouveau` sí piden LLVM →
30otra rama del track.)
31
32## DAG de dependencias (estado contra el corpus actual)
33
34| Tier | Receta | meson? | Estado en takana | Notas |
35|---|---|---|---|---|
36| build | `python3` | — | 🟢 en store | meson/mako lo usan |
37| build | `meson` | — | 🟡 incoming | importada de Alpine 1.11.1; pyproject, necesita python3 |
38| build | `samurai` (≡ninja) | — | 🟡 incoming | 1.3, clon C de ninja (lo que usa Alpine) |
39| build | `pkgconf` | — | 🟢 receta | sustituto de pkg-config |
40| build | `bison` / `flex` | — | 🟢 receta | mesa genera parsers |
41| build | `mako` (módulo py) | — | ⚪ por verificar | templating de codegen de mesa; pip/source sobre python3 |
42| lib | `expat` `zlib` `zstd` `libffi` | — | 🟢 receta | deps de wayland/mesa |
43| lib | `libdrm` | sí | 🟡 incoming | 2.4.134; **fijar `-Dgallium`? no** — libdrm es agnóstico; `link=dynamic` |
44| lib | `wayland` | sí | 🟡 incoming | 1.25.0; deps expat+libffi; `-Ddocumentation=false` |
45| lib | `wayland-protocols` | sí | 🟡 incoming | 1.48; sólo datos (XML) + meson; dep wayland |
46| lib | `seatd` (→`libseat`) | sí | 🟡 incoming | la sesión de mirada abre el DRM vía libseat |
47| **top** | `mesa` | sí | 🟡 incoming | 26.1.1; recortar a iris-only (arriba); deps: libdrm, wayland, wayland-protocols, expat, zlib, zstd, python3+mako |
48
49🟢 listo · 🟡 importada, **falta adaptar** (traducir `abuild-meson`/`_abuild_phase`
50de Alpine a fases takana + `meson`/`samurai` directos, como hizo `elfutils`) · ⚪ por crear.
51
52## Trabajo de adaptación por receta (lo real)
53
54Las recetas en `recipes/incoming/` son **puntos de partida** de `import-alpine`:
55traen los parches musl de Alpine (lo valioso) pero usan los helpers de abuild que
56el lab de takana no tiene. Cada una necesita, mínimo:
57
581. Reemplazar `abuild-meson` por `meson setup output --prefix=/usr --buildtype=release <-Dflags>`
59   y `_abuild_phase`/`DESTDIR=/out` por las fases `configure`/`compile`/`install` de takana.
602. `compiler = "zig-cc"`, `target = "x86_64-linux-musl"`, `link = "dynamic"` (son libs compartidas).
613. Declarar las deps de build en el grafo de takana (no como `makedepends` de Alpine).
624. Verificar `zig_version` si zig 0.14 miscompila (patrón de `elfutils`/`binutils`/`flex`: fijar 0.13.0).
63
64Orden de build (hojas→raíz): `meson`+`samurai` → `libdrm`,`wayland` → `wayland-protocols`,`seatd` → `mesa`.
65
66## Estado de build (2026-06-27)
67
68Construidas y selladas en el store (`takana --store store build recipes/<x>.toml`):
69
70| Receta | Estado | Nota de adaptación |
71|---|---|---|
72| `samurai` | 🟢 **built** | `zig_version=0.13.0` (el default miscompila → `reallocarray` falla en runtime) |
73| `meson` | 🟢 **built** | Python puro: copia `mesonbuild/`+wrapper, sin wheel/gpep517; `python3` runtime-dep |
74| `libdrm` | 🟢 **built** | core-only (todas las GPU helper disabled) → evita libpciaccess; iris usa libdrm core |
75| `seatd` | 🟢 **built** | `-Dwerror=false` (musl `CMSG_NXTHDR` dispara `-Wsign-compare`); logind disabled, backend seatd |
76| `libffi` | 🟢 **built** | `--with-pic`: el `.a` lleva objetos PIC ⇒ enlazable dentro de `.so` (lo exige libwayland-server/Mesa; sin PIC: `R_X86_64_PC32 ... recompile with -fPIC`) |
77| `wayland` | 🟢 **built** | `link=dynamic` (Mesa liga las `.so`). **Root cause del bloqueo RESUELTO (2026-06-27):** los headers de protocolo salían vacíos NO por bug del scanner ni del XML, sino porque el `wayland-scanner` in-tree se compila **enlazado dinámico** contra la musl (zig cc nativo no hace estático acá) y bajo musl-dinámico `freopen(@OUTPUT@,"w",stdout)` queda roto por la copy-relocation de `stdout` → trunca el archivo y manda el header a stdout. FIX: `wayland-scanner-dup2-output.patch` redirige con `dup2(fd, STDOUT_FILENO)` (nivel descriptor) en vez de `freopen`. Verificado byte-a-byte: salida idéntica a la del scanner estático (217484 B). |
78| `wayland-protocols` | 🟢 **built** | sólo instala XML + `.pc`; build-dep wayland (su meson chequea wayland-scanner) |
79| `markupsafe` `mako` `packaging` | 🟢 **built** | módulos Python puros (copia a site-packages, sin pip/wheel). `mako`=codegen de Mesa; `markupsafe`=dep de mako (cae a `_native`); `packaging` porque el chequeo de versión de mako usa `packaging.version` y Python 3.12 ya no trae `distutils` |
80| `zlib` `zstd` `expat` | 🟢 **built (PIC)** | `-fPIC`/`--with-pic` para enlace dentro de `.so` (como libffi). Mesa al final ligó libz/libzstd **compartidas de la base Alpine**; libexpat.a (PIC) sí se enlazó estática |
81| `mesa` | 🟢 **built** | **iris-only, Mesa 24.0.9** (no 26.1: desde 24.1 iris exige intel-clc→LLVM; ver arriba). `-Dllvm=disabled -Dintel-clc=disabled`, sin Vulkan/glx/rusticl/codecs. Instala `dri/iris_dri.so` + `libEGL/libgbm/libGLESv2/libglapi` + egl/gbm/glesv2 `.pc`. Fixes: `PYTHONPATH` al site-packages (configure+compile) para mako; `libffi` en deps (lo pide `wayland-client.pc`); `mesa-version-script-comma.patch` (version-script en forma coma, que zig cc no reordena). Runtime: el rootfs necesita `libz.so.1`/`libzstd.so.1`/`libexpat`(o estático) + libdrm/wayland |
82
83meson anda con zig cc (clang 21) sobre proyectos meson — validado con libdrm/seatd/wayland/mesa. **El
84stack gráfico está COMPLETO.** Lo que falta es el lado tawasuyu (mirada-greeter dinámico contra Mesa)
85y el ensamblado del rootfs de producto con las `.so` compartidas (libz/libzstd/libdrm/wayland/mesa).
86
87## Lado tawasuyu (recetas Cargo, después de Mesa)
88
89Modeladas sobre `recipes/arje-zero.toml` (fuente = monorepo tawasuyu a commit fijado, build hermético):
90
91| Receta | bin | link | dep gráfica |
92|---|---|---|---|
93| `arje-splash` | `/usr/lib/arje/arje-splash` | static-musl | sólo DRM dumb-buffer (sin Mesa) |
94| `net-bring-up` | `/usr/lib/arje/net-bring-up` | static-musl | ninguna |
95| `mirada-greeter` | `/usr/bin/mirada-greeter` | **dynamic** 🟢 **built** | dlopen: EGL/GLES/GBM (mesa) + wayland; link: libpam |
96| `mirada-compositor` | `/usr/bin/mirada-compositor` | **dynamic** 🟢 **built** | link: gbm/seat/udev/input/pixman/xkbcommon; dlopen: EGL/wayland/drm |
97
98`mirada-greeter` 🟢 **CONSTRUIDO Y SELLADO** (Cargo, 314 crates incl. todo el stack wgpu/winit/llimphi
99para musl; PIE dinámico). DT_NEEDED real = sólo `libpam.so.0` + musl; **EGL/GLES/GBM/wayland/iris se
100dlopen-ean en runtime** (wgpu/winit) ⇒ el rootfs debe TENERLAS presentes pero no son NEEDED. Fixes de
101la receta:
102- **atspi/accesskit** (a11y, vía `accesskit_winit`): `zbus-lockstep-macros` `#[validate]` PANICA
103  («File has no extension.») porque escanea `xml/` de atspi-common y hace `.extension().expect()` en
104  el SUBDIR `xml/schemas/` (zbus-lockstep-macros/src/lib.rs:147). Fix = fase `compile` custom que
105  apunta `LOCKSTEP_XML_PATH` a un dir con sólo los `.xml`. (Más limpio a futuro: hacer accesskit
106  OPCIONAL en llimphi-ui — el greeter no necesita a11y.)
107- **PAM**: auth-core → `pam`/`pam-sys` hace bindgen sobre `security/pam_appl.h` ⇒ nueva receta
108  `linux-pam` 1.6.1 (libpam.so + headers, build limpio en musl con gcc de Alpine).
109
110`mirada-compositor` 🟢 **CONSTRUIDO Y SELLADO** (Cargo, ~255 crates incl. smithay 0.7 para musl; PIE
111dinámico). Es el compositor que maneja DRM/GBM/EGL/libseat/libinput directo y dentro del cual corre
112`mirada-greeter` como cliente. smithay (default features) enlaza `drm-sys`→libdrm, `gbm-sys`→mesa,
113`libseat-sys`→seatd, `input-sys`→libinput, `libudev-sys`→**libudev-zero** (libudev sin udevd, encaja
114con el no-systemd de arje), + `xkbcommon`→**libxkbcommon** y **pixman** (link, no dlopen). Por eso el
115**stack de entrada** nuevo: `libinput` + `libevdev` + `mtdev` (config.sub viejo parcheado al moderno) +
116`libudev-zero` + `libxkbcommon` + `pixman`. `foreign-av` NO enlaza ffmpeg (spawnea el binario en
117runtime) ⇒ no hizo falta construir ffmpeg. NEEDED del binario: libgbm/libseat/libudev/libinput/
118libpixman-1/libxkbcommon + musl.
119
120**El stack de sesión gráfica está COMPLETO**: Mesa(iris) + wayland + el stack de entrada +
121mirada-compositor + mirada-greeter, todo sellado. Falta el ensamblado del rootfs (todas las `.so` +
122config/módulos PAM + datos xkb de xkeyboard-config) y arrancar la sesión.
123
124Los otros dos (arje-splash, net-bring-up) no dependen de Mesa.
125
126## Hecho cuando
127
128`takana bootstrap product` produce un rootfs que, con la seed `arje-tawasuyu`,
129arranca `arje-zero` → splash → `mirada-greeter` toma el DRM con Mesa/iris, sin
130caer a texto. Verificación: boot en QEMU (con virgl/GPU) o metal en la laptop Iris Xe.

14-mesa-stack.md

SDD 14 — Stack gráfico (Mesa iris) para el escritorio tawasuyu

Estado: cola importada (2026-06-27). Contraparte en takana del salto demo→producción de arje: el rootfs de producto necesita Mesa para que el greeter real de mirada (mirada-greeter-llimphi) tome el DRM tras el handoff del splash. Seed de producción: tawasuyu/03_ukupacha/arje/seeds/arje-tawasuyu.card.json (ente display-manager-mesa). Ver su contrato rootfs en seeds/README.md.

Por qué iris-only (sin LLVM, sin Vulkan) — y por qué Mesa 24.0.9

⚠ Pin de versión (2026-06-27): «iris sin LLVM» SÓLO vale hasta Mesa 24.0.x. Desde 24.1 el driver iris pasó a requerir intel-clc (kernels OpenCL-C internos compilados en build-time) ⇒ with_clc ⇒ libclc + clang/LLVM. Bisección confirmada: 24.0.9 = último con with_intel_clc = intel-clc=='enabled' (default disabled) ⇒ con iris-only y sin Vulkan/rusticl, with_clc=FALSE, nada de LLVM. Por eso la receta pinea 24.0.9 (no la 26.1.1 importada de Alpine). Para Mesa ≥24.1 habría que construir LLVM+clang+libclc primero — otra rama del track.

El target inmediato es una laptop Intel Iris Xe. En Mesa ≤24.0 el driver gallium iris NO necesita LLVM (eso es radeonsi/llvmpipe). Recortando el build de Alpine (que trae el kitchen-sink) a iris-only se elimina la cola pesada — clang, llvm, libclc, spirv-llvm-translator, rust-bindgen, Vulkan, X11/glx:

-Dgallium-drivers=iris   -Dvulkan-drivers=   -Dllvm=disabled
-Dplatforms=wayland      -Dglx=disabled      -Dexpat=enabled

Eso deja un Mesa que sólo arrastra deps que takana ya tiene o son chicas. (Para AMD/NVIDIA-nouveau más adelante: radeonsi/nouveau sí piden LLVM → otra rama del track.)

DAG de dependencias (estado contra el corpus actual)

TierRecetameson?Estado en takanaNotas
buildpython3—🟢 en storemeson/mako lo usan
buildmeson—🟡 incomingimportada de Alpine 1.11.1; pyproject, necesita python3
buildsamurai (≡ninja)—🟡 incoming1.3, clon C de ninja (lo que usa Alpine)
buildpkgconf—🟢 recetasustituto de pkg-config
buildbison / flex—🟢 recetamesa genera parsers
buildmako (módulo py)—⚪ por verificartemplating de codegen de mesa; pip/source sobre python3
libexpat zlib zstd libffi—🟢 recetadeps de wayland/mesa
liblibdrmsí🟡 incoming2.4.134; fijar -Dgallium? no — libdrm es agnóstico; link=dynamic
libwaylandsí🟡 incoming1.25.0; deps expat+libffi; -Ddocumentation=false
libwayland-protocolssí🟡 incoming1.48; sólo datos (XML) + meson; dep wayland
libseatd (→libseat)sí🟡 incomingla sesión de mirada abre el DRM vía libseat
topmesasí🟡 incoming26.1.1; recortar a iris-only (arriba); deps: libdrm, wayland, wayland-protocols, expat, zlib, zstd, python3+mako

🟢 listo · 🟡 importada, falta adaptar (traducir abuild-meson/_abuild_phase de Alpine a fases takana + meson/samurai directos, como hizo elfutils) · ⚪ por crear.

Trabajo de adaptación por receta (lo real)

Las recetas en recipes/incoming/ son puntos de partida de import-alpine: traen los parches musl de Alpine (lo valioso) pero usan los helpers de abuild que el lab de takana no tiene. Cada una necesita, mínimo:

  1. Reemplazar abuild-meson por meson setup output --prefix=/usr --buildtype=release <-Dflags> y _abuild_phase/DESTDIR=/out por las fases configure/compile/install de takana.
  2. compiler = "zig-cc", target = "x86_64-linux-musl", link = "dynamic" (son libs compartidas).
  3. Declarar las deps de build en el grafo de takana (no como makedepends de Alpine).
  4. Verificar zig_version si zig 0.14 miscompila (patrón de elfutils/binutils/flex: fijar 0.13.0).

Orden de build (hojas→raíz): meson+samurai → libdrm,wayland → wayland-protocols,seatd → mesa.

Estado de build (2026-06-27)

Construidas y selladas en el store (takana --store store build recipes/<x>.toml):

RecetaEstadoNota de adaptación
samurai🟢 builtzig_version=0.13.0 (el default miscompila → reallocarray falla en runtime)
meson🟢 builtPython puro: copia mesonbuild/+wrapper, sin wheel/gpep517; python3 runtime-dep
libdrm🟢 builtcore-only (todas las GPU helper disabled) → evita libpciaccess; iris usa libdrm core
seatd🟢 built-Dwerror=false (musl CMSG_NXTHDR dispara -Wsign-compare); logind disabled, backend seatd
libffi🟢 built--with-pic: el .a lleva objetos PIC ⇒ enlazable dentro de .so (lo exige libwayland-server/Mesa; sin PIC: R_X86_64_PC32 ... recompile with -fPIC)
wayland🟢 builtlink=dynamic (Mesa liga las .so). Root cause del bloqueo RESUELTO (2026-06-27): los headers de protocolo salían vacíos NO por bug del scanner ni del XML, sino porque el wayland-scanner in-tree se compila enlazado dinámico contra la musl (zig cc nativo no hace estático acá) y bajo musl-dinámico freopen(@OUTPUT@,"w",stdout) queda roto por la copy-relocation de stdout → trunca el archivo y manda el header a stdout. FIX: wayland-scanner-dup2-output.patch redirige con dup2(fd, STDOUT_FILENO) (nivel descriptor) en vez de freopen. Verificado byte-a-byte: salida idéntica a la del scanner estático (217484 B).
wayland-protocols🟢 builtsólo instala XML + .pc; build-dep wayland (su meson chequea wayland-scanner)
markupsafe mako packaging🟢 builtmódulos Python puros (copia a site-packages, sin pip/wheel). mako=codegen de Mesa; markupsafe=dep de mako (cae a _native); packaging porque el chequeo de versión de mako usa packaging.version y Python 3.12 ya no trae distutils
zlib zstd expat🟢 built (PIC)-fPIC/--with-pic para enlace dentro de .so (como libffi). Mesa al final ligó libz/libzstd compartidas de la base Alpine; libexpat.a (PIC) sí se enlazó estática
mesa🟢 builtiris-only, Mesa 24.0.9 (no 26.1: desde 24.1 iris exige intel-clc→LLVM; ver arriba). -Dllvm=disabled -Dintel-clc=disabled, sin Vulkan/glx/rusticl/codecs. Instala dri/iris_dri.so + libEGL/libgbm/libGLESv2/libglapi + egl/gbm/glesv2 .pc. Fixes: PYTHONPATH al site-packages (configure+compile) para mako; libffi en deps (lo pide wayland-client.pc); mesa-version-script-comma.patch (version-script en forma coma, que zig cc no reordena). Runtime: el rootfs necesita libz.so.1/libzstd.so.1/libexpat(o estático) + libdrm/wayland

meson anda con zig cc (clang 21) sobre proyectos meson — validado con libdrm/seatd/wayland/mesa. El stack gráfico está COMPLETO. Lo que falta es el lado tawasuyu (mirada-greeter dinámico contra Mesa) y el ensamblado del rootfs de producto con las .so compartidas (libz/libzstd/libdrm/wayland/mesa).

Lado tawasuyu (recetas Cargo, después de Mesa)

Modeladas sobre recipes/arje-zero.toml (fuente = monorepo tawasuyu a commit fijado, build hermético):

Recetabinlinkdep gráfica
arje-splash/usr/lib/arje/arje-splashstatic-muslsólo DRM dumb-buffer (sin Mesa)
net-bring-up/usr/lib/arje/net-bring-upstatic-muslninguna
mirada-greeter/usr/bin/mirada-greeterdynamic 🟢 builtdlopen: EGL/GLES/GBM (mesa) + wayland; link: libpam
mirada-compositor/usr/bin/mirada-compositordynamic 🟢 builtlink: gbm/seat/udev/input/pixman/xkbcommon; dlopen: EGL/wayland/drm

mirada-greeter 🟢 CONSTRUIDO Y SELLADO (Cargo, 314 crates incl. todo el stack wgpu/winit/llimphi para musl; PIE dinámico). DT_NEEDED real = sólo libpam.so.0 + musl; EGL/GLES/GBM/wayland/iris se dlopen-ean en runtime (wgpu/winit) ⇒ el rootfs debe TENERLAS presentes pero no son NEEDED. Fixes de la receta:

mirada-compositor 🟢 CONSTRUIDO Y SELLADO (Cargo, ~255 crates incl. smithay 0.7 para musl; PIE dinámico). Es el compositor que maneja DRM/GBM/EGL/libseat/libinput directo y dentro del cual corre mirada-greeter como cliente. smithay (default features) enlaza drm-sys→libdrm, gbm-sys→mesa, libseat-sys→seatd, input-sys→libinput, libudev-sys→libudev-zero (libudev sin udevd, encaja con el no-systemd de arje), + xkbcommon→libxkbcommon y pixman (link, no dlopen). Por eso el stack de entrada nuevo: libinput + libevdev + mtdev (config.sub viejo parcheado al moderno) + libudev-zero + libxkbcommon + pixman. foreign-av NO enlaza ffmpeg (spawnea el binario en runtime) ⇒ no hizo falta construir ffmpeg. NEEDED del binario: libgbm/libseat/libudev/libinput/ libpixman-1/libxkbcommon + musl.

El stack de sesión gráfica está COMPLETO: Mesa(iris) + wayland + el stack de entrada + mirada-compositor + mirada-greeter, todo sellado. Falta el ensamblado del rootfs (todas las .so + config/módulos PAM + datos xkb de xkeyboard-config) y arrancar la sesión.

Los otros dos (arje-splash, net-bring-up) no dependen de Mesa.

Hecho cuando

takana bootstrap product produce un rootfs que, con la seed arje-tawasuyu, arranca arje-zero → splash → mirada-greeter toma el DRM con Mesa/iris, sin caer a texto. Verificación: boot en QEMU (con virgl/GPU) o metal en la laptop Iris Xe.