freebsd_bootstrap.sh (5452B)
1 #!/usr/bin/env bash 2 # Run the three-stage self-build (mk/bootstrap.mk) for a FreeBSD arch natively 3 # in the corresponding FreeBSD VM, from a macOS dev host. 4 # 5 # The bootstrap is a NATIVE build: `make bootstrap` keys off the VM's own uname 6 # (HOST_OS=freebsd + aarch64), so it selects the FreeBSD ELF toolchain and 7 # reaches its fixed point entirely inside the VM. No cross-compilation happens. 8 # 9 # The VM must be prepared (scripts/freebsd_vm.sh prepare <arch>) but does not 10 # need to be running -- this script starts it, waits for SSH, runs the build, 11 # and shuts it down (unless KIT_FREEBSD_VM_KEEP_UP=1). 12 # 13 # usage: scripts/freebsd_bootstrap.sh [arch] [chain] 14 # arch aarch64 (default; the only FreeBSD arch that has a native compiler 15 # installed in the base VM image today) 16 # chain both (default) | debug (-O0) | release (-O1) 17 # 18 # Env overrides: 19 # KIT_FREEBSD_VM_KEEP_UP=1 leave the VM running after the build 20 # KIT_FREEBSD_BOOT_TOY=1 also run the Toy corpus through the stage3 compiler 21 22 set -eu 23 24 ROOT="$(cd "$(dirname "$0")/.." && pwd)" 25 ARCH="${1:-aarch64}" 26 CHAIN="${2:-both}" 27 28 case "$ARCH" in 29 aarch64|arm64) ARCH=aarch64 ;; 30 amd64|x64) ARCH=amd64 ;; 31 *) echo "freebsd_bootstrap: unsupported arch '$ARCH'" >&2; exit 2 ;; 32 esac 33 34 case "$CHAIN" in 35 both) TARGET="bootstrap" ;; 36 debug) TARGET="bootstrap-debug" ;; 37 release) TARGET="bootstrap-release" ;; 38 *) echo "freebsd_bootstrap: unknown chain '$CHAIN' (want both|debug|release)" >&2; exit 2 ;; 39 esac 40 41 KEEP_UP="${KIT_FREEBSD_VM_KEEP_UP:-0}" 42 TOY="${KIT_FREEBSD_BOOT_TOY:-0}" 43 BUILD_DIR="build/freebsd-boot/$ARCH" 44 45 ssh_vm() { 46 scripts/freebsd_vm.sh ssh "$ARCH" "$@" 47 } 48 49 # Ensure VM is running. 50 vm_started=0 51 if ! scripts/freebsd_vm.sh ssh "$ARCH" true 2>/dev/null; then 52 printf 'freebsd_bootstrap: starting %s VM\n' "$ARCH" 53 scripts/freebsd_vm.sh run "$ARCH" & 54 scripts/freebsd_vm.sh wait-ssh "$ARCH" 55 vm_started=1 56 fi 57 58 # Send the source tree to the VM. Ship the working-tree content of every tracked 59 # file (not `git archive HEAD`, which only sees committed state) so an 60 # in-progress bootstrap test reflects uncommitted changes across the whole tree, 61 # not just Makefile/mk/. git ls-files keeps build/ and other untracked/ignored 62 # artifacts out -- the VM builds into /home/kit/work/build/. 63 # 64 # COPYFILE_DISABLE=1 stops macOS bsdtar from archiving each file's extended 65 # attributes (every checkout carries a `com.apple.provenance` xattr) as an 66 # AppleDouble `._<name>` pax sidecar. macOS tar merges those back on listing so 67 # they look absent here, but FreeBSD's tar extracts them as literal `._*.c` 68 # files, which the Makefile's `*.c` globs then try (and fail) to compile. 69 printf 'freebsd_bootstrap: sending source tree to %s VM\n' "$ARCH" 70 ssh_vm 'rm -rf /home/kit/work && mkdir -p /home/kit/work' 71 git -C "$ROOT" ls-files -z | (cd "$ROOT" && COPYFILE_DISABLE=1 tar --null -T - -cf -) \ 72 | ssh_vm 'tar -C /home/kit/work -xf -' 73 74 printf 'freebsd_bootstrap: running %s bootstrap on %s\n' "$TARGET" "$ARCH" 75 76 ssh_vm sh <<EOF 77 set -eu 78 cd /home/kit/work 79 echo "=== freebsd_bootstrap: \$(uname -m) FreeBSD / $TARGET ===" 80 clang --version | head -1 81 # FreeBSD ships BSD make as 'make'; the kit Makefile requires GNU make (gmake). 82 MAKE=\$(which gmake 2>/dev/null || which make) 83 # Capture the bootstrap result without aborting the script: a chain that fails 84 # (e.g. the -O1 release link) should still let the Toy corpus run through the 85 # stage3 of any chain that did reach its fixed point. 86 boot_rc=0 87 \$MAKE $TARGET BUILD_DIR='$BUILD_DIR' CC=clang AR=ar MAKE="\$MAKE" || boot_rc=\$? 88 if [ "$TOY" = "1" ]; then 89 # test/toy/run.sh needs bash (it uses arrays); the FreeBSD base system ships 90 # only the POSIX /bin/sh, so a bash package must be installed (pkg install 91 # bash). Skip with a clear note rather than fail cryptically when it is not. 92 TOYSH=\$(which bash 2>/dev/null || true) 93 if [ -z "\$TOYSH" ]; then 94 echo "=== Toy corpus: SKIPPED (bash not installed; run 'pkg install bash') ===" 95 else 96 for m in debug release; do 97 s3="$BUILD_DIR/\$m/bootstrap/stage3/kit" 98 [ -x "\$s3" ] || continue 99 echo "=== Toy corpus through \$m stage3 ===" 100 KIT="\$(pwd)/\$s3" "\$TOYSH" test/toy/run.sh || true 101 done 102 fi 103 fi 104 echo "=== freebsd_bootstrap: DONE $TARGET (bootstrap rc=\$boot_rc) ===" 105 exit \$boot_rc 106 EOF 107 108 # Bring back the stage3 binaries for inspection. 109 STAGE3_OUT="$ROOT/build/freebsd-boot-$ARCH" 110 mkdir -p "$STAGE3_OUT" 111 for m in debug release; do 112 remote="$BUILD_DIR/$m/bootstrap/stage3/kit" 113 if ssh_vm test -f "/home/kit/work/$remote" 2>/dev/null; then 114 scripts/freebsd_vm.sh scp "$ARCH" \ 115 "/home/kit/work/$remote" /dev/null 2>/dev/null || true 116 # Use scp_arch directly for a real local copy. 117 local_out="$STAGE3_OUT/kit.$m" 118 port=$(scripts/freebsd_vm.sh ssh "$ARCH" 'echo $SSH_CLIENT' 2>/dev/null | awk '{print $2}' || echo 2223) 119 port=2223 120 SSH_KEY="$(ls "$HOME/.cache/kit/freebsd-vm"/*/ssh/id_ed25519 2>/dev/null | head -1)" 121 if [ -f "$SSH_KEY" ]; then 122 scp -P "$port" -i "$SSH_KEY" \ 123 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o LogLevel=ERROR \ 124 "kit@127.0.0.1:/home/kit/work/$remote" "$local_out" 2>/dev/null || true 125 [ -f "$local_out" ] && printf 'stage3 (%s): %s\n' "$m" "$local_out" 126 fi 127 fi 128 done 129 130 if [ "$KEEP_UP" != "1" ] && [ "$vm_started" = "1" ]; then 131 printf 'freebsd_bootstrap: stopping VM\n' 132 ssh_vm 'sudo shutdown -p now' 2>/dev/null || true 133 fi