build.sh (4925B)
1 #!/bin/sh 2 ## build.sh — build a P1v2 .P1 source into a runnable aarch64 ELF binary. 3 ## 4 ## Mirrors the Makefile's PROG=m1m pipeline but targets the P1v2 DEFINE 5 ## table at build/p1v2/aarch64/p1_aarch64.M1. 6 ## 7 ## Usage: m1pp/build.sh <source.P1> <output_binary> 8 ## 9 ## Pipeline (mirrors Makefile PROG=m1m): 10 ## 1. lint — assert every P1v2 op token in source.P1 is defined 11 ## 2. prune — strip DEFINEs the source doesn't reference 12 ## 3. catm — pruned defs ++ source.P1 -> combined.M1 13 ## 4. M1 — combined.M1 -> .hex2 14 ## 5. catm — ELF header ++ .hex2 -> linked.hex2 15 ## 6. hex2 — linked.hex2 -> raw ELF 16 ## 7. chmod 0700, deposit at <output_binary> 17 ## 18 ## Default mode uses native-compiled mescc-tools M1/hex2 on the host: 19 ## ~150× faster than the bootstrap M0/hex2-0 on the linux/arm64 VM (the 20 ## bootstrap tools do one syscall per byte; mescc-tools uses buffered 21 ## stdio). Output is byte-exact — verified against the bootstrap chain 22 ## with --little-endian on both tools. 23 ## 24 ## This is a dev-loop convenience. It does not alter the bootstrap chain 25 ## itself: the stage0 M0/hex2-0 binaries under build/$ARCH/tools remain 26 ## the source of truth. Set M1PP_BOOTSTRAP_TOOLS=1 to force the original 27 ## container-based path (verification, or when mescc-tools is unavailable). 28 ## 29 ## Intermediates land in build/m1pp/<basename>.* for later inspection. 30 31 set -eu 32 33 if [ "$#" -ne 2 ]; then 34 echo "usage: $0 <source.P1> <output_binary>" >&2 35 exit 2 36 fi 37 38 SRC=$1 39 OUT=$2 40 41 REPO=$(cd "$(dirname "$0")/.." && pwd) 42 ARCH=aarch64 43 PLATFORM=linux/arm64 44 IMAGE=localhost/distroless-busybox:latest 45 CONTAINERFILE=Containerfile.busybox 46 47 P1_DEFS=build/p1v2/$ARCH/p1_$ARCH.M1 48 TOOLS=build/$ARCH/tools 49 ELF_HDR=build/upstream/AArch64/ELF-aarch64.hex2 50 BASE_ADDR=0x600000 ## must match the load address encoded in $ELF_HDR 51 52 NATIVE_TOOLS_DIR=build/native-tools 53 NATIVE_M1=$NATIVE_TOOLS_DIR/M1 54 NATIVE_HEX2=$NATIVE_TOOLS_DIR/hex2 55 56 cd "$REPO" 57 58 for f in "$P1_DEFS" "$ELF_HDR" lint.sh "$SRC"; do 59 if [ ! -e "$f" ]; then 60 echo "build.sh: missing dependency: $f" >&2 61 exit 1 62 fi 63 done 64 65 NAME=$(basename "$SRC" .P1) 66 WORK=build/m1pp/$NAME.work 67 mkdir -p "$WORK" "$(dirname "$OUT")" 68 69 PRUNED=$WORK/p1.pruned.M1 70 71 ## Step 1: lint. 72 sh lint.sh "$P1_DEFS" "$SRC" 73 74 ## Step 2: prune. Same awk one-liner as Makefile — collect all whitespace- 75 ## separated tokens from the source, keep only DEFINEs whose name appears. 76 awk 'NR==FNR{for(i=1;i<=NF;i++)u[$i]=1;next} /^DEFINE /{if($2 in u)print;next} {print}' \ 77 "$SRC" "$P1_DEFS" > "$PRUNED" 78 79 ## Steps 3-7: mode selection. 80 if [ "${M1PP_BOOTSTRAP_TOOLS:-0}" = 1 ]; then 81 ## Bootstrap mode: run stage0 M0/hex2-0 inside the container. Slow 82 ## (~110s on 1 MB m1pp.P1) but exercises the same code path the 83 ## seed/tcc-boot chain does. Stage through /tmp to dodge virtiofs. 84 for f in "$TOOLS/M0" "$TOOLS/hex2-0" "$TOOLS/catm"; do 85 if [ ! -e "$f" ]; then 86 echo "build.sh: missing bootstrap dependency: $f" >&2 87 exit 1 88 fi 89 done 90 if ! podman image exists "$IMAGE"; then 91 podman build -f "$CONTAINERFILE" -t "$IMAGE" . 92 fi 93 podman run --rm --pull=never --platform "$PLATFORM" \ 94 -v "$REPO":/work \ 95 -w /work \ 96 "$IMAGE" sh -ec " 97 set -eu 98 cp $PRUNED /tmp/p1.M1 99 cp $SRC /tmp/prog.M1 100 $TOOLS/catm /tmp/combined.M1 /tmp/p1.M1 /tmp/prog.M1 101 $TOOLS/M0 /tmp/combined.M1 /tmp/prog.hex2 102 103 cp $ELF_HDR /tmp/elf.hex2 104 $TOOLS/catm /tmp/linked.hex2 /tmp/elf.hex2 /tmp/prog.hex2 105 $TOOLS/hex2-0 /tmp/linked.hex2 /tmp/prog 106 chmod 0700 /tmp/prog 107 108 cp /tmp/combined.M1 $WORK/combined.M1 109 cp /tmp/prog.hex2 $WORK/prog.hex2 110 cp /tmp/linked.hex2 $WORK/linked.hex2 111 cp /tmp/prog $WORK/prog 112 " 113 else 114 ## Native mode (default): host-compiled mescc-tools M1/hex2. The 115 ## bootstrap chain is not invoked. Flags are chosen to make the 116 ## emitted aarch64 ELF bit-exact with the bootstrap build: 117 ## M1: --little-endian (default is big-endian; --architecture 118 ## aarch64 does NOT override that — see M1-macro.c:786). 119 ## hex2: --little-endian and --base-address matches $ELF_HDR. 120 if [ ! -x "$NATIVE_M1" ] || [ ! -x "$NATIVE_HEX2" ]; then 121 sh m1pp/build-native-tools.sh 122 fi 123 124 ## catm on the bootstrap side is just multi-file concat → shell cat 125 ## is equivalent. 126 cat "$PRUNED" "$SRC" > "$WORK/combined.M1" 127 "$NATIVE_M1" --architecture "$ARCH" --little-endian \ 128 -f "$WORK/combined.M1" -o "$WORK/prog.hex2" 129 cat "$ELF_HDR" "$WORK/prog.hex2" > "$WORK/linked.hex2" 130 "$NATIVE_HEX2" --architecture "$ARCH" --little-endian \ 131 --base-address "$BASE_ADDR" \ 132 -f "$WORK/linked.hex2" -o "$WORK/prog" 133 chmod 0700 "$WORK/prog" 134 fi 135 136 cp "$WORK/prog" "$OUT" 137 chmod 0700 "$OUT"