prep-src.sh (10719B)
1 #!/bin/sh 2 ## prep-src.sh — build the canonical generated source tree. 3 ## 4 ## All host-side source preparation happens once, up front, into a 5 ## single canonical tree at build/<arch>/src/. This tree is the audit 6 ## basis and the only thing boot stages should read for source. Boot 7 ## stages do no flattening, no unpacking, no patching, no calibration. 8 ## 9 ## Layout produced: 10 ## build/<arch>/src/ 11 ## bin/ binary inputs not built by a stage 12 ## hex0-seed vendored seed only 13 ## src/ everything textual 14 ## stage0-posix/ ELF.hex2 + *.hex0|*.hex1|*.hex2 15 ## M1pp/ M1pp.P1 16 ## hex2pp/ hex2pp.P1 17 ## P1/ P1*.{M1,M1pp,P1pp}, entry-*.P1pp, 18 ## elf-end.P1pp 19 ## catm/ catm.P1pp 20 ## scheme1/ scheme1.P1pp, prelude.scm 21 ## cc/ cc.scm, main.scm 22 ## tcc/ tcc.flat.c plus 23 ## tcc-0.9.26-1147-gee75a10c/{include,lib} 24 ## tcc/libc/$ARCH/ start.S, sys_stubs.S 25 ## tcc/cc/ mem.c (memcpy/memmove/memset/memcmp) 26 ## libc/ libc.flat.c (mes-libc flattened) 27 ## musl/ filtered musl-1.2.5 tree (overrides 28 ## merged, deletes applied, generated 29 ## alltypes.h/syscall.h dropped in, 30 ## per-arch skip filter applied). 31 ## kernel/ seed-kernel sources for this arch 32 ## test-fixtures/ boot-hello.c smoke binary 33 ## run/ run.scm files driving each bootN stage 34 ## boot3.scm static (copied from bootprep/assets/) 35 ## boot4.scm generated by bootprep/boot4-gen-runscm.sh 36 ## boot5.scm generated by bootprep/boot5-gen-runscm.sh 37 ## boot6.scm generated by bootprep/boot6-gen-runscm.sh 38 ## 39 ## The musl skip list (vendor/musl/skip-<arch>.txt) is calibrated 40 ## offline by bootprep/boot5-calibrate.sh and committed; prep-src.sh 41 ## reads it and applies the filter inline. Re-run boot5-calibrate.sh 42 ## manually when the patch set, calibration arch, or tcc version 43 ## changes. 44 ## 45 ## Usage: bootprep/prep-src.sh <arch> 46 ## <arch> ∈ {aarch64, amd64, riscv64, riscv32} 47 48 set -eu 49 50 . boot/lib-arch.sh 51 bootlib_init prep-src "${1:-}" 52 53 DST=$ROOT/build/$ARCH/src 54 DST_BIN=$DST/bin 55 DST_SRC=$DST/src 56 57 TAG="[$BOOT_TAG]" 58 59 # ── (0) reset destination ───────────────────────────────────────────── 60 rm -rf "$DST" 61 mkdir -p "$DST_BIN" "$DST_SRC" 62 63 # ── (1) vendored seed (pre-built binary + textual sources) ──────────── 64 SEED=vendor/seed/$ARCH 65 [ -d "$SEED" ] || { echo "$TAG missing $SEED" >&2; exit 1; } 66 67 cp "$SEED/hex0-seed" "$DST_BIN/hex0-seed" 68 69 mkdir -p "$DST_SRC/stage0-posix" 70 for f in ELF.hex2 hex0.hex0 hex1.hex0 hex2.hex1 catm.hex2 M0.hex2; do 71 [ -e "$SEED/$f" ] || { echo "$TAG missing $SEED/$f" >&2; exit 1; } 72 cp "$SEED/$f" "$DST_SRC/stage0-posix/$f" 73 done 74 75 # ── (2) repo-tree textual sources ───────────────────────────────────── 76 mkdir -p "$DST_SRC/M1pp" 77 cp M1pp/M1pp.P1 "$DST_SRC/M1pp/M1pp.P1" 78 79 mkdir -p "$DST_SRC/hex2pp" 80 cp hex2pp/hex2pp.P1 "$DST_SRC/hex2pp/hex2pp.P1" 81 82 mkdir -p "$DST_SRC/P1" 83 cp "P1/P1.M1pp" "$DST_SRC/P1/P1.M1pp" 84 cp "P1/P1-$ARCH.M1" "$DST_SRC/P1/P1-$ARCH.M1" 85 cp "P1/P1-$ARCH.M1pp" "$DST_SRC/P1/P1-$ARCH.M1pp" 86 cp "P1/P1pp.P1pp" "$DST_SRC/P1/P1pp.P1pp" 87 cp "P1/entry-libc.P1pp" "$DST_SRC/P1/entry-libc.P1pp" 88 cp "P1/entry-plain.P1pp" "$DST_SRC/P1/entry-plain.P1pp" 89 cp "P1/elf-end.P1pp" "$DST_SRC/P1/elf-end.P1pp" 90 91 mkdir -p "$DST_SRC/catm" 92 cp catm/catm.P1pp "$DST_SRC/catm/catm.P1pp" 93 94 mkdir -p "$DST_SRC/scheme1" 95 cp scheme1/scheme1.P1pp "$DST_SRC/scheme1/scheme1.P1pp" 96 cp scheme1/prelude.scm "$DST_SRC/scheme1/prelude.scm" 97 98 # RV32 is supported through the native P1/Scheme bootstrap. TCC and all 99 # consumers of it are a separate target port, intentionally not present yet. 100 if [ "$TCC_SUPPORTED" != 1 ]; then 101 n_files=$(find "$DST" -type f | wc -l | tr -d ' ') 102 echo "$TAG OK -> $DST ($n_files files; boot0..boot2 sources, TCC intentionally omitted)" 103 exit 0 104 fi 105 106 mkdir -p "$DST_SRC/cc" 107 cp cc/cc.scm "$DST_SRC/cc/cc.scm" 108 cp cc/main.scm "$DST_SRC/cc/main.scm" 109 110 # tcc-libc: per-arch _start + sys_* wrappers consumed by boot4. 111 mkdir -p "$DST_SRC/tcc/libc/$ARCH" 112 cp "tcc/libc/$ARCH/start.S" "$DST_SRC/tcc/libc/$ARCH/start.S" 113 cp "tcc/libc/$ARCH/sys_stubs.S" "$DST_SRC/tcc/libc/$ARCH/sys_stubs.S" 114 115 # tcc-cc: tiny mem helpers consumed by boot4 + boot6. 116 mkdir -p "$DST_SRC/tcc/cc" 117 cp tcc/cc/mem.c "$DST_SRC/tcc/cc/mem.c" 118 119 # Smoke binary linked by boot4 + boot5. 120 mkdir -p "$DST_SRC/test-fixtures" 121 cp bootprep/assets/boot-hello.c "$DST_SRC/test-fixtures/boot-hello.c" 122 cp bootprep/assets/toolchain-hello.c "$DST_SRC/test-fixtures/toolchain-hello.c" 123 124 # ── (3) seed-kernel sources for this arch ───────────────────────────── 125 mkdir -p "$DST_SRC/kernel/arch/$ARCH" "$DST_SRC/kernel/user" 126 cp seed-kernel/kernel.c "$DST_SRC/kernel/kernel.c" 127 for f in seed-kernel/arch/$ARCH/*; do 128 [ -f "$f" ] || continue 129 cp "$f" "$DST_SRC/kernel/arch/$ARCH/$(basename "$f")" 130 done 131 for f in seed-kernel/user/*; do 132 [ -f "$f" ] || continue 133 cp "$f" "$DST_SRC/kernel/user/$(basename "$f")" 134 done 135 136 # ── (4) tcc flatten ─────────────────────────────────────────────────── 137 # stage1-flatten.sh writes to build/<arch>/vendor/tcc/. Run it (it's 138 # idempotent) and mirror the relevant artifacts into src/tcc/. 139 echo "$TAG flatten tcc.flat.c (host)" 140 bootprep/stage1-flatten.sh --arch "$ARCH" 141 142 TCC_VENDOR=$ROOT/build/$ARCH/vendor/tcc 143 TCC_PKG=tcc-0.9.26-1147-gee75a10c 144 [ -e "$TCC_VENDOR/tcc.flat.c" ] || { echo "$TAG flatten produced no tcc.flat.c" >&2; exit 1; } 145 [ -d "$TCC_VENDOR/$TCC_PKG/include" ] || { echo "$TAG flatten produced no $TCC_PKG/include" >&2; exit 1; } 146 [ -d "$TCC_VENDOR/$TCC_PKG/lib" ] || { echo "$TAG flatten produced no $TCC_PKG/lib" >&2; exit 1; } 147 148 mkdir -p "$DST_SRC/tcc" 149 cp "$TCC_VENDOR/tcc.flat.c" "$DST_SRC/tcc/tcc.flat.c" 150 mkdir -p "$DST_SRC/tcc/$TCC_PKG" 151 cp -R "$TCC_VENDOR/$TCC_PKG/include" "$DST_SRC/tcc/$TCC_PKG/include" 152 cp -R "$TCC_VENDOR/$TCC_PKG/lib" "$DST_SRC/tcc/$TCC_PKG/lib" 153 154 # ── (5) mes-libc flatten ────────────────────────────────────────────── 155 echo "$TAG flatten libc.flat.c (host)" 156 bootprep/libc-flatten.sh --arch "$ARCH" 157 158 LIBC_VENDOR=$ROOT/build/$ARCH/vendor/mes-libc 159 [ -e "$LIBC_VENDOR/libc.flat.c" ] || { echo "$TAG flatten produced no libc.flat.c" >&2; exit 1; } 160 161 mkdir -p "$DST_SRC/libc" 162 cp "$LIBC_VENDOR/libc.flat.c" "$DST_SRC/libc/libc.flat.c" 163 164 # ── (6) musl unpack + overrides + deletes + generated headers ───────── 165 MUSL_TARBALL=vendor/musl/1.2.5.tar.gz 166 MUSL_OVERRIDES=vendor/musl/overrides 167 MUSL_DELETES=vendor/musl/deletes.txt 168 MUSL_GENERATED=vendor/musl/generated/$MUSL_ARCH 169 MUSL_SKIP=vendor/musl/skip-$ARCH.txt 170 171 [ -e "$MUSL_TARBALL" ] || { echo "$TAG missing $MUSL_TARBALL" >&2; exit 1; } 172 [ -d "$MUSL_OVERRIDES" ] || { echo "$TAG missing $MUSL_OVERRIDES" >&2; exit 1; } 173 [ -e "$MUSL_DELETES" ] || { echo "$TAG missing $MUSL_DELETES" >&2; exit 1; } 174 [ -d "$MUSL_GENERATED" ] || { echo "$TAG missing $MUSL_GENERATED (run bootprep/musl-vendor.sh)" >&2; exit 1; } 175 [ -e "$MUSL_SKIP" ] || { echo "$TAG missing $MUSL_SKIP (run bootprep/boot5-calibrate.sh $ARCH)" >&2; exit 1; } 176 177 echo "$TAG unpack musl-1.2.5 + apply overrides/deletes" 178 MUSL_TMP=$(mktemp -d) 179 trap 'rm -rf "$MUSL_TMP"' EXIT 180 tar xzf "$MUSL_TARBALL" -C "$MUSL_TMP" 181 [ -d "$MUSL_TMP/musl-1.2.5" ] || { echo "$TAG musl tarball did not unpack to musl-1.2.5/" >&2; exit 1; } 182 183 cp -R "$MUSL_OVERRIDES/." "$MUSL_TMP/musl-1.2.5/" 184 while read -r p; do 185 [ -n "$p" ] && rm -rf "$MUSL_TMP/musl-1.2.5/$p" 186 done < "$MUSL_DELETES" 187 188 # Drop pre-generated arch headers + version.h into the same obj/ layout 189 # boot5 expects. 190 mkdir -p "$MUSL_TMP/musl-1.2.5/obj/include/bits" \ 191 "$MUSL_TMP/musl-1.2.5/obj/src/internal" 192 cp "$MUSL_GENERATED/alltypes.h" "$MUSL_TMP/musl-1.2.5/obj/include/bits/alltypes.h" 193 cp "$MUSL_GENERATED/syscall.h" "$MUSL_TMP/musl-1.2.5/obj/include/bits/syscall.h" 194 echo '#define VERSION "1.2.5-tcc-boot5"' > "$MUSL_TMP/musl-1.2.5/obj/src/internal/version.h" 195 196 mkdir -p "$DST_SRC/musl" 197 # Move into place — the canonical tree owns this from now on. 198 ( cd "$MUSL_TMP/musl-1.2.5" && tar cf - . ) | ( cd "$DST_SRC/musl" && tar xf - ) 199 200 # Apply the committed per-arch skip filter inline: copy the list as 201 # skip.txt metadata, then drop every listed path from src/musl/. 202 cp "$MUSL_SKIP" "$DST_SRC/musl/skip.txt" 203 n_skip=0 204 n_missing=0 205 while read -r rel; do 206 [ -n "$rel" ] || continue 207 case "$rel" in 208 \#*) continue ;; 209 esac 210 if [ -e "$DST_SRC/musl/$rel" ]; then 211 rm -rf "$DST_SRC/musl/$rel" 212 n_skip=$((n_skip + 1)) 213 else 214 n_missing=$((n_missing + 1)) 215 fi 216 done < "$DST_SRC/musl/skip.txt" 217 if [ "$n_missing" -gt 0 ]; then 218 echo "$TAG WARN: $n_missing skip-list entries were not present in $DST_SRC/musl" >&2 219 fi 220 echo "$TAG musl skip filter: dropped=$n_skip" 221 222 # ── (7) run.scm files ───────────────────────────────────────────────── 223 # Static run.scm (boot3) copied verbatim; the rest are generated. The 224 # musl tree is now stable, so boot5-enumerate + boot5-gen-runscm can 225 # run alongside boot4/boot6 generation. 226 mkdir -p "$DST/run" 227 cp bootprep/assets/boot3-run.scm "$DST/run/boot3.scm" 228 bootprep/boot4-gen-runscm.sh "$ARCH" 229 bootprep/boot5-enumerate.sh "$ARCH" 230 bootprep/boot5-gen-runscm.sh "$ARCH" 231 bootprep/boot6-gen-runscm.sh "$ARCH" 232 233 # ── summary ─────────────────────────────────────────────────────────── 234 n_files=$(find "$DST" -type f | wc -l | tr -d ' ') 235 echo "$TAG OK -> $DST ($n_files files)"