From 64894d863c2dee48251a73812bbde61e7109e161 Mon Sep 17 00:00:00 2001 From: Sergio Date: Thu, 11 Jun 2026 15:13:32 +0000 Subject: [PATCH] =?UTF-8?q?bootstrap:=20builder=20ejecutable=20=E2=80=94?= =?UTF-8?q?=20toolchain=20con=20bwrap/git/curl=20+=20shim=20del=20loader?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Correr el rebuild EN la VM destapó dos faltantes reales del builder (justo lo que la verificación de Stage 2 debe cazar): 1. El toolchain (variante a, desde Alpine) traía compiladores (cargo/make/zig) pero NO las herramientas de orquestación del lab — bwrap (anida el sandbox), git (git archive del mirror) y curl (tarballs). En el host las aporta el sistema; en la VM el toolchain es el único userland capaz, así que deben vivir ahí. bootstrap-devfs.sh las añade (paquete `bubblewrap`, no `bwrap`). 2. Esos binarios son Alpine *dinámicos* y no corren desde el userland Stage 1 *estático* (musl --disable-shared ⇒ no hay loader en /lib). rebuild-stage1 ahora instala un shim del loader musl (cp a /lib) + LD_LIBRARY_PATH/PATH al toolchain antes de invocar hammer; el sandbox de build sigue anidando en /toolchain. El hammer estático corre por ruta absoluta. El builder boot end-to-end ya estaba probado; esto lo hace además *capaz de reconstruirse*. 28 tests verdes. Co-Authored-By: Claude Opus 4.8 (1M context) --- crates/hammer-bootstrap/src/lib.rs | 19 ++++++++++++++++--- scripts/bootstrap-devfs.sh | 6 +++++- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/crates/hammer-bootstrap/src/lib.rs b/crates/hammer-bootstrap/src/lib.rs index 18a605f9..ac01ba7e 100644 --- a/crates/hammer-bootstrap/src/lib.rs +++ b/crates/hammer-bootstrap/src/lib.rs @@ -489,22 +489,35 @@ pub fn verify_against(report: &VerifyReport, rebuilt_content: ArtifactHash) -> R /// `/etc/hammer/rebuild.env` (`SEED_HASH`/`SEED_KIND`/`REF_CONTENT`), apunta el sandbox de build al /// toolchain de adentro (`/toolchain`) y compara `stage1'` contra la referencia. Si `REF_CONTENT` va /// vacío, sólo imprime el content-hash de `stage1'` para comparación manual. +/// +/// El toolchain es Alpine **dinámico**: sus binarios (bwrap/git/curl/cargo/make) no corren desde el +/// userland Stage 1, que es **estático** (no hay loader en `/lib`). El driver instala un *shim* del +/// loader musl (`cp` a `/lib`) + `LD_LIBRARY_PATH`/`PATH` al toolchain, y a partir de ahí esas +/// herramientas son ejecutables; el `hammer` estático vive en `/usr/bin/hammer`. El sandbox de build +/// (bwrap) anida en `/toolchain`. (El shim sólo se usa para *invocar* el toolchain desde fuera del +/// sandbox: fetch git/tarball; dentro del sandbox el loader está en su sitio.) const REBUILD_DRIVER: &str = r#"#!/bin/sh # rebuild-stage1 — rebuild de Stage 1 con el toolchain del propio rootfs (auto-alojamiento, SDD 11 §7). # Booteado en la VM (builder rootfs), reconstruye stage1' usando SÓLO las herramientas de adentro y # compara su content-hash con la referencia que `hammer bootstrap stage2` ancló afuera. set -eu . /etc/hammer/rebuild.env # SEED_HASH, SEED_KIND, REF_CONTENT (REF_CONTENT puede ir vacío) +# Shim del loader musl: deja correr los binarios *dinámicos* del toolchain (bwrap/git/curl/cargo/make) +# desde el root Stage 1 estático. Usa el busybox estático (rutas absolutas) ANTES de tocar el PATH. +/bin/mkdir -p /lib +/bin/cp -f /toolchain/lib/ld-musl-x86_64.so.1 /lib/ld-musl-x86_64.so.1 +export LD_LIBRARY_PATH=/toolchain/lib:/toolchain/usr/lib +export PATH=/toolchain/usr/bin:/toolchain/usr/sbin:/toolchain/bin:/usr/bin:/bin:/sbin export HAMMER_ROOTFS=/toolchain # el sandbox de build: el toolchain (variante a, desde Alpine) export HAMMER_WORK=/work export HAMMER_CACHE= echo ">> rebuild stage1 (toolchain in-rootfs, semilla $SEED_HASH)" -PRIME=$(hammer --store /store bootstrap stage1 --seed-hash "$SEED_HASH" --seed "$SEED_KIND" --recipes /etc/hammer/recipes) +PRIME=$(/usr/bin/hammer --store /store bootstrap stage1 --seed-hash "$SEED_HASH" --seed "$SEED_KIND" --recipes /etc/hammer/recipes) echo ">> stage1' = $PRIME" if [ -n "${REF_CONTENT:-}" ]; then - hammer --store /store bootstrap stage2 --rootfs "$PRIME" --verify "$REF_CONTENT" + /usr/bin/hammer --store /store bootstrap stage2 --rootfs "$PRIME" --verify "$REF_CONTENT" else - hammer --store /store bootstrap stage2 --rootfs "$PRIME" + /usr/bin/hammer --store /store bootstrap stage2 --rootfs "$PRIME" fi "#; diff --git a/scripts/bootstrap-devfs.sh b/scripts/bootstrap-devfs.sh index 7a9e15f4..6a833a48 100755 --- a/scripts/bootstrap-devfs.sh +++ b/scripts/bootstrap-devfs.sh @@ -117,7 +117,11 @@ else # paquetes la necesitan. zig cc nativo la encuentra en /usr/include. (Lo destapó la # verificación de reproducibilidad de Stage 2: con el config determinista, los applets de # console-tools la exigen.) - NEEDED="make autoconf automake m4 patch coreutils libtool pkgconf bash binutils rust cargo linux-headers" + # `bwrap git curl`: el rebuild *dentro* del builder rootfs (Stage 2 pleno, SDD 11 §7) corre + # hammer-build con su propio toolchain. En el host estas tres las aporta el sistema, pero en la + # VM el toolchain ES el único userland capaz, así que deben vivir aquí: `bwrap` anida el sandbox + # de build, `git` rematerializa las fuentes git (git archive del mirror), `curl` baja tarballs. + NEEDED="make autoconf automake m4 patch coreutils libtool pkgconf bash binutils rust cargo linux-headers bubblewrap git curl" missing="" for pkg in $NEEDED; do # apk info -e devuelve el paquete si está instalado, vacío si no.