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 1572Shell 203Rust 109Markdown 993728 Definitions

⎇ ce2668598e4d8b60e5e070a0e422cd1dd12f0033 recipes/gtk4.toml TOML · 113 lines · 8.5 KB History raw

gtk4: el `--export-dynamic` venia del .pc de gmodule, y estatico destapo un bug de upstream 29897ab2b · Sergio ·

1# gtk4 4.18.6 — el toolkit de GUI. meson static, backend SOLO wayland (sin X11/broadway/win/mac),
2# renderer GL vía libepoxy (vulkan disabled), todo lo opcional off (demos/tests/docs/cups/gstreamer/
3# introspection). Corona el stack gráfico C del lab: con esto el corpus puede producir apps GTK reales.
4# Deps = cierre transitivo .pc completo (pkg-config estático resuelve Requires.private).
5name    = "gtk4"
6version = "4.18.6"
7license = "LGPL-2.1-or-later"
8
9[source]
10tarball = "https://download.gnome.org/sources/gtk/4.18/gtk-4.18.6.tar.xz"
11sha256  = "e1817c650ddc3261f9a8345b3b22a26a5d80af154630dedc03cc7becefffd0fa"
12
13[build]
14compiler = "zig-cc"
15target   = "x86_64-linux-musl"
16link     = "static"
17
18[build.phases]
19# GTK4 construye libgtk.a (static_library 'gtk') Y libgtk-4.so; las tools linkean la .so con libgtk_dep,
20# imposible en el lab static-musl. Parche 1: que las tools usen libgtk_static_dep (la .a). El sed es seguro:
21# "libgtk_dep" NO es substring de "libgtk_static_dep" ⇒ no toca las que ya usan el estático.
22#
23# ── Parche 2 (2026-08-27): NO construir `libgtk-4.so` en absoluto ────────────────────────────────
24# `gtk/meson.build` declara DOS objetivos hermanos con llamadas explícitas: `static_library('gtk')` y
25# `shared_library('gtk-4')`. Por ser explícita, `-Ddefault_library=static` NO la suprime — no hay
26# flag que valga. Y esa .so era el ÚNICO objetivo compartido de los 10 que enlaza la receta (los otros
27# 9 son ejecutables), así que arrastraba CINCO archivos .a sin PIC —libtiff, libfreetype, libfontconfig,
28# libjpeg, libpng16— y moría con 13930 `relocation … recompile with -fPIC`. Un ejecutable sí puede
29# enlazar una .a no-PIC; una .so no.
30#
31# Se apaga con `build_by_default: false` + `install: false` en ESE bloque (sed acotado por rango, que
32# toca 1 de los 10 `install: true` del fichero). No se borra la declaración: `pkg_config.generate(libgtk)`
33# la sigue necesitando para emitir el `.pc` con `-lgtk-4`, que es el nombre que la fase install fabrica
34# como archive GORDO. Nada la enlaza: los usuarios de `libgtk_dep` son demos/tests/testsuite/examples y
35# los backends de impresión y media, TODOS desactivados por las flags de abajo… SALVO UNO.
36#
37# ⚠ `build_by_default: false` NO BASTA POR SÍ SOLO, y el primer intento falló por esto: ninja
38# construye igual un objetivo si algo DEPENDE de él. `modules/printbackends/meson.build` declara
39# `shared_module('printbackend-file')` con `dependencies: libgtk_dep` —y el propio fuente avisa
40# «The 'file' print backend cannot be disabled»: no hay opción de meson que lo quite, está fuera de
41# los `if` de cpdb/cups—. Ese módulo arrastraba `libgtk-4.so` de vuelta al grafo y la .so volvía a
42# enlazarse en [995/997] con los mismos 13930 errores PIC. Por eso se apaga TAMBIÉN.
43# En todo el árbol hay 5 objetivos compartidos: `libgtk-4.so`, printbackend-{cpdb,cups,file} y
44# media-gstreamer. cpdb/cups/media ya los quitan las flags; los otros dos, estos dos seds.
45#
46# ── Parche 3 (2026-08-31): `gmodule-no-export-2.0`, o los 8 ejecutables salen DINÁMICOS ─────────
47# `link = "static"` era mentira y los 8 `tools/` enlazaban musl dinámicamente (audit estricto).
48# Huella que lo delata sin mirar el build: `readelf --dyn-syms` daba **21 475 entradas** contra
49# ~2 700 de un binario dinámico normal ⇒ eso es `--export-dynamic`, no un enlace corriente.
50#
51# NO venía del meson de gtk —ahí no aparece la palabra— sino de un `.pc` DE DEPENDENCIA:
52# `gmodule-2.0.pc` trae literalmente `Libs: -Wl,--export-dynamic`, y `meson.build:426` pedía
53# `dependency('gmodule-2.0')`. El wrapper de cc del lab (`sandbox.rs:597`) tira el `-static`
54# inyectado ante `--export-dynamic` ⇒ lo ponía el lab y lo sacaba el lab, por un flag heredado.
55#
56# **No hace falta parchear el `.pc` de glib**: upstream ya publica la misma librería sin el flag.
57# `gmodule-no-export-2.0.pc` tiene el `-lgmodule-2.0 -pthread` de verdad, y los otros dos
58# (`gmodule-2.0`, `gmodule-export-2.0`) son wrappers que sólo hacen `Requires:` sobre él y añaden
59# `-Wl,--export-dynamic`. Pedir el `no-export` es la palanca prevista, no un apaño.
60#
61# Cuesta cero acá: `gmodule_dep` se declara una vez y se usa en un solo sitio (`gtk/meson.build:1002`),
62# y los dos consumidores de `g_module_open` —`gtkbuilderscope.c` y `gtkmain.c`— son caminos de
63# `dlopen` que un binario estático musl no puede tomar igual.
64#
65# ⚠ REGLA GENERAL: cualquier receta que enlace gmodule hereda `--export-dynamic` y pierde el
66# `-static` SIN AVISO. Si `link = "static"` no pega y hay glib de por medio, mirar los `.pc` de las
67# deps antes que el build del proyecto.
68#
69# ── Parche 4: el bug de upstream que SÓLO existe en estático ────────────────────────────────────
70# Con los 8 ejecutables ya estáticos, TODOS morían con SIGSEGV (rc=139) hasta en `--help`, donde el
71# binario dinámico imprimía el uso. No era el enlace: es un fallo de gtk. Backtrace con gdb:
72#     g_module_symbol (module=0x0, symbol_name="gtk_progress_get_type") at gmodule.c:855
73#     _gtk_module_has_mixed_deps (module_to_check=0x0) at gtk/gtkmain.c:474
74#     do_pre_parse_initialization () at gtk/gtkmain.c:498
75#     gtk_init_check () at gtk/gtkmain.c:635
76# `_gtk_module_has_mixed_deps(NULL)` hace `module = g_module_open (NULL, 0)` y pasa el resultado a
77# `g_module_symbol` **sin comprobarlo**. En musl ESTÁTICO `dlopen(NULL)` devuelve NULL siempre ⇒
78# desreferencia de nulo en el offset 8, en el arranque de `gtk_init_check`. Con libc dinámica
79# `dlopen(NULL)` funciona y el bug no se ve nunca: es de los que sólo existen de un lado.
80# El parche es la comprobación que falta. Devolver FALSE es lo correcto además de lo seguro: en un
81# binario estático no hay módulos cargables, así que no puede haber símbolos de GTK 2/3 mezclados.
82# `gtk/gtkbuilderscope.c:188` tiene el otro `g_module_open(NULL,…)` del árbol y ése SÍ está bien
83# (devuelve NULL a un getter y va guardado por `g_module_supported()`).
84#
85# ⚠ El artefacto deja de traer `libgtk-4.so`. Es lo coherente con `link = "static"` y con la fase
86# install, que ya fabricaba `libgtk-4.a` como el producto real; la .so se construía e instalaba sin
87# que nadie la usara. Las colas wlr/gnome tienen sus PROPIAS recetas de gtk4 y no se ven afectadas.
88configure = '''
89sed -i "s/dependency('gmodule-2.0'/dependency('gmodule-no-export-2.0'/" meson.build
90sed -i 's|  if (g_module_symbol (module, "gtk_progress_get_type", &func))|  if (module == NULL)\n    return FALSE;\n&|' gtk/gtkmain.c
91sed -i 's/libgtk_dep/libgtk_static_dep/g' tools/meson.build
92sed -i "/^libgtk = shared_library('gtk-4',/,/^)/ s/^  install: true,$/  install: false,\n  build_by_default: false,/" gtk/meson.build
93sed -i "/^shared_module('printbackend-file',/,/^)/ s/^  install: true,$/  install: false,\n  build_by_default: false,/" modules/printbackends/meson.build
94PKG_CONFIG_PATH=/usr/lib/pkgconfig PYTHONPATH=/usr/lib/python3.12/site-packages meson setup output --prefix=/usr --buildtype=release --wrap-mode=nodownload --prefer-static -Ddefault_library=static -Dwayland-backend=true -Dx11-backend=false -Dbroadway-backend=false -Dwin32-backend=false -Dmacos-backend=false -Dvulkan=disabled -Dintrospection=disabled -Dbuild-demos=false -Dbuild-testsuite=false -Dbuild-tests=false -Dbuild-examples=false -Dmedia-gstreamer=disabled -Dprint-cups=disabled -Dprint-cpdb=disabled -Dcloudproviders=disabled -Dsysprof=disabled -Dtracker=disabled -Dcolord=disabled -Df16c=disabled -Ddocumentation=false -Dman-pages=false -Dc_args=-Wno-error=date-time
95'''
96compile   = "PYTHONPATH=/usr/lib/python3.12/site-packages ninja -C output"
97# meson instala solo libgtk-4.so y genera convenience-libs THIN (gtk/gdk/gsk por separado, referencian
98# los .o por ruta → inútiles fuera del build dir). Fusiono los tres en UN archive GORDO libgtk-4.a (embebe
99# todos los .o) para que `-lgtk-4` + `-static` linkee de verdad en el lab static-musl.
100install = '''
101PYTHONPATH=/usr/lib/python3.12/site-packages DESTDIR=/out meson install -C output --no-rebuild
102rm -f /out/usr/lib/libgtk-4.a
103cd output
104objs=""
105for a in $(find . -name '*.a'); do
106  d=$(dirname "$a"); b=$(basename "$a")
107  for o in $(cd "$d" && zig ar t "$b"); do objs="$objs $d/$o"; done
108done
109zig ar rcs /out/usr/lib/libgtk-4.a $objs
110'''
111
112[deps]
113build = ["meson", "samurai", "python3", "pkgconf", "glib", "cairo", "pango", "gdk-pixbuf", "graphene", "libepoxy", "wayland", "wayland-protocols", "libxkbcommon", "libdrm", "fontconfig", "harfbuzz", "fribidi", "libpng", "pixman", "freetype", "expat", "libffi", "pcre2", "zlib", "libjpeg-turbo", "libtiff", "mesa"]