linux_bootstrap.sh (3488B)
1 #!/usr/bin/env bash 2 # Run the three-stage self-build (mk/bootstrap.mk) for aarch64-linux inside a 3 # Linux container, from a non-Linux dev host (e.g. an Apple-silicon Mac). 4 # 5 # The bootstrap is a NATIVE build: `make bootstrap` keys off the container's 6 # own uname (HOST_OS=linux + aarch64), so it selects the aarch64-linux ELF 7 # toolchain and reaches its fixed point entirely inside the container. No 8 # cross-compilation is involved -- the host only supplies podman + the repo. 9 # 10 # We run on the same arm64 Linux container family used by the hosted test 11 # suite: alpine (musl) or debian (glibc). The container needs a seed C 12 # compiler (clang) to build stage1; stages 2 and 3 are built by kit itself. 13 # 14 # usage: scripts/linux_bootstrap.sh [libc] [chain] 15 # libc musl (default, alpine) | glibc (debian) 16 # chain both (default) | debug (-O0) | release (-O1) 17 # 18 # Env overrides: 19 # KIT_LINUX_BOOT_IMAGE container image (defaults per libc, below) 20 # KIT_LINUX_BOOT_PLATFORM podman --platform (default linux/arm64) 21 # KIT_LINUX_BOOT_TOY=1 also run the Toy corpus through the stage3 compiler 22 # 23 # The stage tree lands under build/linux-boot/<libc>/ on the host (gitignored), 24 # so artifacts survive the run for inspection / per-object diffing. 25 26 set -eu 27 28 ROOT="$(cd "$(dirname "$0")/.." && pwd)" 29 LIBC="${1:-musl}" 30 CHAIN="${2:-both}" 31 PLATFORM="${KIT_LINUX_BOOT_PLATFORM:-linux/arm64}" 32 33 case "$LIBC" in 34 musl) DEF_IMAGE="docker.io/library/alpine:3.23" ;; 35 glibc) DEF_IMAGE="docker.io/arm64v8/debian:bookworm-slim" ;; 36 *) echo "linux_bootstrap: unknown libc '$LIBC' (want musl|glibc)" >&2; exit 2 ;; 37 esac 38 IMAGE="${KIT_LINUX_BOOT_IMAGE:-$DEF_IMAGE}" 39 40 case "$CHAIN" in 41 both) TARGET="bootstrap" ;; 42 debug) TARGET="bootstrap-debug" ;; 43 release) TARGET="bootstrap-release" ;; 44 *) echo "linux_bootstrap: unknown chain '$CHAIN' (want both|debug|release)" >&2; exit 2 ;; 45 esac 46 47 TOY="${KIT_LINUX_BOOT_TOY:-0}" 48 BUILD_DIR="build/linux-boot/$LIBC" 49 50 # In-container provisioning + build. The package sets give: a seed clang/lld, 51 # make, the libc dev headers, binutils (ar/ranlib used by the host stage1 52 # link), the ASan/UBSan runtime + unwinder for the -O0 stage1, and perl (the 53 # `shasum` the bootstrap recipe prints with). detect_leaks=0 because kit is 54 # arena-allocated and never frees -- LeakSanitizer (absent on the macOS 55 # reference host, which is why this only bites on Linux) would otherwise abort 56 # every stage1 cc invocation. 57 case "$LIBC" in 58 musl) 59 PROVISION='apk add --no-cache clang lld make musl-dev binutils compiler-rt libgcc perl-utils bash >/dev/null' 60 ;; 61 glibc) 62 PROVISION='export DEBIAN_FRONTEND=noninteractive; apt-get update -qq >/dev/null && apt-get install -y -qq clang lld make libc6-dev binutils perl >/dev/null' 63 ;; 64 esac 65 66 read -r -d '' REMOTE <<EOF || true 67 set -eu 68 $PROVISION 69 cd /work 70 echo "=== linux_bootstrap: \$(uname -m) / $LIBC / $TARGET ===" 71 clang --version | head -1 72 make $TARGET BUILD_DIR='$BUILD_DIR' CC=clang AR=ar 73 if [ "$TOY" = "1" ]; then 74 for m in debug release; do 75 s3="$BUILD_DIR/\$m/bootstrap/stage3/kit" 76 [ -x "\$s3" ] || continue 77 echo "=== Toy corpus through \$m stage3 ===" 78 KIT="\$(pwd)/\$s3" test/toy/run.sh || true 79 done 80 fi 81 echo "=== linux_bootstrap: DONE $TARGET ===" 82 EOF 83 84 exec podman run --rm --platform "$PLATFORM" \ 85 -e ASAN_OPTIONS=halt_on_error=1:abort_on_error=1:detect_leaks=0 \ 86 -e UBSAN_OPTIONS=halt_on_error=1:print_stacktrace=1 \ 87 -v "$ROOT":/work:Z \ 88 "$IMAGE" sh -c "$REMOTE"