boot2

Playing with the boostrap
git clone https://git.ryansepassi.com/git/boot2.git
Log | Files | Refs | README

commit 7a40928766648342fc82fb107a508408ff2908f6
parent 1293270d3338064f60208d4d80eae653ba250de0
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Tue,  5 May 2026 12:19:50 -0700

boot{3,4,5}: --no-cache podman build; drop ./ spawn prefix

Two small fixups on the unified run.scm path:

- podman build for boot2-empty:<arch> now uses --no-cache. Without it,
  podman's layer cache hashes ENV/ARG directives ignoring the resolved
  --build-arg value, so the second per-arch build silently aliases its
  tag onto the first arch's image SHA — a later --platform run against
  the aliased tag warns "image platform … does not match expected
  platform". The Containerfile is FROM scratch + WORKDIR, so no-cache
  costs nothing. Drops the ARG/ENV cache-bust attempt that didn't work.

- run.scm spawns drop the "./" prefix on bare names (catm, scheme1,
  M1pp, hex2pp, tcc, tccN). Linux execve resolves bare relative paths
  against cwd, and the seed kernel's flat path map normalizes "./" away
  anyway; the prefix was a defensive cleanup added while debugging
  what turned out to be the prelude probe bug.

Diffstat:
Mscripts/Containerfile.empty | 15++++++---------
Mscripts/boot3-run.scm | 14+++++++-------
Mscripts/boot3.sh | 2+-
Mscripts/boot4-gen-runscm.sh | 26+++++++++++++-------------
Mscripts/boot4.sh | 2+-
Mscripts/boot5-gen-runscm.sh | 26+++++++++++++-------------
Mscripts/boot5.sh | 2+-
7 files changed, 42 insertions(+), 45 deletions(-)

