diff --git a/recipes/bash.toml b/recipes/bash.toml index df3d21ca..f2f21dac 100644 --- a/recipes/bash.toml +++ b/recipes/bash.toml @@ -18,6 +18,33 @@ link = "static" strip_debug = true flags = [] +# ── POR QUÉ ESTÁTICO, Y QUÉ CUESTA (audit 2026-08-31) ───────────────────────────────────────── +# La receta decía `link = "static"` y el binario salía DINÁMICO contra `libncursesw.so.6` y +# `libc.so`. No era purismo: **NINGÚN artefacto del corpus provee esas dos** —el de `ncurses` sólo +# empaqueta `.a`— así que el bash sellado sólo corría dentro del sandbox de Alpine y **no dentro de +# una imagen de hammer**, estando en los perfiles `base`, `cli`, `escritorio-cosmic` y +# `escritorio-sway`. Un shell del sistema base que no arranca en el sistema base. +# +# EVIDENCIA de que no arrancaba, ejecutando el binario sellado anterior en el host: +# Error relocating /lib/libncursesw.so.6: __vfprintf_chk: symbol not found +# El mismo síntoma que curl en su día. El nuevo sale `statically linked`, dice +# `5.3.0(1)-release (x86_64-pc-linux-musl)` y pasa arrays, asociativos, aritmética, sustitución +# de comandos y `=~`. +# +# ⚠ EL PRECIO, medido: **el artefacto pasa de 122 a 16 ficheros**. No es una pérdida accidental +# sino el acoplamiento de upstream: `configure.ac:981` salta `AC_CHECK_LIB(dl, dlopen)` y +# `AC_CHECK_FUNCS(dlopen …)` cuando `opt_static_link=yes`, y sin `HAVE_DLOPEN` bash no construye +# ni instala los ~40 cargables de `usr/lib/bash/` (`enable -f`), sus 62 headers de +# `usr/include/bash/`, ni `usr/lib/pkgconfig/bash.pc`. Es correcto: **un binario estático no puede +# `dlopen`**, así que instalarlos sería publicar una capacidad que no existe — el fallo silencioso +# de CLAUDE.md §3. Y lo que se pierde no funcionaba igual: dinámico no eran «cargables que +# funcionan», era «un bash que no arranca». +# Nadie depende de ellos: `yupana radio bash` da 0 dependientes directos y 0 transitivos. +# Si algún día se quieren de vuelta, la decisión es de imagen —bash dinámico + hidratar la `.so` +# de ncurses— y no de esta línea. +# +# Es la misma causa que htop y e2fsprogs, y NO es libtool: es el `-rdynamic` de upstream contra la +# regla del wrapper. Ver la nota en `compile`. [build.phases] # de build() de Alpine (traducido; el lab provee $CBUILD/$CHOST — Etapa G Fase 3): compile = ''' @@ -32,9 +59,15 @@ _abuild_phase() { --disable-nls \ --enable-readline \ --without-bash-malloc \ - --without-installed-readline + --without-installed-readline \ + --enable-static-link # parallel build workarounds - make y.tab.c && make builtins/libbuiltins.a && make + # `LOCAL_LDFLAGS=`: `configure.ac:1223` pone `LOCAL_LDFLAGS=-rdynamic` en linux*, y el wrapper + # de cc del lab (`sandbox.rs:597`) tira el `-static` inyectado ante `-rdynamic` ⇒ bash salía + # DINÁMICO contra `libncursesw.so.6` y `libc.so`. **`--enable-static-link` SOLO NO ALCANZA**: + # pone `STATIC_LD=-static` (`Makefile.in:170`) pero queda en la misma línea que el `-rdynamic` + # de `BASE_LDFLAGS`, y el wrapper mira la línea entera. Van los dos. + make y.tab.c && make builtins/libbuiltins.a && make LOCAL_LDFLAGS= } _abuild_phase ''' @@ -42,7 +75,7 @@ _abuild_phase install = ''' _abuild_phase() { mkdir -p "/out"/etc/bash - make DESTDIR="/out" install + make DESTDIR="/out" install LOCAL_LDFLAGS= rm -rf "/out"/usr/share/locale } _abuild_phase