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…

gcc-libs enviaba un ld script que pedía una librería que nadie tenía

`/usr/lib/libgcc_s.so` no es una librería: es un ld script —`GROUP ( libgcc_s.so.1 -lgcc )`— y ese
`-lgcc` es libgcc.a, que ninguna receta del corpus proveía. Esta misma la borraba: el
`find -name '*.a' -delete` de la poda, y de paso el `rm -rf /usr/lib/gcc` se llevaba el original.

Medido en la caja con el rust recién sellado: los binarios estáticos compilan y corren, pero
cualquier dylib —y eso incluye TODAS las proc-macros— muere con `unable to find library -lgcc`. O
sea `cargo build` con `derive` imposible sobre takana, con el compilador perfecto. Y no alcanza con
dar `-L /usr/lib`: con eso se resuelven `-lc` y `-lgcc_s`, y entonces aparece justo este `-lgcc`.

Es la misma familia que el hueco que originó esta receta —todo presente, todo reproducible, y el
camino que hace falta no existe—, sólo que del lado del ENLACE en vez del arranque.

libgcc.a se copia a /usr/lib (donde el -L del enlazador ya mira; el gcc completo no está en esta
distro) y se salva de la poda. Y entra un GUARDIÁN 3 que compara lo que el ld script PIDE contra lo
que el artefacto TRAE: si vuelve a quedarse sin libgcc.a, corta.

Radio medido con yupana antes de tocar: 7 dependientes directos, 9 transitivos, 7 imágenes.

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

e49545e0a7eff5f10c1d90e8cb54036becedf255 · by Sergio · (1 month ago) · parent 096c426b1 · browse the tree at this commit

Semantic delta

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

1 files · +38 −3

diff --git a/recipes/gcc-libs.toml b/recipes/gcc-libs.toml
index 29294c40..30e43e45 100644
--- a/recipes/gcc-libs.toml
+++ b/recipes/gcc-libs.toml
@@ -119,13 +119,37 @@ if [ -d /out/usr/lib64 ]; then
   rm -rf /out/usr/lib64
 fi
 
-# Se PODA todo lo que no sea runtime: headers, `.a`, `.la`, libsupc++, los `.py` del pretty-printer.
-# Esta receta existe para que un binario ARRANQUE, no para compilar contra ella; dejar los headers
+# ── libgcc.a SE SALVA DE LA PODA, Y ES UNA CORRECCIÓN (2026-09-17) ───────────────────────────
+# `/usr/lib/libgcc_s.so` que esta receta instala **no es una librería: es un ld script**
+#
+#     GROUP ( libgcc_s.so.1 -lgcc )
+#
+# y ese `-lgcc` es `libgcc.a`, que NINGUNA receta del corpus proveía —ésta la borraba con el
+# `find -name '*.a' -delete` de acá abajo, y de paso `rm -rf /usr/lib/gcc` se llevaba el original—.
+# Consecuencia medida en la caja de producción con el `rust` recién sellado: los binarios ESTÁTICOS
+# compilan y corren, pero **cualquier dylib —y eso incluye TODAS las proc-macros— muere**:
+#
+#     ld.lld: error: unable to find library -lgcc
+#
+# O sea `cargo build` con `derive` (serde, clap…) imposible sobre takana, con el compilador perfecto.
+# Es la misma familia que el hueco que originó esta receta: todo presente, todo reproducible, y el
+# camino que hace falta no existe. Y no alcanza con dar `-L /usr/lib`: con eso se resuelven `-lc` y
+# `-lgcc_s`, y entonces aparece justo este `-lgcc`.
+#
+# Va a `/usr/lib` —no al directorio privado de gcc— porque es donde el `-L` del enlazador ya mira, y
+# porque el gcc completo no está en esta distro: acá la librería tiene que valerse sola.
+A=$(find /out -name libgcc.a | head -1)
+test -n "$A" || { echo "!! el install no dejó ninguna libgcc.a — sin ella el ld script de libgcc_s miente" >&2; exit 1; }
+cp "$A" /out/usr/lib/libgcc.a
+
+# Se PODA todo lo que no sea runtime: headers, el resto de los `.a`, `.la`, libsupc++, los `.py` del
+# pretty-printer. Esta receta existe para que un binario ARRANQUE —y ahora también para que el
+# `libgcc_s.so` que envía sea ENLAZABLE—, no para compilar C++ contra ella; dejar los headers
 # invitaría a que otra receta se enlace contra esto en vez de contra el lab, que es una decisión
 # distinta y no la que se está tomando acá.
 find /out -name '*.la' -delete
 rm -rf /out/usr/include /out/usr/share /out/usr/lib/gcc
-find /out -name '*.a' -delete
+find /out -name '*.a' ! -name 'libgcc.a' -delete
 find /out -name '*.py' -delete
 
 L=/out/usr/lib
@@ -166,4 +190,15 @@ test -z "$falta" || {
   exit 1
 }
 echo "guardián: los 6 símbolos que firefox no encontraba están DEFINIDOS"
+
+# ── GUARDIÁN 3: EL LD SCRIPT NO PUEDE MENTIR ─────────────────────────────────────────────────
+# `libgcc_s.so` es un ld script que manda buscar `-lgcc`. Si esa librería no viaja con él, el
+# artefacto sella, reproduce, y la primera dylib que alguien enlace en una caja takana muere. Se
+# comprueba lo que el script PIDE contra lo que el artefacto TRAE, no la intención.
+if grep -q "GROUP" "$L/libgcc_s.so" 2>/dev/null; then
+  grep -q -- "-lgcc" "$L/libgcc_s.so" && test -f "$L/libgcc.a" || {
+    echo "!! $L/libgcc_s.so es un ld script que pide -lgcc y no hay libgcc.a al lado" >&2
+    cat "$L/libgcc_s.so" >&2; exit 1; }
+  echo "guardián: el ld script pide -lgcc y libgcc.a viaja con él ($(stat -Lc%s "$L/libgcc.a") bytes)"
+fi
 '''