commit e33c8d156b4908f97cefbbaf230a2721719e92fd
parent c26c833c509d82ff3c9c7023792eab3cb1745e23
Author: Ryan Sepassi <rsepassi@gmail.com>
Date: Wed, 6 May 2026 15:31:02 -0700
prep: fold musl skip filter into prep-src; calibration is manual
Drop bootprep/prep-musl.sh and require vendor/musl/skip-<arch>.txt up
front. prep-src.sh now applies the skip filter inline after the musl
unpack and runs boot5-enumerate + boot5-gen-runscm alongside the boot4
and boot6 run.scm generation. Re-running calibration when the patch
set, arch, or tcc version changes is a manual call to
bootprep/boot5-calibrate.sh; boot.sh no longer invokes it implicitly.
Diffstat:
7 files changed, 48 insertions(+), 148 deletions(-)
diff --git a/boot/boot.sh b/boot/boot.sh
@@ -1,18 +1,5 @@
#!/bin/sh
## boot.sh — drive boot0 → boot6 end-to-end under one driver.
-##
-## Usage: boot/boot.sh <arch>
-## DRIVER=seed boot/boot.sh <amd64|aarch64|riscv64>
-## DRIVER=podman boot/boot.sh <amd64|aarch64|riscv64>
-##
-## DRIVER (default podman) is exported and consumed by each bootN.sh.
-## Outputs land at build/$ARCH/$DRIVER/bootN/, so the two driver trees
-## coexist on disk. DRIVER=seed runs the build pipeline on top of the
-## podman-built boot6 kernel at build/$ARCH/podman/boot6/{Image,kernel.elf};
-## first-time setup therefore requires one prior podman pass:
-## ./boot/boot.sh <arch> # default DRIVER=podman
-## DRIVER=seed ./boot/boot.sh <arch> # re-run on tcc-built kernel
-## Subsequent DRIVER=seed runs reuse the Image directly — no stashing.
set -eu
@@ -36,12 +23,6 @@ Environment variables (all optional):
BOOT5_TIMEOUT (default 7200) boot5 (musl) wall-clock seconds.
BOOT6_TIMEOUT (default 1200) boot6 (kernel) wall-clock seconds.
QEMU_MEM (default 3072M) guest RAM passed to the seed-driver qemu.
- TCC_BOOTSTRAP_RELAX_FIXEDPOINT set to 1 in boot4 to accept tcc2 != tcc3.
- After a codegen-altering tcc patch the
- two-stage rule needs a third bounce to
- converge; the next boot4 run, started
- from this run's tcc3, will reach
- tcc2 == tcc3 with no extra knob.
EOF
exit 0
;;
@@ -59,32 +40,15 @@ if [ "$DRIVER" = seed ]; then
fi
fi
-# Wipe only this driver's tree so the other driver's outputs survive
-# (the seed driver consumes build/$ARCH/podman/boot6/$KERNEL_NAME).
-rm -rf build/$ARCH/$DRIVER
-
-# Per-stage timing comes from each child's own bootlib EXIT trap
-# (`[bootN/$DRIVER/$ARCH] done in Xs (cum Ys)`); this orchestrator only
-# adds its own total at the end (also via the lib trap).
-# A0a: build the canonical generated source tree at build/$ARCH/src/.
-# Boot stages read source from there exclusively (no flatten/unpack/
-# patch inside boot{N}.sh).
+# Boot stages read source from build/$ARCH/src/ exclusively.
./bootprep/prep-src.sh $ARCH
+rm -rf build/$ARCH/$DRIVER
./boot/boot0.sh $ARCH
./boot/boot1.sh $ARCH
./boot/boot2.sh $ARCH
./boot/boot3.sh $ARCH
./boot/boot4.sh $ARCH
-
-# A0b: apply the per-arch musl skip filter (needs tcc3 from boot4 if
-# the calibration list is missing; the committed list is the common
-# case and runs without compiler).
-./bootprep/prep-musl.sh $ARCH
-
./boot/boot5.sh $ARCH
-
-# boot6 builds the seed-kernel ELF/Image with boot4's tcc3 (no `ld -T`,
-# no objcopy).
./boot/boot6.sh $ARCH
diff --git a/boot/boot5.sh b/boot/boot5.sh
@@ -21,7 +21,7 @@
## ─── Tools ────────────────────────────────────────────────────────────
## scheme1 evaluates the prep-time run.scm at
## build/$ARCH/src/run/boot5.scm (generated by
-## bootprep/boot5-gen-runscm.sh after prep-musl) against the flat
+## bootprep/boot5-gen-runscm.sh during prep-src) against the flat
## staging root.
##
## ─── Outputs ─────────────────────────────────────────────────────────
@@ -48,8 +48,8 @@ MUSL_DIR=$SRC/src/musl
require_prev "$BOOT4" tcc3
require_prev "$BOOT2" catm scheme1
require_file "$BOOT4/libtcc1.a" "run boot/boot4.sh $ARCH"
-require_file "$MUSL_DIR" "run bootprep/prep-src.sh $ARCH and bootprep/prep-musl.sh $ARCH"
-require_file "$MUSL_DIR/skip.txt" "run bootprep/prep-musl.sh $ARCH"
+require_file "$MUSL_DIR" "run bootprep/prep-src.sh $ARCH"
+require_file "$MUSL_DIR/skip.txt" "run bootprep/prep-src.sh $ARCH"
require_file "$SRC/src/tcc/stdarg-bridge.h" "run bootprep/prep-src.sh $ARCH"
# ── prepare staging dirs ──────────────────────────────────────────────
@@ -65,7 +65,7 @@ runscm_runscm "$SRC/run/boot5.scm"
# primitive). Per-source list is the build-srcs.txt produced by
# bootprep/boot5-enumerate.sh at prep time.
SRCS=$SRC/run/boot5/build-srcs.txt
-require_file "$SRCS" "run bootprep/prep-musl.sh $ARCH"
+require_file "$SRCS" "run bootprep/prep-src.sh $ARCH"
COBJ=$STAGE/out/obj/musl
mkdir -p "$COBJ/crt"
awk '
diff --git a/boot/lib-arch.sh b/boot/lib-arch.sh
@@ -74,7 +74,7 @@ _bootlib_finish() {
fi
# Record this stage's time. Boot stages have OUT (set by driver_init);
# the orchestrator (BOOT_STAGE=boot) doesn't write — its time would
- # double-count. Other stages without OUT (prep-src, prep-musl) write
+ # double-count. Other stages without OUT (prep-src) write
# to a per-arch sidecar dir.
if [ "$BOOT_STAGE" != boot ]; then
if [ -n "${OUT:-}" ] && [ -d "$OUT" ]; then
diff --git a/bootprep/boot5-enumerate.sh b/bootprep/boot5-enumerate.sh
@@ -1,14 +1,14 @@
#!/bin/sh
## boot5-enumerate.sh — enumerate musl sources from the canonical
-## post-prep-musl tree and emit the build-srcs / crt-mode files that
+## musl tree and emit the build-srcs / crt-mode files that
## boot5-gen-runscm.sh consumes.
##
## Mirrors musl's Makefile rule: a per-arch override (under
## $d/$MUSL_ARCH/) replaces the same-stem base file (under $d/). The
## canonical tree already had the per-arch skip filter applied by
-## prep-musl.sh, so no skip subtraction is needed here.
+## prep-src.sh, so no skip subtraction is needed here.
##
-## Inputs: build/<arch>/src/src/musl/ (post-prep-musl tree)
+## Inputs: build/<arch>/src/src/musl/ (filtered tree)
## Outputs: build/<arch>/src/run/boot5/build-srcs.txt
## build/<arch>/src/run/boot5/crt-mode ("asm" or "c")
##
@@ -27,7 +27,7 @@ esac
MUSL_DIR=build/$ARCH/src/src/musl
OUT_DIR=build/$ARCH/src/run/boot5
-[ -d "$MUSL_DIR" ] || { echo "missing $MUSL_DIR (run bootprep/prep-musl.sh $ARCH)" >&2; exit 1; }
+[ -d "$MUSL_DIR" ] || { echo "missing $MUSL_DIR (run bootprep/prep-src.sh $ARCH)" >&2; exit 1; }
mkdir -p "$OUT_DIR"
SRC_TOP="src/aio src/conf src/crypt src/ctype src/dirent
diff --git a/bootprep/boot5-gen-runscm.sh b/bootprep/boot5-gen-runscm.sh
@@ -13,8 +13,7 @@
## Conventions (cwd-relative; resolves to / under seed init, /work under
## podman bind-mount):
## musl tree in/musl/<rel-path> (read-only; canonical
-## tree from prep-src/
-## prep-musl)
+## tree from prep-src)
## pre-gen hdrs in/musl/obj/include/bits/{alltypes,syscall}.h,
## in/musl/obj/src/internal/version.h
## .o outputs out/obj/musl/<src-with-.o> (rw; pre-mkdir'd by host)
diff --git a/bootprep/prep-musl.sh b/bootprep/prep-musl.sh
@@ -1,80 +0,0 @@
-#!/bin/sh
-## prep-musl.sh — A0b: apply the per-arch musl skip filter on top of
-## build/<arch>/src/src/musl/.
-##
-## prep-src.sh (A0a) leaves the musl tree at build/<arch>/src/src/musl/
-## with overrides merged, deletes applied, and pre-generated alltypes.h
-## / syscall.h dropped in. boot5-calibrate.sh's per-arch skip list (the
-## set of musl translation units tcc 0.9.26 cannot compile) needs a
-## working tcc3, so it can't be folded into A0a.
-##
-## A0b is a single transform: read the skip list (committed or freshly
-## calibrated), copy it into the canonical tree as skip.txt, and remove
-## every listed path from src/musl/. After A0b the tree is the exact
-## set of files boot5 will compile — no skip enumeration at boot time.
-##
-## Skip-list source policy:
-## - if vendor/musl/skip-<arch>.txt exists, use it
-## verbatim (the common case — calibrations are committed).
-## - else run bootprep/boot5-calibrate.sh <arch>, which itself depends
-## on boot4/tcc3. The script writes the committed file for us.
-##
-## Usage: bootprep/prep-musl.sh <arch>
-## <arch> ∈ {aarch64, amd64, riscv64}
-
-set -eu
-
-. boot/lib-arch.sh
-bootlib_init prep-musl "${1:-}"
-
-DST=$ROOT/build/$ARCH/src
-DST_MUSL=$DST/src/musl
-SKIP_COMMITTED=vendor/musl/skip-$ARCH.txt
-
-TAG="[$BOOT_TAG]"
-
-[ -d "$DST_MUSL" ] || {
- echo "$TAG missing $DST_MUSL — run bootprep/prep-src.sh $ARCH first" >&2
- exit 1
-}
-
-# ── (1) materialize the skip list ─────────────────────────────────────
-if [ ! -e "$SKIP_COMMITTED" ]; then
- echo "$TAG no committed skip list at $SKIP_COMMITTED — calibrating"
- bootprep/boot5-calibrate.sh "$ARCH"
- [ -e "$SKIP_COMMITTED" ] || {
- echo "$TAG calibration did not produce $SKIP_COMMITTED" >&2
- exit 1
- }
-fi
-cp "$SKIP_COMMITTED" "$DST_MUSL/skip.txt"
-
-# ── (2) apply filter — drop every listed path from src/musl/ ──────────
-n_skip=0
-n_missing=0
-while read -r rel; do
- [ -n "$rel" ] || continue
- case "$rel" in
- \#*) continue ;;
- esac
- if [ -e "$DST_MUSL/$rel" ]; then
- rm -rf "$DST_MUSL/$rel"
- n_skip=$((n_skip + 1))
- else
- n_missing=$((n_missing + 1))
- fi
-done < "$DST_MUSL/skip.txt"
-
-if [ "$n_missing" -gt 0 ]; then
- echo "$TAG WARN: $n_missing skip-list entries were not present in $DST_MUSL" >&2
-fi
-
-n_remaining=$(find "$DST_MUSL" -type f | wc -l | tr -d ' ')
-echo "$TAG OK filtered=$n_skip remaining=$n_remaining files in $DST_MUSL"
-
-# ── (3) enumerate musl sources + generate boot5 run.scm ───────────────
-# The filtered tree is now stable; emit the build-srcs + crt-mode that
-# boot5-gen-runscm consumes, then emit boot5.scm itself. boot5.sh just
-# reads the result.
-bootprep/boot5-enumerate.sh "$ARCH"
-bootprep/boot5-gen-runscm.sh "$ARCH"
diff --git a/bootprep/prep-src.sh b/bootprep/prep-src.sh
@@ -1,12 +1,12 @@
#!/bin/sh
-## prep-src.sh — A0a: build the canonical generated source tree.
+## prep-src.sh — build the canonical generated source tree.
##
## All host-side source preparation happens once, up front, into a
## single canonical tree at build/<arch>/src/. This tree is the audit
## basis and the only thing boot stages should read for source. Boot
## stages do no flattening, no unpacking, no patching, no calibration.
##
-## Layout produced (see docs/PLAN.md §A0):
+## Layout produced:
## build/<arch>/src/
## bin/ binary inputs not built by a stage
## hex0-seed vendored seed only
@@ -26,22 +26,21 @@
## libc/ libc.flat.c (mes-libc flattened)
## musl/ filtered musl-1.2.5 tree (overrides
## merged, deletes applied, generated
-## alltypes.h/syscall.h dropped in).
-## prep-musl.sh applies the per-arch
-## skip filter on top.
+## alltypes.h/syscall.h dropped in,
+## per-arch skip filter applied).
## kernel/ seed-kernel sources for this arch
## test-fixtures/ boot-hello.c smoke binary
## run/ run.scm files driving each bootN stage
## boot3.scm static (copied from bootprep/assets/)
## boot4.scm generated by bootprep/boot4-gen-runscm.sh
## boot5.scm generated by bootprep/boot5-gen-runscm.sh
-## (after prep-musl.sh)
## boot6.scm generated by bootprep/boot6-gen-runscm.sh
##
-## A0 is split: prep-src.sh runs before boot0 and produces everything
-## that doesn't need a working compiler. prep-musl.sh runs after boot4
-## (or copies the committed skip list) and applies the calibration
-## filter on top of src/musl/.
+## The musl skip list (vendor/musl/skip-<arch>.txt) is calibrated
+## offline by bootprep/boot5-calibrate.sh and committed; prep-src.sh
+## reads it and applies the filter inline. Re-run boot5-calibrate.sh
+## manually when the patch set, calibration arch, or tcc version
+## changes.
##
## Usage: bootprep/prep-src.sh <arch>
## <arch> ∈ {aarch64, amd64, riscv64}
@@ -160,11 +159,13 @@ MUSL_TARBALL=vendor/musl/1.2.5.tar.gz
MUSL_OVERRIDES=vendor/musl/overrides
MUSL_DELETES=vendor/musl/deletes.txt
MUSL_GENERATED=vendor/musl/generated/$MUSL_ARCH
+MUSL_SKIP=vendor/musl/skip-$ARCH.txt
[ -e "$MUSL_TARBALL" ] || { echo "$TAG missing $MUSL_TARBALL" >&2; exit 1; }
[ -d "$MUSL_OVERRIDES" ] || { echo "$TAG missing $MUSL_OVERRIDES" >&2; exit 1; }
[ -e "$MUSL_DELETES" ] || { echo "$TAG missing $MUSL_DELETES" >&2; exit 1; }
[ -d "$MUSL_GENERATED" ] || { echo "$TAG missing $MUSL_GENERATED (run bootprep/musl-vendor.sh)" >&2; exit 1; }
+[ -e "$MUSL_SKIP" ] || { echo "$TAG missing $MUSL_SKIP (run bootprep/boot5-calibrate.sh $ARCH)" >&2; exit 1; }
echo "$TAG unpack musl-1.2.5 + apply overrides/deletes"
MUSL_TMP=$(mktemp -d)
@@ -189,21 +190,37 @@ mkdir -p "$DST_SRC/musl"
# Move into place — the canonical tree owns this from now on.
( cd "$MUSL_TMP/musl-1.2.5" && tar cf - . ) | ( cd "$DST_SRC/musl" && tar xf - )
-# Seed src/musl/skip.txt with the committed skip list when one exists,
-# so the canonical tree carries metadata even before prep-musl.sh
-# applies the filter. prep-musl.sh refreshes/regenerates this.
-SKIP_COMMITTED=vendor/musl/skip-$ARCH.txt
-if [ -e "$SKIP_COMMITTED" ]; then
- cp "$SKIP_COMMITTED" "$DST_SRC/musl/skip.txt"
+# Apply the committed per-arch skip filter inline: copy the list as
+# skip.txt metadata, then drop every listed path from src/musl/.
+cp "$MUSL_SKIP" "$DST_SRC/musl/skip.txt"
+n_skip=0
+n_missing=0
+while read -r rel; do
+ [ -n "$rel" ] || continue
+ case "$rel" in
+ \#*) continue ;;
+ esac
+ if [ -e "$DST_SRC/musl/$rel" ]; then
+ rm -rf "$DST_SRC/musl/$rel"
+ n_skip=$((n_skip + 1))
+ else
+ n_missing=$((n_missing + 1))
+ fi
+done < "$DST_SRC/musl/skip.txt"
+if [ "$n_missing" -gt 0 ]; then
+ echo "$TAG WARN: $n_missing skip-list entries were not present in $DST_SRC/musl" >&2
fi
+echo "$TAG musl skip filter: dropped=$n_skip"
# ── (7) run.scm files ─────────────────────────────────────────────────
-# Static run.scm (boot3) copied verbatim; boot4/boot6 generated here.
-# boot5.scm needs the post-prep-musl tree, so it's generated by
-# prep-musl.sh.
+# Static run.scm (boot3) copied verbatim; the rest are generated. The
+# musl tree is now stable, so boot5-enumerate + boot5-gen-runscm can
+# run alongside boot4/boot6 generation.
mkdir -p "$DST/run"
cp bootprep/assets/boot3-run.scm "$DST/run/boot3.scm"
bootprep/boot4-gen-runscm.sh "$ARCH"
+bootprep/boot5-enumerate.sh "$ARCH"
+bootprep/boot5-gen-runscm.sh "$ARCH"
bootprep/boot6-gen-runscm.sh "$ARCH"
# ── summary ───────────────────────────────────────────────────────────