kde/Plasma: cierre runtime COMPLETO del rootfs + zlib soberano shared
- complete-closure.sh: escanea DT_NEEDED de todos los ELF del rootfs y proyecta del store sellado el artefacto que provee cada soname AUSENTE, iterando a punto fijo. Resuelve las deps runtime que el índice del repo NO lista (libmount.so.1/util-linux, libltdl, libzstd, libQt6UiTools). Sonames base (musl libc/loader) no se hidratan. - zlib-shared.toml: variante DINÁMICA de zlib (el canónico es --static). El stack GUI NEEDED libz.so.1 por soname y ningún artefacto lo proveía → caía al libz.so.1 de Alpine (fuga de soberanía Capa 0). .so fabricado del libz.a PIC vía --whole-archive (soname libz.so.1). - Resultado: rootfs kde-store-rootfs con 1269 .so, 0 sonames faltantes; kwin_wayland resuelve TODAS sus libs y carga su QPA (bloqueado sólo en render: worker sin GPU/llvmpipe). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
# zlib-shared 1.3.1 — variante DINÁMICA de zlib para el escritorio KDE.
|
||||
#
|
||||
# El zlib canónico (recipes/zlib.toml) es `--static` (sólo libz.a, para el toolchain rust/mrustc). Pero
|
||||
# el stack GUI dinámico (Qt/KDE/libpng/Mesa) linkea `libz.so.1` por SONAME en runtime, y ese `.so` no lo
|
||||
# provee ningún artefacto sellado ⇒ el rootfs hidratado caía a la libz.so.1 del sysroot Alpine (fuga de
|
||||
# soberanía, deuda static↔dinámico de Capa 0). Esta variante sella el `libz.so.1` soberano: los `.so` de
|
||||
# KDE ya tienen NEEDED libz.so.1 (mismo soname), así que basta hidratar este artefacto — sin rebuild de KDE.
|
||||
#
|
||||
# Build shared: el configure a mano de zlib genera libz.so.1.3.1 + symlinks libz.so.1/libz.so por defecto
|
||||
# (sin --static). -fPIC/-O2/-fno-sanitize=undefined igual que la canónica (evita el runtime UBSan de zig).
|
||||
|
||||
name = "zlib-shared"
|
||||
version = "1.3.1"
|
||||
|
||||
[source]
|
||||
tarball = "https://github.com/madler/zlib/releases/download/v1.3.1/zlib-1.3.1.tar.gz"
|
||||
sha256 = "9a93b2b7dfdac77ceba5a558a580e74667dd6fede4585b91eefb60f03b72df23"
|
||||
|
||||
[build]
|
||||
compiler = "zig-cc"
|
||||
target = "x86_64-linux-musl"
|
||||
link = "dynamic"
|
||||
|
||||
# zlib configure a-mano no construye el .so con el CC multi-palabra de zig ⇒ fabricamos libz.so.1 del
|
||||
# libz.a PIC con --whole-archive (truco documentado de Capa 0). El soname libz.so.1 es el que NEEDED todo
|
||||
# el stack KDE. Symlinks libz.so.1→.1.3.1 y libz.so→.1 para el loader y el linker.
|
||||
[build.phases]
|
||||
configure = "CFLAGS='-fPIC -O2 -fno-sanitize=undefined' ./configure --prefix=/usr --static"
|
||||
compile = "make -j\"$(nproc)\" && ${CC:-zig cc} -shared -Wl,-soname,libz.so.1 -Wl,--whole-archive libz.a -Wl,--no-whole-archive -o libz.so.1.3.1"
|
||||
install = "make install DESTDIR=/out && install -Dm755 libz.so.1.3.1 /out/usr/lib/libz.so.1.3.1 && ln -sf libz.so.1.3.1 /out/usr/lib/libz.so.1 && ln -sf libz.so.1 /out/usr/lib/libz.so"
|
||||
@@ -0,0 +1,64 @@
|
||||
#!/usr/bin/env bash
|
||||
# complete-closure.sh — completa el cierre RUNTIME de un FHS hidratado: escanea los `NEEDED` (DT_NEEDED)
|
||||
# de cada ELF del rootfs y, por cada soname AUSENTE, proyecta del store SELLADO el artefacto que lo
|
||||
# provee (`hammer hydrate`). Itera hasta punto fijo. Resuelve las deps runtime que el índice del repo NO
|
||||
# lista (p.ej. libmount.so.1 de util-linux, dep de build de kcoreaddons pero .so runtime de libKF6CoreAddons).
|
||||
#
|
||||
# Sonames del SUSTRATO base (musl libc, loader, libgcc) NO se hidratan: los provee la base soberana del
|
||||
# sistema destino. El resto se toma del store (mtime<CUTOFF = cosecha coherente).
|
||||
set -uo pipefail
|
||||
ROOT="$(cd "$(dirname "$0")/../.." && pwd)"; cd "$ROOT"
|
||||
STORE="${STORE:-./store}"; RFS="${RFS:-work/kde-store-rootfs}"; LINK="${LINK:-static}"
|
||||
HAMMER="${HAMMER:-./target/release/hammer}"
|
||||
CUTOFF="${CUTOFF:-$(date -d 'today 00:00' +%s 2>/dev/null || echo 9999999999)}"
|
||||
# sonames provistos por la base (no soberanos aún / runtime del sistema): no hidratar.
|
||||
BASE_SONAMES="libc.so libc.musl-x86_64.so.1 ld-musl-x86_64.so.1 libc.so.6 ld-linux-x86-64.so.2 libm.so.6 libdl.so.2 libpthread.so.0 librt.so.1 libresolv.so.2"
|
||||
|
||||
is_base(){ case " $BASE_SONAMES " in *" $1 "*) return 0;; esac; return 1; }
|
||||
|
||||
# índice soname -> artefacto (hash) del store, sólo mtime<CUTOFF (set coherente).
|
||||
echo "==> indexando sonames del store (mtime<$(date -d @$CUTOFF 2>/dev/null||echo $CUTOFF))…"
|
||||
declare -A PROV
|
||||
while IFS= read -r d; do
|
||||
hash="${d##*/}"; hash="${hash%%-*}"
|
||||
while IFS= read -r so; do
|
||||
b="${so##*/}"
|
||||
[ -z "${PROV[$b]:-}" ] && PROV[$b]="$hash"
|
||||
done < <(find "$d" -name "*.so*" -printf '%f\n' 2>/dev/null)
|
||||
done < <(find "$STORE" -maxdepth 1 -type d -name "*-*" -printf '%T@ %p\n' 2>/dev/null | awk -v c="$CUTOFF" '$1<c{print $2}')
|
||||
echo " sonames en el store: ${#PROV[@]}"
|
||||
|
||||
round=0
|
||||
while :; do
|
||||
round=$((round+1))
|
||||
# presentes en el rootfs
|
||||
declare -A HAVE=()
|
||||
while IFS= read -r f; do HAVE["${f##*/}"]=1; done < <(find "$RFS" -name "*.so*" 2>/dev/null)
|
||||
# NEEDED de todos los ELF del rootfs
|
||||
declare -A NEED=()
|
||||
while IFS= read -r bin; do
|
||||
while IFS= read -r n; do NEED["$n"]=1; done < <(readelf -d "$bin" 2>/dev/null | grep NEEDED | grep -oE '\[[^]]+\]' | tr -d '[]')
|
||||
done < <(find "$RFS" -type f \( -name "*.so*" -o -path "*/bin/*" -o -path "*/libexec/*" \) 2>/dev/null)
|
||||
# faltantes
|
||||
missing=(); for n in "${!NEED[@]}"; do
|
||||
[ -n "${HAVE[$n]:-}" ] && continue
|
||||
is_base "$n" && continue
|
||||
missing+=("$n")
|
||||
done
|
||||
if [ ${#missing[@]} -eq 0 ]; then echo "==> ronda $round: cierre COMPLETO, 0 sonames faltantes"; break; fi
|
||||
echo "==> ronda $round: ${#missing[@]} sonames faltantes"
|
||||
did=0; declare -A HYDRATED=()
|
||||
for n in "${missing[@]}"; do
|
||||
h="${PROV[$n]:-}"
|
||||
if [ -z "$h" ]; then printf " ? %-32s (ningún artefacto lo provee)\n" "$n"; continue; fi
|
||||
[ -n "${HYDRATED[$h]:-}" ] && continue
|
||||
if "$HAMMER" --store "$STORE" hydrate "$h" --into "$RFS" --link "$LINK" >/dev/null 2>&1; then
|
||||
printf " + %-32s ← %s\n" "$n" "${h:0:12}"; HYDRATED[$h]=1; did=$((did+1))
|
||||
else
|
||||
printf " ✗ %-32s hydrate falló (%s)\n" "$n" "${h:0:12}"
|
||||
fi
|
||||
done
|
||||
unset HAVE NEED
|
||||
[ $did -eq 0 ] && { echo "==> ronda $round: nada nuevo hidratado (faltantes irresolubles), corto"; break; }
|
||||
done
|
||||
echo "==> .so totales: $(find "$RFS" -name '*.so*'|wc -l); binarios: $(find "$RFS" -path '*/bin/*' -type f|wc -l)"
|
||||
Reference in New Issue
Block a user