tawasuyu

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 1181Shell 82Rust 62Markdown 521515 Definitions

Etapa G: wayland + wayland-protocols CONSTRUIDAS (scanner desbloqueado)

Root cause real del bloqueo de wayland: NO era bug del wayland-scanner ni del XML
(ambos verificados OK). En el sandbox el scanner in-tree se compila ENLAZADO DINÁMICO
contra la musl (zig cc nativo no produce estático acá), y bajo musl-dinámico
`freopen(@OUTPUT@,"w",stdout)` queda roto por la copy-relocation de `stdout`: trunca el
archivo de salida pero manda el header generado a stdout → @OUTPUT@ vacío → `WL_SHM_FORMAT_*`
/ `wl_*` «undeclared» al compilar libwayland.

Fix: wayland-scanner-dup2-output.patch redirige la salida con `dup2(fd, STDOUT_FILENO)`
(nivel descriptor) en vez de `freopen` → robusto al modo de enlace. Verificado byte-a-byte:
salida idéntica a la del scanner estático (217484 B al archivo).

Segundo blocker (libwayland-server.so): libffi.a era no-PIC → `R_X86_64_PC32 ... recompile
with -fPIC` al ligarlo dentro de una .so. libffi ahora con --with-pic (superset; sigue
sirviendo para enlace estático). Mesa necesitará lo mismo en zlib/zstd/expat.

Restaura recipes/samurai.toml (lo necesita el stack adaptado de recipes/: libdrm/seatd/
wayland; las otras build-deps —meson/pkgconf/python3/expat/libffi— ya viven en recipes/).

Sellados: wayland (libwayland-{client,server,cursor,egl}.so + scanner + .pc),
wayland-protocols (XML + .pc). Queda mesa (iris-only).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

6fb7fd36d052a8b63f548e7061b25b3b9ab097fd · by sergio · (3 months ago) · parent 5126a8b67 · browse the tree at this commit

Semantic delta

No definition changed: this change is text, documentation or data.

5 files · +87 −19

