| 1 | #!/usr/bin/env bash |
| 2 | # Proves a toolchain can make a runnable linux-arm64 binary: builds the |
| 3 | # hello-world in scripts/smoke/<lang>, checks it is aarch64 and static (or |
| 4 | # libc-only), and runs it under qemu. Prints "<lang>: ok" on success. |
| 5 | # scripts/smoke.sh <go|rust|zig|ocaml|haskell|swift|nim|spinel> |
| 6 | set -euo pipefail |
| 7 | here=$(cd "$(dirname "$0")" && pwd) |
| 8 | source "$here/env.sh" |
| 9 | lang=$1 |
| 10 | src="$here/smoke/$lang" |
| 11 | out=$(mktemp -d -p "${TMPDIR:-$HOME/.cache}") |
| 12 | trap 'rm -rf "$out"' EXIT |
| 13 | bin="$out/smoke" |
| 14 | case $lang in |
| 15 | go) (cd "$src" && CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -o "$bin" .) ;; |
| 16 | rust) (cd "$src" && CARGO_TARGET_DIR="$out/target" cargo zigbuild -q --release --target aarch64-unknown-linux-musl && |
| 17 | cp "$out/target/aarch64-unknown-linux-musl/release/smoke" "$bin") ;; |
| 18 | zig) (cd "$out" && zig build-exe -target aarch64-linux-musl -O ReleaseSmall -femit-bin="$bin" "$src/main.zig") ;; |
| 19 | swift) (cd "$src" && swift build -q -c release --swift-sdk aarch64-swift-linux-musl --scratch-path "$out/build" && |
| 20 | cp "$out/build/aarch64-swift-linux-musl/release/smoke" "$bin") ;; |
| 21 | ocaml) cp "$src/main.ml" "$out/" && (cd "$out" && "$here/arm64.sh" ocamlfind ocamlopt -package unix -linkpkg -ccopt -static main.ml -o smoke) ;; |
| 22 | haskell) cp "$src/Main.hs" "$out/" && (cd "$out" && "$here/arm64.sh" ghc -O -static -optl-static -optl-pthread Main.hs -o smoke >/dev/null) ;; |
| 23 | mojo) cp "$src/main.mojo" "$out/" && (cd "$out" && "$here/arm64.sh" /root/.pixi/bin/mojo build main.mojo -o smoke 2>/dev/null) ;; |
| 24 | spinel) "$here/smoke-spinel.sh" "$src/main.rb" "$bin" ;; |
| 25 | nim) (cd "$out" && nim c --hints:off -d:release --cpu:arm64 --os:linux --cc:clang \ |
| 26 | --clang.exe="$here/zigcc-aarch64-musl" --clang.linkerexe="$here/zigcc-aarch64-musl" \ |
| 27 | --passL:-static --nimcache:"$out/cache" -o:"$bin" "$src/main.nim" >/dev/null) ;; |
| 28 | *) echo "unknown language $lang" >&2; exit 2 ;; |
| 29 | esac |
| 30 | desc=$(file -b "$bin") |
| 31 | echo "$lang: $desc" | cut -c1-160 |
| 32 | case $desc in *aarch64*) ;; *) echo "$lang: not an aarch64 binary" >&2; exit 1 ;; esac |
| 33 | case $desc in *"statically linked"*|*"static-pie"*) ;; *) |
| 34 | extra=$(readelf -d "$bin" | sed -n 's/.*(NEEDED).*\[\(.*\)\]/\1/p' | grep -Ev '^(libc|libm|libpthread|libdl|librt|ld-linux-aarch64)\.so' || true) |
| 35 | [ -z "$extra" ] || { echo "$lang: needs shared libraries beyond libc: $extra" >&2; exit 1; } ;; |
| 36 | esac |
| 37 | got=$(qemu-aarch64-static -L "${BAKEOFF_TOOLCHAINS:-$HOME/.local/share/bakeoff-toolchains}/arm64root" "$bin") |
| 38 | [ "$got" = ok ] || { echo "$lang: printed '$got', want ok" >&2; exit 1; } |
| 39 | echo "$lang: ok" |
| 40 | |