boot5-gen-runscm.sh (6905B)
1 #!/bin/sh 2 ## boot5-gen-runscm.sh — emit run.scm driving boot5's musl + hello build 3 ## inside the seed kernel. Mirrors boot/boot5.sh's podman-path script 4 ## generation step-for-step: per-source `tcc -c`, per-arch CRT, archive, 5 ## link hello. Source enumeration done by bootprep/boot5-enumerate.sh 6 ## at prep time; this script consumes the resulting build-srcs.txt and 7 ## emits one `(run "in/tcc" …)` form per TU. 8 ## 9 ## Usage: bootprep/boot5-gen-runscm.sh <arch> 10 ## Reads build/<arch>/src/run/boot5/{build-srcs.txt, crt-mode} 11 ## Writes build/<arch>/src/run/boot5.scm 12 ## 13 ## Conventions (cwd-relative; resolves to / under seed init, /work under 14 ## podman bind-mount): 15 ## musl tree in/musl/<rel-path> (read-only; canonical 16 ## tree from prep-src) 17 ## pre-gen hdrs in/musl/obj/include/bits/{alltypes,syscall}.h, 18 ## in/musl/obj/src/internal/version.h 19 ## .o outputs out/obj/musl/<src-with-.o> (rw; pre-mkdir'd by host) 20 ## tcc binary in/tcc (input) 21 ## libtcc1.a in/libtcc1.a (input) 22 ## stdarg bridge in/tcc-stdarg-bridge.h 23 ## hello.c in/hello.c 24 ## exports out/{libc.a,crt1.o,crti.o,crtn.o,hello} 25 ## (flat at out/ root so runscm_export pulls by basename) 26 27 set -eu 28 [ "$#" -eq 1 ] || { echo "usage: $0 <arch>" >&2; exit 2; } 29 ARCH=$1 30 case "$ARCH" in 31 aarch64) MUSL_ARCH=aarch64 ;; 32 amd64) MUSL_ARCH=x86_64 ;; 33 riscv64) MUSL_ARCH=riscv64 ;; 34 *) echo "boot5-gen: unsupported arch '$ARCH'" >&2; exit 2 ;; 35 esac 36 37 RUN_DIR=build/$ARCH/src/run 38 SRCS=$RUN_DIR/boot5/build-srcs.txt 39 CRT_MODE=$(cat "$RUN_DIR/boot5/crt-mode") 40 OUT=$RUN_DIR/boot5.scm 41 [ -e "$SRCS" ] || { echo "missing $SRCS (run bootprep/boot5-enumerate.sh $ARCH)" >&2; exit 1; } 42 mkdir -p "$(dirname "$OUT")" 43 44 CIN=in/musl 45 COUT=out/obj/musl 46 47 # Mirrors boot5.sh's CFLAGS_BASE exactly; the only difference is that 48 # every per-arg token is quoted as its own scheme bytevector. The leading 49 # "in/tcc" is the spawned binary; everything after is its argv. 50 CFLAGS_BASE_QUOTED='"-std=c99" "-nostdinc" "-ffreestanding" "-fno-strict-aliasing" "-D_XOPEN_SOURCE=700"' 51 CFLAGS_BASE_QUOTED="$CFLAGS_BASE_QUOTED \"-I$CIN/arch/$MUSL_ARCH\" \"-I$CIN/arch/generic\" \"-I$CIN/obj/src/internal\" \"-I$CIN/src/include\" \"-I$CIN/src/internal\" \"-I$CIN/obj/include\" \"-I$CIN/include\"" 52 CFLAGS_BASE_QUOTED="$CFLAGS_BASE_QUOTED \"-O2\" \"-fomit-frame-pointer\" \"-Werror=implicit-function-declaration\" \"-Werror=implicit-int\" \"-Werror=pointer-sign\" \"-Werror=pointer-arith\"" 53 CFLAGS_C_QUOTED="$CFLAGS_BASE_QUOTED \"-include\" \"in/tcc-stdarg-bridge.h\"" 54 CFLAGS_ASM_QUOTED="$CFLAGS_BASE_QUOTED" 55 CRTFLAGS_C_QUOTED="$CFLAGS_C_QUOTED \"-fno-stack-protector\" \"-DCRT\"" 56 CRTFLAGS_ASM_QUOTED="$CFLAGS_ASM_QUOTED \"-fno-stack-protector\" \"-DCRT\"" 57 58 # tcc 0.9.26's riscv64-link.c default ELF_START_ADDR=0x10000 sits below 59 # the seed kernel's USER_VA_LO (0x200000); land riscv64 user binaries 60 # in the same 0x600000 window the rest of the chain uses. amd64 61 # (0x400000) and aarch64 (0x400000) defaults already fit the window. 62 case "$MUSL_ARCH" in 63 riscv64) LINK_TTEXT='"-Wl,-Ttext=0x600000"' ;; 64 *) LINK_TTEXT= ;; 65 esac 66 67 { 68 cat <<'PROLOGUE' 69 ;; boot5 run.scm — drive musl-1.2.5 (~500 TUs) + hello. 70 ;; Generated by bootprep/boot5-gen-runscm.sh; consumed by both DRIVER=podman 71 ;; (cwd=/work bind mount) and DRIVER=seed (cwd=/, cpio rootfs). The musl 72 ;; source tree is staged read-only at in/tmp/musl-1.2.5/...; per-source .o 73 ;; outputs go to out/obj/musl-1.2.5/...; final artefacts (libc.a, crt1.o, 74 ;; crti.o, crtn.o, hello) land at flat out/ paths so runscm_export can 75 ;; pull them by basename. 76 77 (define (must r tag) 78 (if (and (car r) (= 0 (cdr r))) 79 r 80 (begin 81 (write-string stderr "boot5: step failed: ") 82 (write-string stderr tag) 83 (write-string stderr "\n") 84 (exit 1)))) 85 86 (write-string stdout "boot5: stage A (compile sources)\n") 87 PROLOGUE 88 89 # Stage A: per-source compile. Each line of build-srcs.txt is a path 90 # relative to musl-1.2.5/; choose flags by extension. 91 awk -v CFLAGS_C="$CFLAGS_C_QUOTED" -v CFLAGS_ASM="$CFLAGS_ASM_QUOTED" -v CIN="$CIN" -v COUT="$COUT" ' 92 { 93 src = $0 94 obj = src 95 sub(/\.[^.]*$/, ".o", obj) 96 if (src ~ /\.c$/) flags = CFLAGS_C 97 else if (src ~ /\.[sS]$/) flags = CFLAGS_ASM 98 else flags = CFLAGS_C 99 printf "(must (run \"in/tcc\" %s \"-c\" \"%s/%s\" \"-o\" \"%s/%s\") \"%s\")\n", \ 100 flags, CIN, src, COUT, obj, src 101 }' "$SRCS" 102 103 cat <<EOF 104 105 (write-string stdout "boot5: stage B (CRT)\n") 106 ;; Position-independent + non-PIC CRT helpers. -fPIC objects are needed 107 ;; for shared-binding tools, even though our hello is fully static. 108 (must (run "in/tcc" $CRTFLAGS_C_QUOTED "-fPIC" "-c" "$CIN/crt/Scrt1.c" "-o" "$COUT/crt/Scrt1.o") "Scrt1.o") 109 (must (run "in/tcc" $CRTFLAGS_C_QUOTED "-c" "$CIN/crt/crt1.c" "-o" "$COUT/crt/crt1.o") "crt1.o") 110 (must (run "in/tcc" $CRTFLAGS_C_QUOTED "-fPIC" "-c" "$CIN/crt/rcrt1.c" "-o" "$COUT/crt/rcrt1.o") "rcrt1.o") 111 EOF 112 113 if [ "$CRT_MODE" = asm ]; then 114 cat <<EOF 115 (must (run "in/tcc" $CRTFLAGS_ASM_QUOTED "-c" "$CIN/crt/$MUSL_ARCH/crti.s" "-o" "$COUT/crt/crti.o") "crti.o") 116 (must (run "in/tcc" $CRTFLAGS_ASM_QUOTED "-c" "$CIN/crt/$MUSL_ARCH/crtn.s" "-o" "$COUT/crt/crtn.o") "crtn.o") 117 EOF 118 else 119 cat <<EOF 120 (must (run "in/tcc" $CRTFLAGS_C_QUOTED "-c" "$CIN/crt/crti.c" "-o" "$COUT/crt/crti.o") "crti.o") 121 (must (run "in/tcc" $CRTFLAGS_C_QUOTED "-c" "$CIN/crt/crtn.c" "-o" "$COUT/crt/crtn.o") "crtn.o") 122 EOF 123 fi 124 125 # Stage C: archive libc.a. tcc -ar accepts many obj args; assemble the 126 # full list inline. The list is enormous (~1500 paths × ~40 chars = 127 # ~60 KB on a single line) but the prelude reader handles it fine. 128 { 129 printf '\n(write-string stdout "boot5: stage C (libc.a)\\n")\n' 130 printf '(must (run "in/tcc" "-ar" "rcs" "out/libc.a"' 131 awk -v COUT="$COUT" '{ 132 obj = $0 133 sub(/\.[^.]*$/, ".o", obj) 134 printf " \"%s/%s\"", COUT, obj 135 }' "$SRCS" 136 printf ') "libc.a")\n' 137 } 138 139 cat <<EOF 140 141 ;; Publish CRT objects at flat out/ paths so runscm_export can pull them. 142 (must (run "in/catm" "out/crt1.o" "$COUT/crt/crt1.o") "crt1.o publish") 143 (must (run "in/catm" "out/crti.o" "$COUT/crt/crti.o") "crti.o publish") 144 (must (run "in/catm" "out/crtn.o" "$COUT/crt/crtn.o") "crtn.o publish") 145 146 (write-string stdout "boot5: stage D (link hello)\n") 147 ;; -Lout pulls libc.a (just built); -Lin pulls libtcc1.a (input). 148 (must (run "in/tcc" "-static" "-nostdinc" "-nostdlib" "-include" "in/tcc-stdarg-bridge.h" $LINK_TTEXT 149 "-I$CIN/include" "-I$CIN/arch/$MUSL_ARCH" "-I$CIN/arch/generic" "-I$CIN/obj/include" 150 "out/crt1.o" "in/hello.c" "-Lout" "-lc" "-Lin" "-ltcc1" "-Lout" "-lc" "-o" "out/hello") "link hello") 151 152 (write-string stdout "boot5: ALL-OK\n") 153 (exit 0) 154 EOF 155 } > "$OUT"