diff --git a/docs/14-mesa-stack.md b/docs/14-mesa-stack.md
index 7a4613ef..2296e8b9 100644
--- a/docs/14-mesa-stack.md
+++ b/docs/14-mesa-stack.md
@@ -66,12 +66,13 @@ Construidas y selladas en el store (`hammer --store store build recipes/<x>.toml
 | `meson` | 🟢 **built** | Python puro: copia `mesonbuild/`+wrapper, sin wheel/gpep517; `python3` runtime-dep |
 | `libdrm` | 🟢 **built** | core-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 |
-| `wayland` | 🔴 **bloqueada — root cause confirmado** | `wayland-scanner` genera headers de protocolo **vacíos** → `WL_SHM_FORMAT_*`/`wl_*` undeclared. **Confirmado (2026-06-27):** la fuente extraída `work/sources/wayland-*/protocol/wayland.xml` está COMPLETA (165075 B), expat OK, no es ordenamiento de samurai (`-j1` falla igual). El scanner recibe el XML completo pero **emite vacío, sale 0** (por stdin expat: «no element found» = lee 0 bytes). ⇒ **bug de runtime del wayland-scanner compilado static-musl** (falla con zig default Y 0.13.0). **FIX:** el scanner es herramienta de build-time (no se shippea) ⇒ construirlo **nativo (host/glibc)** y apuntar libwayland al scanner externo; construir sólo libwayland-{client,server} con musl/zig. Alt: patchear la lectura de input del scanner para musl. |
-| `wayland-protocols` | ⏸ **bloqueada** | build-depende de wayland (necesita wayland-scanner) |
-| `mesa` | 🟡 **pendiente** | recortar a iris-only (sin LLVM/Vulkan/X11); depende de libdrm✓+wayland+wayland-protocols+expat✓+zlib✓+zstd✓+python3✓+mako(⚪) |
+| `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` | 🟢 **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). |
+| `wayland-protocols` | 🟢 **built** | sólo instala XML + `.pc`; build-dep wayland (su meson chequea wayland-scanner) |
+| `mesa` | 🟡 **pendiente** | recortar a iris-only (sin LLVM/Vulkan/X11); depende de libdrm✓+wayland✓+wayland-protocols✓+expat✓+zlib✓+zstd✓+python3✓+mako(⚪). Anticipá PIC en zlib/zstd/expat (como libffi) al ligar las `.so` de Mesa. |
 
-meson anda con zig cc (clang 21) sobre proyectos meson — validado con libdrm y seatd. El cuello real
-restante es **wayland** (scanner) y luego **mesa**.
+meson anda con zig cc (clang 21) sobre proyectos meson — validado con libdrm/seatd/wayland. El cuello
+real restante es **mesa** (recorte iris-only + PIC de sus deps C estáticas).
 
 ## Lado tawasuyu (recetas Cargo, después de Mesa)
 
diff --git a/recipes/libffi.toml b/recipes/libffi.toml
index 6b81bb8a..e8b759bf 100644
--- a/recipes/libffi.toml
+++ b/recipes/libffi.toml
@@ -1,5 +1,8 @@
 # libffi 3.5.2 — interfaz de llamada a función foránea (C). Lib base: python, muchos -sys crates.
 # De-Alpinizada: compiler=gcc, configure-split, estático.
+# --with-pic: el .a estático lleva objetos PIC ⇒ se puede enlazar dentro de bibliotecas COMPARTIDAS
+# (libwayland-server.so / Mesa lo exigen; sin PIC: «R_X86_64_PC32 ... recompile with -fPIC»). PIC
+# es superset: sigue sirviendo para el enlace estático de exes. (2026-06-27, stack gráfico tawasuyu.)
 name    = "libffi"
 version = "3.5.2"
 [source]
@@ -11,6 +14,6 @@ target   = "x86_64-linux-musl"
 link     = "static"
 flags    = []
 [build.phases]
-configure = './configure --build=$CBUILD --host=$CHOST --prefix=/usr --disable-shared --enable-static --disable-exec-static-tramp'
+configure = './configure --build=$CBUILD --host=$CHOST --prefix=/usr --disable-shared --enable-static --with-pic --disable-exec-static-tramp'
 compile   = 'make'
 install   = 'make DESTDIR=/out install'
diff --git a/recipes/samurai.toml b/recipes/samurai.toml
new file mode 100644
index 00000000..affb5d72
--- /dev/null
+++ b/recipes/samurai.toml
@@ -0,0 +1,24 @@
+# samurai 1.3 — clon C de ninja (lo que usa Alpine como `ninja`). Build-tool del stack meson
+# (libdrm/wayland/mesa lo invocan como backend). Provee /usr/bin/samu + symlink /usr/bin/ninja.
+# zig 0.13.0: con el zig default (0.16/clang21) el binario musl miscompila y falla en runtime
+# con "reallocarray: No error information" — el patrón conocido (binutils/elfutils/flex).
+name    = "samurai"
+version = "1.3"
+
+[source]
+tarball = "https://github.com/michaelforney/samurai/releases/download/1.3/samurai-1.3.tar.gz"
+sha256  = "1bc020a9e133432df51911ac71cc34322f828934d9a2282ba2916d88c15976af"
+
+[build]
+compiler    = "zig-cc"
+target      = "x86_64-linux-musl"
+link        = "static"
+zig_version = "0.13.0"
+
+[build.phases]
+compile = 'make CFLAGS="-O2"'
+install = '''
+set -e
+make install PREFIX="/usr" DESTDIR="/out"
+ln -s samu /out/usr/bin/ninja
+'''
diff --git a/recipes/wayland-scanner-dup2-output.patch b/recipes/wayland-scanner-dup2-output.patch
new file mode 100644
index 00000000..1302a3b1
--- /dev/null
+++ b/recipes/wayland-scanner-dup2-output.patch
@@ -0,0 +1,42 @@
+Redirige la salida del scanner al @OUTPUT@ a nivel de descriptor (dup2) en vez de freopen(stdout).
+
+En hammer el wayland-scanner se compila ENLAZADO DINÁMICO contra la musl del sandbox (zig cc
+nativo no produce estático aquí), y bajo musl-dinámico `freopen(argv[2], "w", stdout)` queda roto
+por la copy-relocation de `stdout`: trunca/crea el archivo de salida PERO no redirige el fd que usa
+`printf()`, así que el header generado sale por stdout y el @OUTPUT@ queda VACÍO. Resultado: al
+compilar libwayland, `WL_SHM_FORMAT_*` / `wl_*_interface` / `wl_callback_*` aparecen «undeclared»
+(headers de protocolo vacíos). Verificado a fondo: el binario ESTÁTICO escribe bien al archivo; el
+DINÁMICO no — mismo source, flags y config.h.
+
+`dup2(outfd, STDOUT_FILENO)` redirige el descriptor 1 a nivel de kernel: TODAS las escrituras a
+stdout (cualquiera sea el objeto FILE por la copy-reloc) terminan en el archivo. Robusto frente al
+modo de enlace. La salida queda idéntica byte-a-byte a la del scanner estático.
+
+--- a/src/scanner.c
++++ b/src/scanner.c
+@@ -36,6 +36,8 @@
+ #include <getopt.h>
+ #include <limits.h>
+ #include <unistd.h>
++#include <fcntl.h>
++#include <sys/stat.h>
+
+ #if HAVE_LIBXML
+ #include <libxml/parser.h>
+@@ -2138,11 +2140,14 @@ int main(int argc, char *argv[])
+ 				strerror(errno));
+ 			exit(EXIT_FAILURE);
+ 		}
+-		if (freopen(argv[2], "w", stdout) == NULL) {
++		int outfd = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0644);
++		if (outfd < 0 || dup2(outfd, STDOUT_FILENO) < 0) {
+ 			fprintf(stderr, "Could not open output file: %s\n",
+ 				strerror(errno));
+ 			fclose(input);
+ 			exit(EXIT_FAILURE);
+ 		}
++		if (outfd != STDOUT_FILENO)
++			close(outfd);
+ 	}
+
+ 	/* initialize protocol structure */
diff --git a/recipes/wayland.toml b/recipes/wayland.toml
index 19690544..b0168cb0 100644
--- a/recipes/wayland.toml
+++ b/recipes/wayland.toml
@@ -1,26 +1,24 @@
 # wayland 1.25.0 — libwayland-client/server + wayland-scanner. Lo enlaza mirada (smithay) y Mesa
 # (plataforma wayland). Proyecto meson. Sin docs/tests; sin dtd_validation para no arrastrar
 # libxml2. Core enlaza libffi; wayland-scanner usa expat (ambos ya en hammer). zig 0.13.0 por el
-# patrón musl (evita miscompilación del zig default). link=dynamic: shared libs.
+# patrón musl (evita miscompilación del zig default). link=dynamic: shared libs (Mesa las liga).
 #
-# ⚠ BLOQUEADA (2026-06-27) — ROOT CAUSE CONFIRMADO: el build de libwayland falla porque
-# wayland-scanner genera headers de protocolo VACÍOS (`WL_SHM_FORMAT_ARGB8888`, … undeclared).
-# Verificado: la fuente extraída `work/sources/wayland-*/protocol/wayland.xml` está COMPLETA
-# (165075 bytes), expat está OK (estático, sin símbolos glibc-only), y NO es ordenamiento de
-# samurai (-j1 falla igual). El scanner recibe el XML completo pero emite vacío y sale 0; por
-# stdin expat dice «no element found» = lee 0 bytes. ⇒ es un BUG DE RUNTIME del wayland-scanner
-# compilado static-musl en el lab (falla con zig default Y 0.13.0 — no es la regresión de zig).
-#
-# FIX recomendado: wayland-scanner es herramienta de BUILD-TIME (no se shippea al rootfs) ⇒
-# construirlo NATIVO (host/glibc) y apuntar el build de libwayland al scanner externo
-# (`find_program('wayland-scanner')` / wrap de meson), construyendo sólo libwayland-{client,server}
-# con musl/zig. Alternativa: patchear la lectura de input del scanner para musl. Ver docs/14 §Estado.
+# ROOT CAUSE RESUELTO (2026-06-27) — el build de libwayland fallaba con `WL_SHM_FORMAT_*`/`wl_*`
+# «undeclared»: los headers de protocolo salían VACÍOS. NO es bug del scanner ni del XML (ambos
+# OK). Causa real: en el sandbox 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 pero manda el header a stdout,
+# dejando el @OUTPUT@ vacío. FIX: `wayland-scanner-dup2-output.patch` redirige la salida con
+# `dup2(fd, STDOUT_FILENO)` (a nivel de descriptor) en vez de `freopen` ⇒ robusto al modo de enlace.
+# Verificado byte-a-byte: salida idéntica a la del scanner estático (217484 B al archivo). Ver
+# docs/14 §Estado de build y el encabezado del .patch.
 name    = "wayland"
 version = "1.25.0"
 
 [source]
 tarball = "https://gitlab.freedesktop.org/wayland/wayland/-/releases/1.25.0/downloads/wayland-1.25.0.tar.xz"
 sha256  = "c065f040afdff3177680600f249727e41a1afc22fccf27222f15f5306faa1f03"
+patches = ["wayland-scanner-dup2-output.patch"]
 
 [build]
 compiler    = "zig-cc"