build-p1pp.sh (5151B)
1 #!/bin/sh 2 ## tests/build-p1pp.sh — in-container .P1pp -> ELF via the new chain. 3 ## 4 ## Pure transformation. Caller (the Makefile) ensures every fixed-path 5 ## input below already exists, including the per-arch self-hosted M1pp 6 ## ELF binary (build/$ARCH/podman/boot1/M1pp) and hex2pp ELF binary 7 ## (build/$ARCH/podman/boot1/hex2pp). Both of those are built once via 8 ## the seed M0+hex2 chain inside the bootN pipeline; after that point 9 ## the seed tools no longer participate in any user/test pipeline. 10 ## 11 ## Pipeline (new chain — no M0/hex2 anywhere): 12 ## cat <P1-$ARCH.M1pp> <P1.M1pp> <P1pp.P1pp> <srcs...> -> /tmp/combined.M1pp 13 ## M1pp /tmp/combined.M1pp -> /tmp/expanded.hex2pp 14 ## cat $ELF_HDR /tmp/expanded.hex2pp -> /tmp/linked.hex2pp 15 ## hex2pp /tmp/linked.hex2pp $OUT 16 ## 17 ## $ELF_HDR is vendor/seed/$ARCH/ELF.hex2, which supplies the 18 ## :ELF_base / :_start / :ELF_end framing. hex2pp accepts the hex2 19 ## `LABEL>OTHER` subtraction syntax as a synonym for its own 20 ## `LABEL-OTHER`, so the vendor headers assemble unchanged. 21 ## 22 ## libp1pp (P1/P1pp.P1pp) is concatenated unconditionally so portable 23 ## sources can use %fn, the control-flow macros, and libp1pp routines 24 ## (sys_*, print*, parse_*, fmt_*, memcpy/memcmp, bump allocator, panic, 25 ## %assert_*) without per-program plumbing. hex2pp has no link-time DCE, 26 ## so programs that don't reference any libp1pp routine still pay a 27 ## fixed code-size tax (~a few KB). 28 ## 29 ## Multiple <srcs> are concatenated in the order given. This is how 30 ## libc-using executables compose: a typical chain is 31 ## P1/entry-libc.P1pp build/$ARCH/podman/boot3/libc.P1pp client.P1pp P1/elf-end.P1pp 32 ## with libc.P1pp / client.P1pp produced by cc.scm --lib=PFX so they 33 ## omit the entry stub and trailing :ELF_end (those come from the 34 ## fixed fragments instead). For a single-TU exec, pass exactly one 35 ## source built without --lib= and the fragments are unnecessary. 36 ## 37 ## Per-call intermediates land at build/$ARCH/.work/<work-subpath>/. 38 ## <work-subpath> defaults to the first src's path with extension 39 ## stripped — fine for single-source builds (scheme1, p1 tests). For 40 ## catm chains where the first src is a wrapper (e.g. P1/entry-libc.P1pp 41 ## or a generated build/.../*.P1pp), the caller MUST set WORK_SUBPATH 42 ## explicitly so the work dir mirrors the logical primary source path 43 ## (e.g. tests/cc-libc/000-exit). A one-line sidecar at <out>.workdir 44 ## records the resolved work dir so tooling (tools/disasm-elf.sh) can 45 ## locate the artifacts from the binary alone. 46 ## 47 ## Env: ARCH=aarch64|amd64|riscv64 48 ## WORK_SUBPATH=<repo-relative-path-without-ext> — overrides the 49 ## work-dir name; required when the first src isn't 50 ## the logical primary source. 51 ## Usage: tests/build-p1pp.sh <out> <srcs...> 52 53 set -eu 54 55 # Per-stage tracing is always on. M1pp / hex2pp print little on success 56 # and bail fast on error, so we narrate which step is running, snapshot 57 # intermediates to $WORK before exiting, and print a clear FAIL banner 58 # on error so the user knows where it died. 59 ARCH_LBL=${ARCH:-?} 60 CURRENT_STEP= 61 trap 'rc=$? 62 if [ "$rc" -ne 0 ] && [ -n "$CURRENT_STEP" ]; then 63 echo "[p1pp $ARCH_LBL] FAIL at: $CURRENT_STEP (exit $rc)" >&2 64 if [ -n "${WORK:-}" ]; then 65 echo "[p1pp $ARCH_LBL] partial intermediates in $WORK" >&2 66 fi 67 fi' EXIT 68 69 trace() { 70 label=$1; path=$2 71 sz=$(wc -c < "$path" 2>/dev/null || echo "?") 72 printf '[p1pp %s] %s (%s bytes) %s\n' "$ARCH_LBL" "$label" "$sz" "$path" >&2 73 } 74 75 step() { 76 CURRENT_STEP=$1 77 printf '[p1pp %s] >> %s\n' "$ARCH_LBL" "$CURRENT_STEP" >&2 78 } 79 80 : "${ARCH:?ARCH must be set}" 81 [ "$#" -ge 2 ] || { echo "usage: ARCH=<arch> $0 <out> <srcs...>" >&2; exit 2; } 82 83 OUT=$1 84 shift 85 86 BACKEND=P1/P1-$ARCH.M1pp 87 FRONTEND=P1/P1.M1pp 88 LIBP1PP=P1/P1pp.P1pp 89 ELF_HDR=vendor/seed/$ARCH/ELF.hex2 90 M1PP_BIN=build/$ARCH/podman/boot1/M1pp 91 HEX2PP_BIN=build/$ARCH/podman/boot1/hex2pp 92 if [ -n "${WORK_SUBPATH:-}" ]; then 93 NAME=$WORK_SUBPATH 94 else 95 NAME=${1%.*} 96 fi 97 WORK=build/$ARCH/.work/$NAME 98 mkdir -p "$WORK" "$(dirname "$OUT")" 99 100 # Snapshot each intermediate to $WORK as soon as it's produced, so a 101 # failure leaves the most-recent good artifact on disk for triage. With 102 # the trap above, the user sees both the failing stage and where to 103 # look. 104 step "cat: combined.M1pp <- backend + frontend + libp1pp + $#" 105 cat "$BACKEND" "$FRONTEND" "$LIBP1PP" "$@" > /tmp/combined.M1pp 106 cp /tmp/combined.M1pp "$WORK/combined.M1pp" 107 trace "combined.M1pp" /tmp/combined.M1pp 108 109 step "M1pp: combined.M1pp -> expanded.hex2pp" 110 "$M1PP_BIN" /tmp/combined.M1pp /tmp/expanded.hex2pp 111 cp /tmp/expanded.hex2pp "$WORK/expanded.hex2pp" 112 trace "expanded.hex2pp" /tmp/expanded.hex2pp 113 114 step "cat: linked.hex2pp <- ELF header + expanded.hex2pp" 115 cat "$ELF_HDR" /tmp/expanded.hex2pp > /tmp/linked.hex2pp 116 cp /tmp/linked.hex2pp "$WORK/linked.hex2pp" 117 trace "linked.hex2pp" /tmp/linked.hex2pp 118 119 step "hex2pp: linked.hex2pp -> $OUT" 120 "$HEX2PP_BIN" -B 0x600000 /tmp/linked.hex2pp /tmp/prog.bin 121 cp /tmp/prog.bin "$OUT" 122 chmod 0700 "$OUT" 123 trace "$OUT" "$OUT" 124 125 printf '%s\n' "$WORK" > "$OUT.workdir" 126 CURRENT_STEP=