Files
takana/recipes/expat-shared.toml
SergioandClaude Opus 5 f8f679d038 corpus: expat-shared y libffi-shared cierran la fuga al Alpine del lab
sway es `link = "dynamic"` A PROPÓSITO —un compositor dlopea los drivers DRI de mesa en runtime— y
sale con doce NEEDED. Nueve los cubría la clausura (pixman, drm, evdev, input, udev, wayland-server,
wlroots, xkbcommon, libc), porque esas recetas ya son dinámicas. Los otros tres —libz.so.1,
libexpat.so.1, libffi.so.8— venían de recetas `--disable-shared`, así que NINGÚN artefacto sellado
producía ese `.so` y el rootfs los resolvía contra el sysroot Alpine DEL LAB.

POR QUÉ ERA PEOR QUE UNA DEP FALTANTE. Una dep ausente falla ruidosamente. Ésta no: el lab NO entra
en `hash_inputs`, así que el store daba el artefacto por bueno mientras el binario sólo arrancaba en
una máquina que tuviera Alpine debajo. La fuga era invisible para todo el sistema de medición.

`zlib-shared` ya existía en el corpus y sólo faltaba declararla. `expat-shared` y `libffi-shared` son
nuevas, calcadas del patrón: autotools con --enable-shared, sin el truco de --whole-archive que
zlib-shared necesita porque SU configure aborta bajo zig cc. SONAMEs verificados contra lo que pide
el ELF: libexpat.so.1, libffi.so.8, libz.so.1. Exactos.

NO se tocó `link` en las canónicas: entra en `hash_inputs` y habría re-hasheado expat, libffi y todo
lo que los lista en deps —fontconfig, dbus, mesa, glib, python3, los crates `-sys`— cientos de
recetas selladas por libs que ya están bien. El nombre `*-shared` es distinto del canónico, así que
conviven. Verificado antes de construir: recalculadas las 794 recetas, **0 hashes cambiados**, sólo
las 2 nuevas.

Van al CORPUS y no a incoming-wlr/ porque la resolución de deps es hermano→padre: una receta del
corpus no ve una cola. Es donde ya viven zlib-shared, fontconfig-shared, freetype-shared…

VERIFICADO CON PÍXELES, no con el log. Rootfs rehidratado desde cero (126/126), CERO ficheros de
`.dev-fs/alpine`. Cero «Error relocating». La captura tiene el MISMO sha256 que la de las libs de
Alpine: 177fea396caa9dca, 1280x720, 383 colores. Tercera vez que la evidencia sale bit a bit igual
al cambiar la procedencia — la soberanía no costó ni un píxel.

Perfil: escritorio-sway 126/128. Faltan strace (linux-headers del lab) y rsync (404 de upstream).

QUEDA UN RESTO: el loader `/lib/ld-musl-x86_64.so.1` todavía se toma del host. `recipes/musl.toml`
existe en el corpus pero está EN DEUDA y fuera de todo perfil — mismo agujero de declaración, un
nivel más abajo.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016v9ozVm44p6DB7EMXeZK4o
2026-08-26 18:42:11 +00:00

52 lines
3.4 KiB
TOML

# expat-shared 2.8.1 — variante DINÁMICA de expat.
#
# ── POR QUÉ EXISTE ─────────────────────────────────────────────────────────────────────────────
# El expat canónico (recipes/expat.toml) es `--disable-shared`: sólo `libexpat.a`, que es lo que
# quiere el enlace estático del corpus. Pero `sway` es `link = "dynamic"` A PROPÓSITO —un compositor
# dlopea los drivers DRI de mesa en runtime, así que estático no sirve— y sale con
# `NEEDED libexpat.so.1`. Ese `.so` no lo producía NINGÚN artefacto sellado ⇒ el rootfs hidratado
# caía al `libexpat.so.1` del sysroot Alpine del lab. Es la misma fuga de soberanía que documenta
# `zlib-shared`, y con el agravante de [[lab-fuera-de-hash-inputs]]: el lab NO entra en `hash_inputs`,
# así que la dependencia era invisible para el store — el artefacto se daba por bueno y sólo
# arrancaba en una máquina que tuviera Alpine debajo.
#
# ── POR QUÉ UNA VARIANTE Y NO `link = "dynamic"` EN LA CANÓNICA ────────────────────────────────
# `link` entra en `hash_inputs`. Tocar `recipes/expat.toml` re-hashearía expat y, en cascada, todo
# lo que lo lista en deps — fontconfig, dbus, mesa, los crates `-sys`… cientos de recetas selladas
# a reconstruir por una lib que ya está bien. El patrón `*-shared` deja intacta la canónica: el
# nombre es DISTINTO (`expat-shared` no pisa a `expat`), así que conviven en el mismo store y cada
# consumidor toma la que necesita. Mismo criterio que zlib-shared / freetype-shared / libpng-shared.
#
# ── EN EL CORPUS, NO EN UNA COLA ───────────────────────────────────────────────────────────────
# La resolución de deps es hermano→padre: una receta del corpus NO ve las de `incoming-*`. Las
# variantes compartidas genéricas (zlib-shared, fontconfig-shared, freetype-shared, libpng-shared…)
# ya viven acá por esa razón. Ponerla en `incoming-wlr/` la haría invisible para todo lo demás y
# obligaría a una cuarta copia en cuanto otro escritorio la necesite.
#
# ── EL BUILD ES EL DE AUTOTOOLS, SIN EL TRUCO DE zlib ──────────────────────────────────────────
# zlib-shared fabrica su `.so` a mano con `--whole-archive` porque el configure de zlib aborta bajo
# zig cc. Acá no hace falta: el configure de expat acepta `--enable-shared` y libtool emite el
# `libexpat.so.1` con su SONAME correcto. Se cae el `-all-static -no-pie` de la canónica, que es
# justamente lo que impide producir una compartida.
name = "expat-shared"
version = "2.8.1"
license = "MIT"
[source]
tarball = "https://github.com/libexpat/libexpat/releases/download/R_2_8_1/expat-2.8.1.tar.xz"
sha256 = "10b195ee78160a908388180a8fe3603d4e9a12f4755fbf5f3816b23a9d750da0"
[build]
compiler = "zig-cc"
target = "x86_64-linux-musl"
link = "dynamic"
[deps]
build = ["binutils", "make"]
[build.phases]
configure = './configure --build=$CBUILD --host=$CHOST --prefix=/usr --enable-shared --disable-static --with-pic --without-docbook'
compile = 'make -j"$(nproc)"'
install = 'make DESTDIR=/out install'