kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

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