diff options
Diffstat (limited to 'src/boot/boot.sh')
| -rwxr-xr-x | src/boot/boot.sh | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/src/boot/boot.sh b/src/boot/boot.sh new file mode 100755 index 0000000..c7eb2ed --- /dev/null +++ b/src/boot/boot.sh @@ -0,0 +1,50 @@ +#!/bin/sh +# bootstraps the compiler from the pinned wasm seed. usage: src/boot/boot.sh OUTDIR +# checks seed/zc.wasm against seed/MANIFEST, then under a wasm runtime (wasmtime, or +# node) the seed compiles the compiler sources to g1 and g1 compiles them to g2; when +# they differ g2 compiles them to g3 and g2 = g3 is required (the fixpoint). the result is +# OUTDIR/genome.bin. the seed is proven by the fixpoint, not trusted. nothing here +# uses the c core. +set -e +cd "$(dirname "$0")/../.." +OUT=${1:?outdir}; SEED=${SEED:-seed/zc.wasm}; MAN=${MAN:-seed/MANIFEST} +mkdir -p "$OUT" +sha() { if command -v sha256sum >/dev/null 2>&1; then sha256sum "$1" | cut -d' ' -f1; else shasum -a 256 "$1" | cut -d' ' -f1; fi; } +want=$(sed -n 's/^seed-sha256 //p' "$MAN"); got=$(sha "$SEED") +if [ -z "$BOOT_NOCHECK" ] && [ "$want" != "$got" ]; then + echo "boot: $SEED does not match $MAN" >&2 + echo "boot: manifest sha256 $want" >&2 + echo "boot: file sha256 $got" >&2 + echo "boot: the seed was changed or damaged; restore it from git, or run make seed to rebuild it on purpose" >&2 + exit 1 +fi +if [ -n "$WASM_RUNTIME" ]; then RT=$WASM_RUNTIME +elif command -v wasmtime >/dev/null 2>&1; then RT=wasmtime +elif command -v node >/dev/null 2>&1 && node -e 'process.exit(+process.versions.node.split(".")[0] < 18 ? 1 : 0)' 2>/dev/null; then RT=node +else + echo "boot: no WebAssembly runtime found. the compiler is built from seed/zc.wasm under one of:" >&2 + echo "boot: node 18 or later (macOS: brew install node; debian/ubuntu: apt install nodejs)" >&2 + echo "boot: wasmtime (macOS: brew install wasmtime; elsewhere: curl https://wasmtime.dev/install.sh -sSf | bash)" >&2 + exit 1 +fi +run() { case "$RT" in node) node src/boot/run.mjs "$1" ;; wasmtime) wasmtime run --dir=. "$1" ;; *) $RT "$1" ;; esac; } +le64() { n=$1 i=0; while [ $i -lt 8 ]; do printf "\\$(printf %03o $(( (n >> (8 * i)) & 255 )))"; i=$((i + 1)); done; } +SRC="src/runtime/rt.zc src/core/core.zc $(sed 's#^#src/compiler/#' src/compiler/parts | tr '\n' ' ')" +input() { cat src/tools/build.zc; printf '`'; cat $SRC; } +stage() { # stage IMAGE OUT: IMAGE empty means the seed's own genome + { if [ -n "$1" ]; then printf 'ZCIMAGE\n'; le64 $(wc -c < "$1"); cat "$1"; fi; input; } | run "$SEED" > "$2.tmp" + mv "$2.tmp" "$2" +} +echo "boot: seed $got ok, runtime $RT" +stage "" "$OUT/g1.bin"; echo "boot: g1 (seed -> sources): $(sha "$OUT/g1.bin")" +[ "${BOOT_STAGES:-}" = 1 ] && exit 0 +img=$(sed -n 's/^image-sha256 //p' "$MAN") +[ -n "$img" ] && { [ "$img" = "$(sha "$OUT/g1.bin")" ] && echo "boot: g1 is the image the manifest records" || echo "boot: g1 differs from the manifest's image (the sources changed since the seed was made)"; } +stage "$OUT/g1.bin" "$OUT/g2.bin"; echo "boot: g2 (g1 -> sources): $(sha "$OUT/g2.bin")" +if cmp -s "$OUT/g1.bin" "$OUT/g2.bin"; then + # g1 rebuilt itself unchanged, so it is the fixpoint: a third stage would only repeat it + cp "$OUT/g2.bin" "$OUT/genome.bin"; echo "boot: fixpoint (g1 = g2)"; exit 0 +fi +stage "$OUT/g2.bin" "$OUT/g3.bin"; echo "boot: g3 (g2 -> sources): $(sha "$OUT/g3.bin")" +cmp "$OUT/g2.bin" "$OUT/g3.bin" || { echo "boot: no fixpoint: g2 and g3 differ" >&2; exit 1; } +cp "$OUT/g2.bin" "$OUT/genome.bin"; echo "boot: fixpoint (g2 = g3)" |
