readline-shared: la .so que python3 y sqlite piden (b3:79355aad)
libreadline.so.8, 970.144 bytes. Hermana de ncurses-shared y por la misma fuga: python3 y sqlite-shared salen con NEEDED libreadline.so.8 y la readline del catálogo es --disable-shared, así que sólo produce libreadline.a. En el rootfs hidratado eso se resolvía contra el sysroot Alpine DEL LAB. Versión 8.2 y no la 8.3.3 de Alpine, a propósito: es la que ya usa recipes/readline.toml y tener las dos variantes en versiones distintas es pedir que diverjan sin que nadie lo note. TRES GUARDIANES, y el segundo es de Alpine casi literal. readline sale MAL ENLAZADA por diseño de upstream —libreadline.so no enlaza contra ncurses salvo que se lo fuerces, y queda con tgetent y compañía sin resolver—; Alpine lo arregla con un parche y con un check que falla si el NEEDED de ncurses no aparece. Acá se consigue sin parche con SHLIB_LIBS=-lncursesw, que es la perilla que el propio Makefile expone. El guardián verifica que quedó enlazada, porque si no el fallo reaparece en el consumidor, a un eslabón de distancia y sin nombrar a esta receta. La dep es ncurses-shared y no ncurses: con la estática, libreadline.so.8 se llevaría los objetos de libncursesw.a dentro en vez de declarar el NEEDED — la misma lección que el cairo estático de waterfox. Se promueve además sqlite-shared de incoming-gnome al catálogo canónico: python3 la necesita como dep de ejecución y una receta de recipes/ no ve las de una cola. Sin variantes en conflicto y ya sellada, así que la promoción no cuesta un build.
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
# readline-shared 8.2 — la MISMA readline de `recipes/readline.toml` pero `.so`. Hermana de
|
||||
# `ncurses-shared`, y existe por la misma clase de fuga.
|
||||
#
|
||||
# ══ POR QUÉ HACE FALTA ═════════════════════════════════════════════════════════════════════════
|
||||
# `python3` y `sqlite-shared` salen con `NEEDED libreadline.so.8` y NINGÚN artefacto del cierre
|
||||
# publica ese soname: la readline del catálogo es `--disable-shared`, así que sólo produce
|
||||
# `libreadline.a`. En el rootfs hidratado eso se resuelve contra el sysroot Alpine DEL LAB, que en
|
||||
# la máquina de desarrollo está y en la distro NO. Lo venía reportando `scripts/vigia-sonames.py`
|
||||
# en los CUATRO perfiles, junto a `libstdc++.so.6` — que se pagó el 2026-09-06 con `gcc-libs`.
|
||||
#
|
||||
# No sustituye a `recipes/readline.toml`: quien quiera enlazar estático sigue usando aquélla. Es el
|
||||
# mismo reparto que `ncurses` / `ncurses-shared`.
|
||||
#
|
||||
# ⚠ VERSIÓN 8.2 Y NO LA 8.3.3 DE ALPINE, A PROPÓSITO. El soname que piden los consumidores YA
|
||||
# SELLADOS es `libreadline.so.8`, y las dos lo dan; pero la 8.2 es la que ya usa `readline.toml`, y
|
||||
# tener las dos variantes en versiones distintas es pedir que diverjan sin que nadie lo note. Si se
|
||||
# sube una, se suben las dos.
|
||||
#
|
||||
# ⚠ EL SUBRAYADO: READLINE SALE MAL ENLAZADA POR DISEÑO DE UPSTREAM. `libreadline.so` no enlaza
|
||||
# contra ncurses salvo que se lo fuerces, y queda con `tgetent`, `tputs` y compañía SIN RESOLVER.
|
||||
# Alpine lo arregla con un parche y —esto es lo que se copia— con un guardián que FALLA si el
|
||||
# `NEEDED` de ncurses no aparece. Acá se consigue lo mismo sin parche, pasándole `SHLIB_LIBS` al
|
||||
# make, que es la perilla que el propio Makefile de readline expone para esto.
|
||||
name = "readline-shared"
|
||||
version = "8.2"
|
||||
license = "GPL-3.0-or-later"
|
||||
|
||||
[source]
|
||||
tarball = "https://ftp.gnu.org/gnu/readline/readline-8.2.tar.gz"
|
||||
sha256 = "3feb7171f16a84ee82ca18a36d7b9be109a52c04f492a053331d7d1095007c35"
|
||||
|
||||
[build]
|
||||
compiler = "zig-cc"
|
||||
target = "x86_64-linux-musl"
|
||||
# El punto de la receta: hammer inyecta `LDFLAGS=-static` en modo estático y acá el producto ES la
|
||||
# librería compartida. Igual que en `gcc-libs` y `ncurses-shared`.
|
||||
link = "dynamic"
|
||||
|
||||
[deps]
|
||||
# `ncurses-shared` y no `ncurses`: si acá entrara la estática, `libreadline.so.8` se llevaría los
|
||||
# objetos de `libncursesw.a` dentro en vez de declarar el `NEEDED`, y el guardián de abajo —que es
|
||||
# el de Alpine— lo cazaría. Es la misma lección que el cairo estático de waterfox.
|
||||
build = ["ncurses-shared", "make"]
|
||||
|
||||
[build.phases]
|
||||
configure = "./configure --prefix=/usr --enable-shared --disable-static --with-curses"
|
||||
# `SHLIB_LIBS` es la perilla del Makefile de readline para lo que Alpine resuelve con un parche.
|
||||
compile = 'make SHLIB_LIBS=-lncursesw'
|
||||
install = '''
|
||||
set -e
|
||||
make install DESTDIR=/out SHLIB_LIBS=-lncursesw
|
||||
|
||||
# La readline trae `rlconf.h` y binarios de ejemplo que no hacen falta para satisfacer un NEEDED.
|
||||
rm -rf /out/usr/bin /out/usr/share
|
||||
|
||||
# ── GUARDIÁN 1: el soname que los consumidores piden ─────────────────────────────────────────
|
||||
F=$(find /out/usr/lib -name 'libreadline.so.8*' | head -1)
|
||||
test -n "$F" || { echo "!! no se generó libreadline.so.8 — ¿--enable-shared no tomó?" >&2; ls -l /out/usr/lib >&2; exit 1; }
|
||||
SO=$(readelf -d "$F" 2>/dev/null | sed -n 's/.*SONAME.*\[\(.*\)\].*/\1/p')
|
||||
test "$SO" = "libreadline.so.8" || { echo "!! SONAME es '$SO' y esperaba 'libreadline.so.8'" >&2; exit 1; }
|
||||
echo "guardián: libreadline.so.8 ok (SONAME correcto, $(stat -Lc%s "$F") bytes)"
|
||||
|
||||
# ── GUARDIÁN 2: EL DE ALPINE — que no esté SUBENLAZADA ───────────────────────────────────────
|
||||
# Copiado de su APKBUILD casi literal («verify that it is not underlinked as upstream designed
|
||||
# it»). Sin esto la librería existe, tiene el soname correcto y sus símbolos de terminal quedan
|
||||
# colgando: el fallo reaparecería en el consumidor, a un eslabón de distancia y sin nombrar a esta
|
||||
# receta. Es exactamente la forma de fallo que esta receta viene a cerrar, así que dejarla sin
|
||||
# comprobar sería no haber aprendido nada.
|
||||
readelf -d "$F" 2>/dev/null | grep -q 'NEEDED.*ncurses' || {
|
||||
echo "!! libreadline.so.8 NO está enlazada contra ncurses (subenlazada)" >&2
|
||||
echo " readline hace esto por diseño de upstream; revisá SHLIB_LIBS=-lncursesw." >&2
|
||||
readelf -d "$F" 2>/dev/null | grep NEEDED >&2
|
||||
exit 1
|
||||
}
|
||||
echo "guardián: enlazada contra ncurses ($(readelf -d "$F" | sed -n 's/.*NEEDED.*\[\(.*ncurses.*\)\].*/\1/p'))"
|
||||
|
||||
# ── GUARDIÁN 3: la prueba del consumidor ─────────────────────────────────────────────────────
|
||||
# Los símbolos que python3 y sqlite buscan de verdad. «Existe» no es «sirve».
|
||||
falta=""
|
||||
for s in readline add_history rl_completion_matches; do
|
||||
nm -D --defined-only "$F" 2>/dev/null | grep -qE " $s(@|\$)" || falta="$falta $s"
|
||||
done
|
||||
test -z "$falta" || { echo "!! la .so no define:$falta" >&2; exit 1; }
|
||||
echo "guardián: define los símbolos que piden python3 y sqlite"
|
||||
'''
|
||||
@@ -0,0 +1,55 @@
|
||||
# ── ⚠ VERRUGA MEDIDA (2026-09-05), sin decidir ─────────────────────────────────────────────────
|
||||
# `usr/bin/sqlite3` —el shell de la CLI, NO `libsqlite3.so.0`— sale con `NEEDED libreadline.so.8`, y
|
||||
# el `readline` canónico del corpus es `.a`. O sea que en la imagen GNOME ese comando no carga: lo
|
||||
# resolvía contra el sysroot Alpine DEL LAB. Lo cazó `scripts/vigia-sonames.py`; las APPS están bien,
|
||||
# porque la librería no lo lleva.
|
||||
#
|
||||
# Las dos salidas cuestan cosas distintas y por eso no se decide de paso:
|
||||
# · construir `readline-shared` y sumarla de raíz a `escritorio-gnome` — 1 build nuevo, pero la
|
||||
# imagen carga una librería más sólo para que ande un comando. (`ncurses-shared` ya es raíz del
|
||||
# perfil, así que la cadena cierra.)
|
||||
# · configurar acá `--disable-readline` y no instalar una CLI que nadie pidió — más limpio, pero
|
||||
# re-hashea: `yupana radio sqlite-shared` da **6 dependientes en incoming-gnome** que caen a
|
||||
# deuda.
|
||||
# Se paga barato el día que sqlite-shared se re-selle por otro motivo.
|
||||
|
||||
# sqlite-shared 3.46.1 — variante DINÁMICA de sqlite para la isla dinámica de GNOME.
|
||||
#
|
||||
# Por qué existe: el sqlite canónico (recipes/sqlite.toml) es `--disable-shared --enable-static` y su
|
||||
# libsqlite3.a NO es PIC (verificado: trae reubicaciones R_X86_64_32). libsoup 3.6 lo pide DURO
|
||||
# (meson.build:123-136 cae a `dependency('sqlite3')` sin `required:false`) y libsoup es un .so ⇒
|
||||
# meter el .a no-PIC adentro corta con el mismo `relocation R_X86_64_32 ... recompile with -fPIC`
|
||||
# que frenó a mutter contra freetype. Mismo patrón y misma solución que zlib-shared/cairo-shared:
|
||||
# una variante hermana, sin tocar la canónica (su radio son cientos de sellados).
|
||||
#
|
||||
# El único cambio real frente a la canónica es --enable-shared --disable-static y sacar el
|
||||
# `-all-static -no-pie` de LDFLAGS, que es justo lo que impide producir un .so. Misma versión y mismo
|
||||
# tarball a propósito: el sqlite3.pc que consume libsoup declara la misma versión que el resto del
|
||||
# corpus, así que no se abre un skew de versiones entre el mundo estático y el dinámico.
|
||||
name = "sqlite-shared"
|
||||
version = "3.46.1"
|
||||
|
||||
[source]
|
||||
tarball = "https://sqlite.org/2024/sqlite-autoconf-3460100.tar.gz"
|
||||
sha256 = "67d3fe6d268e6eaddcae3727fce58fcc8e9c53869bdd07a0c61e38ddf2965071"
|
||||
|
||||
[build]
|
||||
compiler = "zig-cc"
|
||||
target = "x86_64-linux-musl"
|
||||
link = "dynamic"
|
||||
|
||||
[build.phases]
|
||||
configure = "./configure --prefix=/usr --enable-shared --disable-static"
|
||||
compile = 'make -j"$(nproc)"'
|
||||
install = "make install DESTDIR=/out"
|
||||
|
||||
[deps]
|
||||
# ✅ DECIDIDA 2026-09-06, y la decisión cambió porque cambió el cálculo. La verruga de arriba dejaba
|
||||
# dos salidas sin elegir, y el argumento contra la primera era «la imagen carga una librería más sólo
|
||||
# para que ande un comando». Ya no es cierto: `python3` sale con el MISMO `NEEDED libreadline.so.8`
|
||||
# y es raíz de los cuatro perfiles, así que `readline-shared` entra en la clausura igual. El coste
|
||||
# marginal de arreglar además el `sqlite3` de la CLI es CERO.
|
||||
# `runtime` no entra en el ArtifactHash ⇒ no re-hashea, y los 6 dependientes que menciona la nota de
|
||||
# arriba no se tocan. Esa era la otra mitad del precio y tampoco se paga.
|
||||
runtime = ["readline-shared"]
|
||||
build = ["make", "pkgconf"]
|
||||
Reference in New Issue
Block a user