boot2

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

boot5.sh (7673B)


      1 #!/bin/sh
      2 ## boot5.sh — build musl-1.2.5 with boot4 artifacts and link hello.
      3 ##
      4 ## Builds on top of boot4's verified-fixed-point tcc (tcc2 == tcc3) and
      5 ## demonstrates that the same compiler can produce a working static libc
      6 ## from upstream musl source — patched only as far as needed to work
      7 ## around tcc's missing GCC extensions (register-asm-variable syscalls,
      8 ## attribute(alias) weak refs, _Complex, x86_64 SSE/x87 inline asm).
      9 ##
     10 ## ─── Inputs ──────────────────────────────────────────────────────────
     11 ##   build/$ARCH/$DRIVER/boot4/tcc3       — boot4's verified self-host tcc
     12 ##   build/$ARCH/$DRIVER/boot4/libtcc1.a  — boot4's tcc runtime archive
     13 ##   build/$ARCH/$DRIVER/boot2/{catm, scheme1}
     14 ##   build/$ARCH/src/src/musl/            — canonical musl tree (overrides
     15 ##                                          merged, deletes applied,
     16 ##                                          alltypes.h/syscall.h generated,
     17 ##                                          per-arch skip filter applied)
     18 ##   build/$ARCH/src/src/tcc/stdarg-bridge.h
     19 ##   build/$ARCH/src/src/test-fixtures/boot-hello.c
     20 ##
     21 ## ─── Tools ────────────────────────────────────────────────────────────
     22 ##   scheme1 evaluates a host-generated run.scm (from boot5-gen-runscm.sh)
     23 ##   against the flat staging root.
     24 ##
     25 ## ─── Outputs ─────────────────────────────────────────────────────────
     26 ##   build/$ARCH/$DRIVER/boot5/libc.a
     27 ##   build/$ARCH/$DRIVER/boot5/{crt1.o, crti.o, crtn.o}
     28 ##   build/$ARCH/$DRIVER/boot5/hello       — static, runs in the container
     29 ##
     30 ## Usage: scripts/boot5.sh <arch>
     31 ##   <arch> ∈ {aarch64, amd64, riscv64} for either DRIVER (default podman).
     32 
     33 set -eu
     34 
     35 . scripts/lib-arch.sh
     36 bootlib_init boot5 "${1:-}"
     37 driver_init empty
     38 require_src
     39 
     40 BOOT2=build/$ARCH/$DRIVER/boot2
     41 BOOT4=build/$ARCH/$DRIVER/boot4
     42 SRC=build/$ARCH/src
     43 MUSL_DIR=$SRC/src/musl
     44 
     45 # ── prerequisites ─────────────────────────────────────────────────────
     46 require_prev "$BOOT4" tcc3
     47 require_prev "$BOOT2" catm scheme1
     48 require_file "$BOOT4/libtcc1.a"           "run scripts/boot4.sh $ARCH"
     49 require_file "$MUSL_DIR"                  "run scripts/prep-src.sh $ARCH and scripts/prep-musl.sh $ARCH"
     50 require_file "$MUSL_DIR/skip.txt"         "run scripts/prep-musl.sh $ARCH"
     51 require_file "$SRC/src/tcc/stdarg-bridge.h" "run scripts/prep-src.sh $ARCH"
     52 
     53 # ── prepare staging dirs ──────────────────────────────────────────────
     54 # $STAGE/in/      — read-only inputs (becomes /work/in or in/ in tmpfs)
     55 # $STAGE/out/     — writable outputs (becomes /work/out or out/ in tmpfs)
     56 # $STAGE/_host/   — host-side scratch (enumeration outputs); never
     57 #                   visible to the container/kernel.
     58 . scripts/lib-runscm.sh
     59 runscm_init "$STAGE" "$OUT"
     60 mkdir -p "$STAGE/_host"
     61 
     62 # ── enumerate musl sources from the canonical tree ────────────────────
     63 # Mirrors musl's Makefile rule: a per-arch override (under
     64 # $d/$MUSL_ARCH/) replaces the same-stem base file (under $d/). The
     65 # canonical tree already had the per-arch skip filter applied by
     66 # prep-musl.sh, so no skip subtraction is needed here.
     67 SRC_TOP="src/aio src/conf src/crypt src/ctype src/dirent
     68          src/env src/errno src/exit src/fcntl src/fenv src/internal
     69          src/ipc src/legacy src/linux src/locale src/malloc
     70          src/malloc/mallocng src/math src/misc src/mman src/mq
     71          src/multibyte src/network src/passwd src/prng src/process
     72          src/regex src/sched src/search src/select src/setjmp src/signal
     73          src/stat src/stdio src/stdlib src/string src/temp src/termios
     74          src/thread src/time src/unistd"
     75 
     76 (
     77     cd "$MUSL_DIR"
     78     for d in $SRC_TOP; do
     79         [ -d "$d" ] || continue
     80         for f in $d/*.c; do [ -f "$f" ] && echo "$f"; done
     81     done
     82 ) > "$STAGE/_host/base.txt"
     83 
     84 (
     85     cd "$MUSL_DIR"
     86     for d in $SRC_TOP; do
     87         [ -d "$d/$MUSL_ARCH" ] || continue
     88         for f in $d/$MUSL_ARCH/*.c $d/$MUSL_ARCH/*.s $d/$MUSL_ARCH/*.S; do
     89             [ -f "$f" ] && echo "$f"
     90         done
     91     done
     92 ) > "$STAGE/_host/arch.txt"
     93 
     94 # REPLACED: bases that have arch-specific overrides (drop them from
     95 # BASE).  KEEP = (BASE - REPLACED) ∪ ARCH.
     96 awk -v ARCH="$MUSL_ARCH" '
     97     {
     98         sub(/\.[^.]*$/, "")          # strip extension
     99         slot = "/" ARCH "/"
    100         i = index($0, slot)
    101         head = substr($0, 1, i - 1)
    102         tail = substr($0, i + length(slot))
    103         print head "/" tail
    104     }
    105 ' "$STAGE/_host/arch.txt" | sort -u > "$STAGE/_host/replaced.txt"
    106 
    107 # Filter base by removing stems that appear in replaced.
    108 awk -v REPF="$STAGE/_host/replaced.txt" '
    109     BEGIN { while ((getline l < REPF) > 0) rep[l] = 1 }
    110     {
    111         stem = $0
    112         sub(/\.c$/, "", stem)
    113         if (!(stem in rep)) print
    114     }
    115 ' "$STAGE/_host/base.txt" > "$STAGE/_host/keep_base.txt"
    116 
    117 cat "$STAGE/_host/keep_base.txt" "$STAGE/_host/arch.txt" | sort -u > "$STAGE/_host/build-srcs.txt"
    118 
    119 n_src=$(wc -l < "$STAGE/_host/build-srcs.txt")
    120 n_skip=$(grep -cv '^[[:space:]]*\(#\|$\)' "$MUSL_DIR/skip.txt" || true)
    121 echo "[$BOOT_TAG] keep=$n_src skip=$n_skip (calibrated)"
    122 
    123 # Record CRT mode (asm vs c) so the gen-runscm step picks the right
    124 # crti/crtn source set without re-checking $MUSL_DIR.
    125 if [ -f "$MUSL_DIR/crt/$MUSL_ARCH/crti.s" ]; then
    126     echo asm > "$STAGE/_host/crt-mode"
    127 else
    128     echo c   > "$STAGE/_host/crt-mode"
    129 fi
    130 
    131 # Pre-create per-source obj/ directories under $STAGE/out/obj/musl/ so
    132 # scheme1's (run "in/tcc" -c …) doesn't need to mkdir at runtime (tcc
    133 # errors out if the parent dir is missing, and scheme1 has no mkdir
    134 # primitive).
    135 awk '
    136     {
    137         sub(/\.[^.]*$/, "")
    138         if (match($0, /\/[^\/]*$/)) print substr($0, 1, RSTART - 1)
    139     }
    140 ' "$STAGE/_host/build-srcs.txt" | sort -u > "$STAGE/_host/build-objdirs.txt"
    141 COBJ=$STAGE/out/obj/musl
    142 mkdir -p "$COBJ/crt"
    143 while read -r d; do mkdir -p "$COBJ/$d"; done < "$STAGE/_host/build-objdirs.txt"
    144 
    145 # ── generate run.scm and stage chain binaries ─────────────────────────
    146 runscm_gen scripts/boot5-gen-runscm.sh "$MUSL_ARCH" "$STAGE/_host"
    147 
    148 runscm_scheme1 "$BOOT2/scheme1"
    149 runscm_prelude "$SRC/src/scheme1/prelude.scm"
    150 
    151 # Chain binaries staged at flat in/ root (cwd-relative names in run.scm).
    152 runscm_input tcc                  "$BOOT4/tcc3"
    153 runscm_input libtcc1.a            "$BOOT4/libtcc1.a"
    154 runscm_input catm                 "$BOOT2/catm"
    155 runscm_input_from_src tcc/stdarg-bridge.h tcc-stdarg-bridge.h
    156 runscm_input_from_src test-fixtures/boot-hello.c hello.c
    157 
    158 # Stage the canonical musl tree under in/musl/. Both drivers pick it
    159 # up automatically (podman bind-mounts $STAGE/in; seed packs
    160 # `find in -type f` into the cpio).
    161 runscm_input_tree_from_src musl musl
    162 
    163 runscm_export libc.a crt1.o crti.o crtn.o hello
    164 
    165 # boot5 has ~1300 spawns + heavy tcc work; bump qemu memory + timeout for
    166 # the seed driver. Podman ignores QEMU_MEM and uses host memory directly.
    167 QEMU_MEM=${QEMU_MEM:-3072M} runscm_run "${BOOT5_TIMEOUT:-7200}"
    168 
    169 echo "[$BOOT_TAG] sizes: libc.a=$(wc -c <"$OUT/libc.a") hello=$(wc -c <"$OUT/hello")"
    170 echo "[$BOOT_TAG] OK -> $OUT/{libc.a, crt1.o, crti.o, crtn.o, hello}"