Files
takana/scripts/audit-needed.sh
T
Sergio 5b9777bdbd declarar gcc-libs como dep de EJECUCIÓN en las seis — y el navegador arranca
Las seis recetas que el audit daba por colgantes declaran ahora
`runtime = ["gcc-libs"]`. `deps.runtime` NO entra en el ArtifactHash —medido:
firefox sigue en b3:8116bdec, atuq en b3:f2960991, waterfox en b3:88b5a762—
así que esto NO reconstruye nada. Lo que cambia es la CLAUSURA, que es lo que se
hidrata en la imagen.

EVIDENCIA DE QUE ARREGLA EL FALLO REAL, no de que compila: `atuq` bajo sway
headless, sin GPU, renderizando about:buildconfig con sus tablas y la barra de
contenedores de la v0.5. Antes moría con decenas de «Error relocating:
_ZNKSt5ctypeIcE13_M_widen_initEv: symbol not found».
docs/evidencia/atuq-arranca-con-gcc-libs-2026-09-06.png

Y el audit se corrige, porque SUB-REPORTABA en dos formas:

  · Miraba sólo ejecutables y `head -12` por artefacto. El siguiente NEEDED que
    faltaba estaba en una LIBRERÍA (libmozsandbox.so pedía libnspr4.so), así que
    daba «6 recetas» cuando el artefacto de firefox declara 30 sonames. Ahora
    recorre TODOS los ELF.
  · No contaba lo que el propio artefacto TRAE. Firefox bundlea su nspr/nss y
    las encuentra por el LD_LIBRARY_PATH que fija su lanzador; contarlas como
    colgantes era un falso positivo.

Con las dos correcciones y gcc-libs en el store, el corpus baja de 25 artefactos
colgantes a TRES, y son otra cosa:

    sqlite-shared   libreadline.so.8
    python3         libreadline.so.8
    naabu           libdl.so.2 libpthread.so.0 libc.so.6

Los dos primeros piden una receta que falta (readline). El tercero pide sonames
de GLIBC, que en una distro musl es un síntoma distinto y merece su propia
mirada. Quedan anotados, no arreglados.
2026-09-06 20:09:10 +00:00

74 lines
4.2 KiB
Bash
Executable File

#!/usr/bin/env bash
# audit-needed.sh — ¿hay artefactos que piden una librería que NADIE del corpus provee?
#
# ── POR QUÉ EXISTE ─────────────────────────────────────────────────────────────────────────────
# Encontrado el 2026-09-06 corriendo el navegador, no leyendo: `atuq` moría con decenas de
# «Error relocating: _ZNKSt5ctypeIcE13_M_widen_initEv: symbol not found». El binario sellado de
# firefox declara
#
# NEEDED libstdc++.so.6 NEEDED libgcc_s.so.1 NEEDED libc.so
#
# y las dos primeras NO EXISTEN en el store ni en ningún cierre: sólo en `.dev-fs/alpine`, o sea en
# el LAB. Es exactamente la lección de `quitar-dep-no-apaga-funcion`: el proyecto la encuentra en el
# sysroot del lab y el artefacto sella con un NEEDED que nadie provee.
#
# LO QUE LO HACE CARO ES QUE NINGUNA MÉTRICA LO VE. `build-state.json` dice `sealed`,
# `verificar-repro.sh` dice que REPRODUCE bit a bit, los guardianes de la receta pasan — y el
# binario no arranca en la distro. El verde responde «¿construye?», nunca «¿corre?».
#
# ── QUÉ MIDE, EXACTAMENTE ──────────────────────────────────────────────────────────────────────
# Índice de sonames PROVISTOS = todo `*.so*` que haya en el store. Para cada ELF ejecutable del
# store, sus `NEEDED` menos lo provisto. Lo que sobra es una dep de ejecución colgante.
#
# NO mira el lab a propósito: si mirara `.dev-fs/alpine` diría que todo está bien, que es justo la
# ilusión que causó el problema. El lab es donde se CONSTRUYE, no donde se corre.
#
# Uso: scripts/audit-needed.sh [--store DIR] (sale 1 si hay colgantes)
set -uo pipefail
STORE="${STORE:-./store}"
[ "${1:-}" = "--store" ] && STORE="$2"
[ -d "$STORE" ] || { echo "no existe $STORE" >&2; exit 2; }
tmp=$(mktemp -d); trap 'rm -rf "$tmp"' EXIT
# 1. Qué provee el corpus. Sólo el basename: es lo que el loader busca.
find "$STORE" -maxdepth 5 -name '*.so' -o -maxdepth 5 -name '*.so.*' 2>/dev/null \
| sed 's|.*/||' | sort -u > "$tmp/provisto"
echo "== sonames provistos por el store: $(wc -l < "$tmp/provisto")"
# 2. Qué pide cada artefacto.
#
# ⚠ DOS CORRECCIONES SOBRE LA PRIMERA VERSIÓN, las dos por sub-reportar (2026-09-06):
# · Miraba sólo ejecutables y `head -12` por artefacto. El `NEEDED` que faltaba de verdad estaba
# en una LIBRERÍA (`libmozsandbox.so` pedía `libnspr4.so`), así que el audit daba «6 recetas»
# cuando el artefacto de firefox solo declara 30 sonames. Ahora mira TODOS los ELF.
# · No contaba lo que el propio artefacto TRAE. Firefox bundlea su nspr/nss y las encuentra por el
# `LD_LIBRARY_PATH` que fija su lanzador; contarlas como colgantes sería un falso positivo.
colgantes=0
for d in "$STORE"/*/; do
d=${d%/}; nombre=$(basename "$d"); receta=${nombre#*-}
# lo que este artefacto se provee a sí mismo
find "$d" \( -name '*.so' -o -name '*.so.*' \) 2>/dev/null | sed 's|.*/||' | sort -u > "$tmp/propio"
falta=""
while IFS= read -r f; do
n=$(readelf -d "$f" 2>/dev/null | sed -n 's/.*Shared library: \[\(.*\)\]/\1/p')
for so in $n; do
grep -qxF "$so" "$tmp/provisto" && continue
grep -qxF "$so" "$tmp/propio" && continue
case "$so" in libc.so|ld-musl*) continue ;; esac # la libc la pone el sistema base
case " $falta " in *" $so "*) ;; *) falta="$falta $so" ;; esac
done
done < <(find "$d" -type f \( -name '*.so' -o -name '*.so.*' -o -perm -u+x \) 2>/dev/null)
[ -n "$falta" ] && { printf ' ✗ %-24s pide y nadie provee:%s\n' "$receta" "$falta"; colgantes=$((colgantes+1)); }
done
echo "════════════════════════════════════════════════════════════"
if [ "$colgantes" -eq 0 ]; then
echo " ✅ sin deps de ejecución colgantes"
else
echo " ⚠ $colgantes artefacto(s) con deps de ejecución COLGANTES"
echo " no arrancan fuera del lab, por más que sellen y reproduzcan"
fi
exit $([ "$colgantes" -eq 0 ] && echo 0 || echo 1)