kit

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

freebsd_bootstrap.sh (6964B)


      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 #   KIT_FREEBSD_BOOT_SEED      repo-relative path to a pre-built stage1 kit. When
     22 #                              set, stage1 is this host-cross-compiled seed
     23 #                              instead of an in-VM clang build (so clang is never
     24 #                              exercised in the VM); only kit's stages 2/3 run
     25 #                              there. Build one with:
     26 #                              scripts/kit_cross.sh freebsd-<arch> --cc=clang
     27 
     28 set -eu
     29 
     30 ROOT="$(cd "$(dirname "$0")/.." && pwd)"
     31 ARCH="${1:-aarch64}"
     32 CHAIN="${2:-both}"
     33 
     34 case "$ARCH" in
     35   aarch64|arm64|aa64) ARCH=aarch64 ;;
     36   amd64|x64|x86_64)   ARCH=amd64 ;;
     37   *) echo "freebsd_bootstrap: unsupported arch '$ARCH'" >&2; exit 2 ;;
     38 esac
     39 
     40 case "$CHAIN" in
     41   both)    TARGET="bootstrap" ;;
     42   debug)   TARGET="bootstrap-debug" ;;
     43   release) TARGET="bootstrap-release" ;;
     44   *) echo "freebsd_bootstrap: unknown chain '$CHAIN' (want both|debug|release)" >&2; exit 2 ;;
     45 esac
     46 
     47 KEEP_UP="${KIT_FREEBSD_VM_KEEP_UP:-0}"
     48 TOY="${KIT_FREEBSD_BOOT_TOY:-0}"
     49 SEED="${KIT_FREEBSD_BOOT_SEED:-}"
     50 BUILD_DIR="build/freebsd-boot/$ARCH"
     51 
     52 if [ -n "$SEED" ]; then
     53   [ -x "$ROOT/$SEED" ] || { echo "freebsd_bootstrap: seed not found/executable: $ROOT/$SEED (build with scripts/kit_cross.sh freebsd-$ARCH --cc=clang)" >&2; exit 2; }
     54 fi
     55 
     56 # Hybrid (seeded) vs in-VM clang stage1. A seed feeds mk/bootstrap.mk a
     57 # host-cross-compiled stage1, so clang is never run in the VM.
     58 if [ -n "$SEED" ]; then
     59   BUILD_LINE="\$MAKE $TARGET BUILD_DIR='$BUILD_DIR' BOOTSTRAP_SEED='/home/kit/work/$SEED' MAKE=\"\$MAKE\""
     60   CC_BANNER="echo \"stage1 seed: $SEED\"; /home/kit/work/$SEED --help >/dev/null 2>&1 && echo 'seed runs' || echo 'seed FAILED to run'"
     61 else
     62   BUILD_LINE="\$MAKE $TARGET BUILD_DIR='$BUILD_DIR' CC=clang AR=ar MAKE=\"\$MAKE\""
     63   CC_BANNER="clang --version | head -1"
     64 fi
     65 
     66 ssh_vm() {
     67   scripts/freebsd_vm.sh ssh "$ARCH" "$@"
     68 }
     69 
     70 # Ensure VM is running.
     71 vm_started=0
     72 if ! scripts/freebsd_vm.sh ssh "$ARCH" true 2>/dev/null; then
     73   printf 'freebsd_bootstrap: starting %s VM\n' "$ARCH"
     74   scripts/freebsd_vm.sh run "$ARCH" &
     75   scripts/freebsd_vm.sh wait-ssh "$ARCH"
     76   vm_started=1
     77 fi
     78 
     79 # Send the source tree to the VM. Ship the working-tree content of every tracked
     80 # file (not `git archive HEAD`, which only sees committed state) so an
     81 # in-progress bootstrap test reflects uncommitted changes across the whole tree,
     82 # not just Makefile/mk/. git ls-files keeps build/ and other untracked/ignored
     83 # artifacts out -- the VM builds into /home/kit/work/build/.
     84 #
     85 # COPYFILE_DISABLE=1 stops macOS bsdtar from archiving each file's extended
     86 # attributes (every checkout carries a `com.apple.provenance` xattr) as an
     87 # AppleDouble `._<name>` pax sidecar. macOS tar merges those back on listing so
     88 # they look absent here, but FreeBSD's tar extracts them as literal `._*.c`
     89 # files, which the Makefile's `*.c` globs then try (and fail) to compile.
     90 printf 'freebsd_bootstrap: sending source tree to %s VM\n' "$ARCH"
     91 ssh_vm 'rm -rf /home/kit/work && mkdir -p /home/kit/work'
     92 git -C "$ROOT" ls-files -z | (cd "$ROOT" && COPYFILE_DISABLE=1 tar --null -T - -cf -) \
     93   | ssh_vm 'tar -C /home/kit/work -xf -'
     94 
     95 # The seed lives under build/ (gitignored), so it is not in the source tar —
     96 # stream it into the VM separately.
     97 if [ -n "$SEED" ]; then
     98   printf 'freebsd_bootstrap: sending stage1 seed to %s VM\n' "$ARCH"
     99   ssh_vm "mkdir -p /home/kit/work/$(dirname "$SEED")"
    100   ssh_vm "cat > /home/kit/work/$SEED && chmod +x /home/kit/work/$SEED" < "$ROOT/$SEED"
    101 fi
    102 
    103 printf 'freebsd_bootstrap: running %s bootstrap on %s\n' "$TARGET" "$ARCH"
    104 
    105 ssh_vm sh <<EOF
    106 set -eu
    107 cd /home/kit/work
    108 echo "=== freebsd_bootstrap: \$(uname -m) FreeBSD / $TARGET ==="
    109 $CC_BANNER
    110 # FreeBSD ships BSD make as 'make'; the kit Makefile requires GNU make (gmake).
    111 MAKE=\$(which gmake 2>/dev/null || which make)
    112 # Capture the bootstrap result without aborting the script: a chain that fails
    113 # (e.g. the -O1 release link) should still let the Toy corpus run through the
    114 # stage3 of any chain that did reach its fixed point.
    115 boot_rc=0
    116 $BUILD_LINE || boot_rc=\$?
    117 if [ "$TOY" = "1" ]; then
    118   # test/toy/run.sh needs bash (it uses arrays); the FreeBSD base system ships
    119   # only the POSIX /bin/sh, so a bash package must be installed (pkg install
    120   # bash). Skip with a clear note rather than fail cryptically when it is not.
    121   TOYSH=\$(which bash 2>/dev/null || true)
    122   if [ -z "\$TOYSH" ]; then
    123     echo "=== Toy corpus: SKIPPED (bash not installed; run 'pkg install bash') ==="
    124   else
    125     for m in debug release; do
    126       s3="$BUILD_DIR/\$m/bootstrap/stage3/kit"
    127       [ -x "\$s3" ] || continue
    128       echo "=== Toy corpus through \$m stage3 ==="
    129       KIT="\$(pwd)/\$s3" "\$TOYSH" test/toy/run.sh || true
    130     done
    131   fi
    132 fi
    133 echo "=== freebsd_bootstrap: DONE $TARGET (bootstrap rc=\$boot_rc) ==="
    134 exit \$boot_rc
    135 EOF
    136 
    137 # Bring back the stage3 binaries for inspection.
    138 STAGE3_OUT="$ROOT/build/freebsd-boot-$ARCH"
    139 mkdir -p "$STAGE3_OUT"
    140 for m in debug release; do
    141   remote="$BUILD_DIR/$m/bootstrap/stage3/kit"
    142   if ssh_vm test -f "/home/kit/work/$remote" 2>/dev/null; then
    143     scripts/freebsd_vm.sh scp "$ARCH" \
    144       "/home/kit/work/$remote" /dev/null 2>/dev/null || true
    145     # Use scp_arch directly for a real local copy.
    146     local_out="$STAGE3_OUT/kit.$m"
    147     port=$(scripts/freebsd_vm.sh ssh "$ARCH" 'echo $SSH_CLIENT' 2>/dev/null | awk '{print $2}' || echo 2223)
    148     port=2223
    149     SSH_KEY="$(ls "$HOME/.cache/kit/freebsd-vm"/*/ssh/id_ed25519 2>/dev/null | head -1)"
    150     if [ -f "$SSH_KEY" ]; then
    151       scp -P "$port" -i "$SSH_KEY" \
    152         -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o LogLevel=ERROR \
    153         "kit@127.0.0.1:/home/kit/work/$remote" "$local_out" 2>/dev/null || true
    154       [ -f "$local_out" ] && printf 'stage3 (%s): %s\n' "$m" "$local_out"
    155     fi
    156   fi
    157 done
    158 
    159 if [ "$KEEP_UP" != "1" ] && [ "$vm_started" = "1" ]; then
    160   printf 'freebsd_bootstrap: stopping VM\n'
    161   ssh_vm 'sudo shutdown -p now' 2>/dev/null || true
    162 fi