diff --git a/scripts/Containerfile.empty b/scripts/Containerfile.empty @@ -4,14 +4,11 @@ ## and run.scm spawns only staged binaries (catm, scheme1, M1pp, hex2pp, ## tcc), so no in-container shell, /bin/sh, or applet tree is needed. ## -## Built per --platform; tag as boot2-empty:<arch>. The ARCH build-arg -## flows into an ENV so each per-arch build produces a distinct image -## SHA — without it, FROM-scratch-only Containerfiles dedup across -## platforms and the second-built tag points back at the first arch's -## image (podman has no platform check on tag resolve, so a rootless -## --platform=linux/riscv64 lookup against an arm64-tagged SHA fails -## with "image not known"). +## Built per --platform with --no-cache; tagged as boot2-empty:<arch>. +## --no-cache is required because podman's layer cache key for an empty +## FROM-scratch + WORKDIR Containerfile is identical across platforms, +## so a second --platform build silently aliases its tag onto the first +## arch's image SHA — leaving e.g. boot2-empty:riscv64 pointing at an +## arm64 image. FROM scratch -ARG ARCH=unknown -ENV CONTAINER_ARCH=$ARCH WORKDIR /work diff --git a/scripts/boot3-run.scm b/scripts/boot3-run.scm @@ -12,27 +12,27 @@ (exit 1)))) (write-string stdout "boot3: catm cc-bundle\n") -(must (run "./catm" "cc-bundled.scm" "prelude.scm" "cc.scm" "main.scm") +(must (run "catm" "cc-bundled.scm" "prelude.scm" "cc.scm" "main.scm") "catm cc-bundle") (write-string stdout "boot3: scheme1 libc\n") -(must (run "./scheme1" "cc-bundled.scm" "--lib=libc__" "libc.flat.c" "libc.P1pp") +(must (run "scheme1" "cc-bundled.scm" "--lib=libc__" "libc.flat.c" "libc.P1pp") "scheme1 libc") (write-string stdout "boot3: scheme1 tcc\n") -(must (run "./scheme1" "cc-bundled.scm" "--lib=tcc__" "tcc.flat.c" "tcc.flat.P1pp") +(must (run "scheme1" "cc-bundled.scm" "--lib=tcc__" "tcc.flat.c" "tcc.flat.P1pp") "scheme1 tcc") (write-string stdout "boot3: catm combined.M1pp\n") -(must (run "./catm" "combined.M1pp" +(must (run "catm" "combined.M1pp" "backend.M1pp" "frontend.M1pp" "libp1pp.P1pp" "entry-libc.P1pp" "libc.P1pp" "tcc.flat.P1pp" "elf-end.P1pp") "catm combined.M1pp") (write-string stdout "boot3: M1pp\n") -(must (run "./M1pp" "combined.M1pp" "expanded.hex2pp") +(must (run "M1pp" "combined.M1pp" "expanded.hex2pp") "M1pp") (write-string stdout "boot3: catm linked.hex2pp\n") -(must (run "./catm" "linked.hex2pp" "ELF.hex2" "expanded.hex2pp") +(must (run "catm" "linked.hex2pp" "ELF.hex2" "expanded.hex2pp") "catm linked.hex2pp") (write-string stdout "boot3: hex2pp\n") -(must (run "./hex2pp" "-B" "0x600000" "linked.hex2pp" "tcc0") +(must (run "hex2pp" "-B" "0x600000" "linked.hex2pp" "tcc0") "hex2pp") (exit 0) diff --git a/scripts/boot3.sh b/scripts/boot3.sh @@ -79,7 +79,7 @@ LIBC_FLAT=build/$ARCH/vendor/mes-libc/libc.flat.c # ── ensure container image exists (podman driver only) ──────────────── if [ "$DRIVER" = podman ] && ! podman image exists "$IMAGE"; then echo "[boot3 $ARCH] building $IMAGE" - podman build --platform "$PLATFORM" --build-arg "ARCH=$ARCH" -t "$IMAGE" \ + podman build --no-cache --platform "$PLATFORM" -t "$IMAGE" \ -f scripts/Containerfile.empty scripts/ fi if [ "$DRIVER" = seed ]; then diff --git a/scripts/boot4-gen-runscm.sh b/scripts/boot4-gen-runscm.sh @@ -32,11 +32,11 @@ esac emit_helpers() { cc=$1 cat <<EOF -(must (run "./$cc" "-nostdlib" "-c" "-o" "start.o" "start.S") "$cc start.o") -(must (run "./$cc" "-nostdlib" "-c" "-o" "sys_stubs.o" "sys_stubs.S") "$cc sys_stubs.o") -(must (run "./$cc" "-nostdlib" "-c" "-o" "mem.o" "mem.c") "$cc mem.o") -(must (run "./$cc" "-nostdlib" "-c" "-o" "libc.o" "libc.flat.c") "$cc libc.o") -(must (run "./$cc" "-nostdlib" $LIB_HELPER_DEFS "-c" "-o" "$LIB_HELPER_OBJ" "$LIB_HELPER_SRC") "$cc $LIB_HELPER_OBJ") +(must (run "$cc" "-nostdlib" "-c" "-o" "start.o" "start.S") "$cc start.o") +(must (run "$cc" "-nostdlib" "-c" "-o" "sys_stubs.o" "sys_stubs.S") "$cc sys_stubs.o") +(must (run "$cc" "-nostdlib" "-c" "-o" "mem.o" "mem.c") "$cc mem.o") +(must (run "$cc" "-nostdlib" "-c" "-o" "libc.o" "libc.flat.c") "$cc libc.o") +(must (run "$cc" "-nostdlib" $LIB_HELPER_DEFS "-c" "-o" "$LIB_HELPER_OBJ" "$LIB_HELPER_SRC") "$cc $LIB_HELPER_OBJ") EOF } @@ -48,25 +48,25 @@ EOF # stage reads them as standalone .o. emit_archive() { cc=$1; pfx=$2 - echo "(must (run \"./catm\" \"${pfx}crt1.o\" \"start.o\") \"copy crt1.o $pfx\")" - echo "(must (run \"./$cc\" \"-ar\" \"rcs\" \"${pfx}libc.a\" \"sys_stubs.o\" \"mem.o\" \"libc.o\") \"$cc ${pfx}libc.a\")" + echo "(must (run \"catm\" \"${pfx}crt1.o\" \"start.o\") \"copy crt1.o $pfx\")" + echo "(must (run \"$cc\" \"-ar\" \"rcs\" \"${pfx}libc.a\" \"sys_stubs.o\" \"mem.o\" \"libc.o\") \"$cc ${pfx}libc.a\")" libtcc1_objs="" for src in $LIBTCC1_C_SRCS; do obj=${src%.c}.o - echo "(must (run \"./$cc\" \"-nostdlib\" $LIBTCC1_C_DEFS \"-c\" \"-o\" \"${obj}\" \"$src\") \"$cc lt ${obj}\")" + echo "(must (run \"$cc\" \"-nostdlib\" $LIBTCC1_C_DEFS \"-c\" \"-o\" \"${obj}\" \"$src\") \"$cc lt ${obj}\")" libtcc1_objs="$libtcc1_objs \"${obj}\"" done for src in $LIBTCC1_ASM_SRCS; do obj=${src%.S}.o - echo "(must (run \"./$cc\" \"-nostdlib\" \"-c\" \"-o\" \"${obj}\" \"$src\") \"$cc lt ${obj}\")" + echo "(must (run \"$cc\" \"-nostdlib\" \"-c\" \"-o\" \"${obj}\" \"$src\") \"$cc lt ${obj}\")" libtcc1_objs="$libtcc1_objs \"${obj}\"" done - echo "(must (run \"./$cc\" \"-ar\" \"rcs\" \"${pfx}libtcc1.a\"$libtcc1_objs) \"$cc ${pfx}libtcc1.a\")" + echo "(must (run \"$cc\" \"-ar\" \"rcs\" \"${pfx}libtcc1.a\"$libtcc1_objs) \"$cc ${pfx}libtcc1.a\")" } emit_link_tcc() { cc=$1; pfx=$2; out=$3 - echo "(must (run \"./$cc\" \"-nostdlib\" \"${pfx}crt1.o\" \"tcc.flat.c\" \"${pfx}libc.a\" \"${pfx}libtcc1.a\" \"${pfx}libc.a\" \"-o\" \"$out\") \"$cc -> $out\")" + echo "(must (run \"$cc\" \"-nostdlib\" \"${pfx}crt1.o\" \"tcc.flat.c\" \"${pfx}libc.a\" \"${pfx}libtcc1.a\" \"${pfx}libc.a\" \"-o\" \"$out\") \"$cc -> $out\")" } { @@ -94,7 +94,7 @@ emit_helpers tcc0 cat <<EOF (write-string stdout "boot4: stage C (tcc0 -> tcc1)\n") -(must (run "./tcc0" "-nostdlib" "start.o" "sys_stubs.o" "mem.o" "libc.o" "$LIB_HELPER_OBJ" "tcc.flat.c" "-o" "tcc1") "tcc0 -> tcc1") +(must (run "tcc0" "-nostdlib" "start.o" "sys_stubs.o" "mem.o" "libc.o" "$LIB_HELPER_OBJ" "tcc.flat.c" "-o" "tcc1") "tcc0 -> tcc1") (write-string stdout "boot4: stage D (tcc1 -> tcc2)\n") EOF @@ -117,7 +117,7 @@ emit_link_tcc tcc2 "s3-" tcc3 cat <<'EPILOGUE' (write-string stdout "boot4: linking hello\n") -(must (run "./tcc2" "-nostdlib" "s3-crt1.o" "hello.c" "s3-libc.a" "s3-libtcc1.a" "s3-libc.a" "-o" "hello") "tcc2 -> hello") +(must (run "tcc2" "-nostdlib" "s3-crt1.o" "hello.c" "s3-libc.a" "s3-libtcc1.a" "s3-libc.a" "-o" "hello") "tcc2 -> hello") (write-string stdout "boot4: ALL-OK\n") (exit 0) EPILOGUE diff --git a/scripts/boot4.sh b/scripts/boot4.sh @@ -118,7 +118,7 @@ LIBC_FLAT=build/$ARCH/vendor/mes-libc/libc.flat.c # ── ensure container image exists (podman driver only) ──────────────── if [ "$DRIVER" = podman ] && ! podman image exists "$IMAGE"; then echo "[boot4 $ARCH] building $IMAGE" - podman build --platform "$PLATFORM" --build-arg "ARCH=$ARCH" -t "$IMAGE" \ + podman build --no-cache --platform "$PLATFORM" -t "$IMAGE" \ -f scripts/Containerfile.empty scripts/ fi if [ "$DRIVER" = seed ]; then diff --git a/scripts/boot5-gen-runscm.sh b/scripts/boot5-gen-runscm.sh @@ -78,7 +78,7 @@ awk -v CFLAGS_C="$CFLAGS_C_QUOTED" -v CFLAGS_ASM="$CFLAGS_ASM_QUOTED" -v CWORK=" if (src ~ /\.c$/) flags = CFLAGS_C else if (src ~ /\.[sS]$/) flags = CFLAGS_ASM else flags = CFLAGS_C - printf "(must (run \"./tcc\" %s \"-c\" \"%s/%s\" \"-o\" \"%s/%s\") \"%s\")\n", \ + printf "(must (run \"tcc\" %s \"-c\" \"%s/%s\" \"-o\" \"%s/%s\") \"%s\")\n", \ flags, CWORK, src, CWORK, obj, src }' "$SRCS" @@ -87,20 +87,20 @@ cat <<EOF (write-string stdout "boot5: stage B (CRT)\n") ;; Position-independent + non-PIC CRT helpers. -fPIC objects are needed ;; for shared-binding tools, even though our hello is fully static. -(must (run "./tcc" $CRTFLAGS_C_QUOTED "-fPIC" "-c" "$CWORK/crt/Scrt1.c" "-o" "$CWORK/obj/crt/Scrt1.o") "Scrt1.o") -(must (run "./tcc" $CRTFLAGS_C_QUOTED "-c" "$CWORK/crt/crt1.c" "-o" "$CWORK/obj/crt/crt1.o") "crt1.o") -(must (run "./tcc" $CRTFLAGS_C_QUOTED "-fPIC" "-c" "$CWORK/crt/rcrt1.c" "-o" "$CWORK/obj/crt/rcrt1.o") "rcrt1.o") +(must (run "tcc" $CRTFLAGS_C_QUOTED "-fPIC" "-c" "$CWORK/crt/Scrt1.c" "-o" "$CWORK/obj/crt/Scrt1.o") "Scrt1.o") +(must (run "tcc" $CRTFLAGS_C_QUOTED "-c" "$CWORK/crt/crt1.c" "-o" "$CWORK/obj/crt/crt1.o") "crt1.o") +(must (run "tcc" $CRTFLAGS_C_QUOTED "-fPIC" "-c" "$CWORK/crt/rcrt1.c" "-o" "$CWORK/obj/crt/rcrt1.o") "rcrt1.o") EOF if [ "$CRT_MODE" = asm ]; then cat <<EOF -(must (run "./tcc" $CRTFLAGS_ASM_QUOTED "-c" "$CWORK/crt/$MUSL_ARCH/crti.s" "-o" "$CWORK/obj/crt/crti.o") "crti.o") -(must (run "./tcc" $CRTFLAGS_ASM_QUOTED "-c" "$CWORK/crt/$MUSL_ARCH/crtn.s" "-o" "$CWORK/obj/crt/crtn.o") "crtn.o") +(must (run "tcc" $CRTFLAGS_ASM_QUOTED "-c" "$CWORK/crt/$MUSL_ARCH/crti.s" "-o" "$CWORK/obj/crt/crti.o") "crti.o") +(must (run "tcc" $CRTFLAGS_ASM_QUOTED "-c" "$CWORK/crt/$MUSL_ARCH/crtn.s" "-o" "$CWORK/obj/crt/crtn.o") "crtn.o") EOF else cat <<EOF -(must (run "./tcc" $CRTFLAGS_C_QUOTED "-c" "$CWORK/crt/crti.c" "-o" "$CWORK/obj/crt/crti.o") "crti.o") -(must (run "./tcc" $CRTFLAGS_C_QUOTED "-c" "$CWORK/crt/crtn.c" "-o" "$CWORK/obj/crt/crtn.o") "crtn.o") +(must (run "tcc" $CRTFLAGS_C_QUOTED "-c" "$CWORK/crt/crti.c" "-o" "$CWORK/obj/crt/crti.o") "crti.o") +(must (run "tcc" $CRTFLAGS_C_QUOTED "-c" "$CWORK/crt/crtn.c" "-o" "$CWORK/obj/crt/crtn.o") "crtn.o") EOF fi @@ -109,7 +109,7 @@ fi # ~60 KB on a single line) but the prelude reader handles it fine. { printf '\n(write-string stdout "boot5: stage C (libc.a)\\n")\n' - printf '(must (run "./tcc" "-ar" "rcs" "libc.a"' + printf '(must (run "tcc" "-ar" "rcs" "libc.a"' awk -v CWORK="$CWORK" '{ obj = "obj/" $0 sub(/\.[^.]*$/, ".o", obj) @@ -121,13 +121,13 @@ fi cat <<EOF ;; Publish CRT objects at flat cwd-relative paths so runscm_export can pull them. -(must (run "./catm" "crt1.o" "$CWORK/obj/crt/crt1.o") "crt1.o publish") -(must (run "./catm" "crti.o" "$CWORK/obj/crt/crti.o") "crti.o publish") -(must (run "./catm" "crtn.o" "$CWORK/obj/crt/crtn.o") "crtn.o publish") +(must (run "catm" "crt1.o" "$CWORK/obj/crt/crt1.o") "crt1.o publish") +(must (run "catm" "crti.o" "$CWORK/obj/crt/crti.o") "crti.o publish") +(must (run "catm" "crtn.o" "$CWORK/obj/crt/crtn.o") "crtn.o publish") (write-string stdout "boot5: stage D (link hello)\n") ;; -L. picks up libc.a + libtcc1.a from the flat staging root (cwd). -(must (run "./tcc" "-static" "-nostdinc" "-nostdlib" "-include" "tcc-stdarg-bridge.h" +(must (run "tcc" "-static" "-nostdinc" "-nostdlib" "-include" "tcc-stdarg-bridge.h" "-I$CWORK/include" "-I$CWORK/arch/$MUSL_ARCH" "-I$CWORK/arch/generic" "-I$CWORK/obj/include" "crt1.o" "hello.c" "-L." "-lc" "-L." "-ltcc1" "-L." "-lc" "-o" "hello") "link hello") diff --git a/scripts/boot5.sh b/scripts/boot5.sh @@ -96,7 +96,7 @@ BRIDGE_FILE=build/tcc/stdarg-bridge.h if [ "$DRIVER" = podman ] && ! podman image exists "$IMAGE"; then echo "[boot5 $ARCH] building $IMAGE" - podman build --platform "$PLATFORM" --build-arg "ARCH=$ARCH" -t "$IMAGE" \ + podman build --no-cache --platform "$PLATFORM" -t "$IMAGE" \ -f scripts/Containerfile.empty scripts/ fi if [ "$DRIVER" = seed ]; then