selfhost-verify: pieza 3 (linux-headers swap) — SWAP_LINUX_HEADERS=1, byte-idéntico a Alpine en host

Tercera pieza del toolchain hammer-from-source (variante b, SDD 11 §7.2b): los headers
UAPI del kernel 6.16.12 que musl/busybox #include, hoy tomados del paquete linux-headers
de Alpine.

- recipes/linux-headers.toml: `make headers` (no `headers_install` — su rsync final falta
  en el toolchain hermético) + unifdef vía HOSTCC=zig cc; .tar.gz (busybox-tar lo
  descomprime sin xz). Sella los 13 subdirs kernel-owned de usr/include.
- assemble_builder: el swap ahora soporta rel_path de DIRECTORIO (reemplaza el árbol
  entero: remove + copy), no sólo binarios. Cubierto por test nuevo
  (builder_rootfs_swaps_toolchain_header_tree_from_source, incl. borrado de huérfanos).
- recipes/linux-headers-alpine-compat.patch: el paquete de Alpine no es el `make headers`
  crudo. Aporta content-pinned 5 archivos que difieren de la salida vainilla; 3 son
  REQUERIDOS (scsi/{scsi,scsi_ioctl,sg}.h — legacy userspace, NO UAPI) porque el applet
  `eject` de busybox los incluye y sin ellos no compila. install los pisa sobre /out y
  limpia el junk (.cmd/Makefile/headers_check.pl/drm) que `cp -a` arrastra.
- scripts/selfhost-verify.sh: SWAP_LINUX_HEADERS=1 construye la receta y emite un --swap
  por subdir kernel-owned (auto-derivado del artefacto sellado).

Criterio de éxito fuerte: `diff -r` del header-tree de hammer contra el de Alpine = VACÍO
⇒ el toolchain swapeado es byte-idéntico al baseline ⇒ reproducibilidad por construcción.
Ensamblado end-to-end en host OK (13 swaps, musl bits/sys intactos). 133 tests verdes.
Pendiente: corrida in-VM para el sello ✓ REPRODUCIBLE.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-13 19:35:01 -04:00
co-authored by Claude Opus 4.8
parent 26b10bd757
commit b05badee23
5 changed files with 693 additions and 16 deletions
+17
View File
@@ -135,6 +135,23 @@ if [[ "${SWAP_BUSYBOX:-0}" == 1 ]]; then
say "busybox hammer: $BB_HASH"
SWAP_ARGS+=(--swap "busybox=$BB_HASH:bin/busybox")
fi
if [[ "${SWAP_LINUX_HEADERS:-0}" == 1 ]]; then
# Pieza 3: los headers UAPI del kernel. NO es un binario sino un árbol — el swap-directorio
# (assemble_builder) reemplaza cada subdir entero. Swapeamos exactamente los subdirs que el
# artefacto sellado produce (linux/asm/asm-generic/cxl/fwctl/misc/mtd/rdma/regulator/scsi/sound/
# video/xen), que son justo los que el paquete linux-headers de Alpine posee; los de musl
# (bits/sys/net/…) quedan intactos.
say "variante b — construir linux-headers desde fuente y swapear /toolchain/usr/include/{linux,asm,…}"
LH_HASH="$("$HAMMER" --store "$STORE" build recipes/linux-headers.toml | grep -oE 'b3:[0-9a-f]{64}' | tail -1)"
[[ "$LH_HASH" == b3:* ]] || die "no obtuve el hash sellado de linux-headers"
say "linux-headers hammer: $LH_HASH"
LH_INC="$(ls -d "$STORE"/*-linux-headers/usr/include 2>/dev/null | head -1)"
[[ -d "$LH_INC" ]] || die "no encuentro usr/include en el linux-headers sellado"
for d in "$LH_INC"/*/; do
sub="$(basename "$d")"
SWAP_ARGS+=(--swap "linux-headers=${LH_HASH}:usr/include/$sub")
done
fi
for s in ${SWAPS:-}; do SWAP_ARGS+=(--swap "$s"); done
# 4) Ensamblar el builder con la referencia embebida.