build: wire `make binary` to a self-built vendored Chez Scheme

ober

4a2b47dabebbc065ac5195b16235b73385a79ba4

diff --git a/.gitignore b/.gitignore
index 28e238e..2581759 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,6 +12,10 @@
 /jerboa-bin-main.c
 /jerboa-bin.wp.so
 
+# Repo-local Chez build/install artifacts
+/.chez/
+/build/
+
 # Rust build artifacts
 jerboa-native-rs/target/
 
diff --git a/Makefile b/Makefile
index 15d68eb..62034e1 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,21 @@
-SCHEME = scheme
+JERBOA_HOME := $(CURDIR)
+CHEZ_BUILD_DIR ?= $(JERBOA_HOME)/build/chez
+CHEZ_PREFIX ?= $(JERBOA_HOME)/.chez
+SCHEME ?= $(CHEZ_PREFIX)/bin/scheme
+
+# Detect host machine type from the vendored configure script (e.g. tarm64osx
+# on macOS arm64, ta6le on x86_64 linux). Used as XM= when bootstrapping
+# native boot files via pb. Pulled out into a helper script because the sed
+# pattern contains parens that confuse Make's $(shell ...) scanner.
+CHEZ_MACHINE_TYPE := $(shell $(JERBOA_HOME)/support/detect-chez-machine.sh)
+
+CHEZ_INSTALL_FLAGS = \
+	--installprefix=$(CHEZ_PREFIX) \
+	--installbin=$(CHEZ_PREFIX)/bin \
+	--installlib=$(CHEZ_PREFIX)/lib \
+	--installman=$(CHEZ_PREFIX)/share/man \
+	--installdoc=$(CHEZ_PREFIX)/share/doc \
+	--as-is
 LIBDIRS = lib
 # Base directory for chez-* repos (legacy C FFI — see `make native` for Rust backend)
 CHEZ_EXT_DIR ?= $(HOME)/src
@@ -7,12 +24,13 @@ CHEZ_EXT_LIBDIRS = $(CHEZ_EXT_DIR)/chez-https/src:$(CHEZ_EXT_DIR)/chez-ssl/src:$
 # Shared object paths for legacy FFI-based chez-* libraries
 CHEZ_EXT_LDPATH = $(CHEZ_EXT_DIR)/chez-ssl:$(CHEZ_EXT_DIR)/chez-zlib:$(CHEZ_EXT_DIR)/chez-pcre2:$(CHEZ_EXT_DIR)/chez-leveldb:$(CHEZ_EXT_DIR)/chez-epoll:$(CHEZ_EXT_DIR)/chez-inotify:$(CHEZ_EXT_DIR)/chez-crypto:$(CHEZ_EXT_DIR)/chez-sqlite:$(CHEZ_EXT_DIR)/chez-postgresql
 
-.PHONY: help build binary test test-reader test-core test-runtime test-stdlib test-ffi test-modules test-expanded test-features test-wrappers test-phase4a test-phase4b test-phase4c test-phase4d test-phase4e test-phase4f test-phase5 test-phase5e test-phase6 test-phase7 test-phase8 test-functional test-repl test-security test-native test-gaps native clean-native audit-native clean fuzz fuzz-smoke fuzz-deep fuzz-reader-fuzz fuzz-json-fuzz fuzz-http2-fuzz fuzz-websocket-fuzz fuzz-dns-fuzz fuzz-pregexp-fuzz fuzz-csv-fuzz fuzz-base64-fuzz fuzz-hex-fuzz fuzz-uri-fuzz fuzz-format-fuzz fuzz-router-fuzz fuzz-sandbox-fuzz test-rawstring test-regex test-rx test-peg test-regex-all check-docs check-docs-strict docker-build docker-push
+.PHONY: help chez build binary test test-reader test-core test-runtime test-stdlib test-ffi test-modules test-expanded test-features test-wrappers test-phase4a test-phase4b test-phase4c test-phase4d test-phase4e test-phase4f test-phase5 test-phase5e test-phase6 test-phase7 test-phase8 test-functional test-repl test-security test-native test-gaps native clean-native audit-native clean fuzz fuzz-smoke fuzz-deep fuzz-reader-fuzz fuzz-json-fuzz fuzz-http2-fuzz fuzz-websocket-fuzz fuzz-dns-fuzz fuzz-pregexp-fuzz fuzz-csv-fuzz fuzz-base64-fuzz fuzz-hex-fuzz fuzz-uri-fuzz fuzz-format-fuzz fuzz-router-fuzz fuzz-sandbox-fuzz test-rawstring test-regex test-rx test-peg test-regex-all check-docs check-docs-strict docker-build docker-push
 
 help:
 	@echo "Usage: make <target>"
 	@echo ""
 	@echo "Build:"
+	@echo "  chez             Build and install vendored Chez Scheme locally"
 	@echo "  build            Compile all Jerboa libraries"
 	@echo "  binary           Build a self-contained jerboa-bin binary (FreeBSD/Linux/macOS)"
 	@echo "  native           Build Rust native library"
@@ -69,7 +87,26 @@ help:
 	@echo "  docker-build     Build jerboa21/jerboa base image"
 	@echo "  docker-push      Push base image to Docker Hub"
 
-build:
+chez: $(SCHEME)
+
+# Two-phase build:
+#   1. Configure with --pb and run `make bootquick XM=$(CHEZ_MACHINE_TYPE)` so
+#      the committed pb boot files compile native boot files for the host.
+#   2. Reconfigure for the native machine type, then `make && make install`
+#      builds the native kernel + scheme using the freshly-bootstrapped
+#      boot files, and installs to $(CHEZ_PREFIX) (./.chez by default).
+$(SCHEME): vendor/ChezScheme/configure
+	@test -n "$(CHEZ_MACHINE_TYPE)" \
+		|| { echo "ERROR: could not detect host machine type from configure --help" >&2; exit 1; }
+	@mkdir -p $(CHEZ_BUILD_DIR)
+	cd $(CHEZ_BUILD_DIR) && $(JERBOA_HOME)/vendor/ChezScheme/configure --pb --as-is
+	$(MAKE) -C $(CHEZ_BUILD_DIR) bootquick XM=$(CHEZ_MACHINE_TYPE)
+	cd $(CHEZ_BUILD_DIR) && $(JERBOA_HOME)/vendor/ChezScheme/configure $(CHEZ_INSTALL_FLAGS)
+	$(MAKE) -C $(CHEZ_BUILD_DIR)
+	$(MAKE) -C $(CHEZ_BUILD_DIR) install
+	test -x $(SCHEME)
+
+build: chez
 	$(SCHEME) --libdirs $(LIBDIRS) --script support/build.ss
 
 # Build a self-contained Jerboa binary that bundles petite.boot, scheme.boot,
@@ -77,8 +114,8 @@ build:
 # Override entry script with BINARY_ENTRY=path/to/script.ss
 BINARY_ENTRY ?= support/binary-entry.ss
 BINARY_OUTPUT ?= jerboa-bin
-binary: build
-	SCHEME=$(SCHEME) support/build-binary.sh $(BINARY_ENTRY) $(BINARY_OUTPUT)
+binary: chez build
+	SCHEME=$(SCHEME) JERBOA_CHEZ_PREFIX=$(CHEZ_PREFIX) support/build-binary.sh $(BINARY_ENTRY) $(BINARY_OUTPUT)
 
 test: test-reader test-core test-runtime test-stdlib test-ffi test-modules test-expanded test-regex-all
 
diff --git a/bin/jerboa b/bin/jerboa
index 326cc77..99a7596 100755
--- a/bin/jerboa
+++ b/bin/jerboa
@@ -9,10 +9,16 @@ set -euo pipefail
 SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
 JERBOA_HOME="${JERBOA_HOME:-$(cd "$SCRIPT_DIR/.." && pwd)}"
 
-SCHEME="${SCHEME:-scheme}"
+SCHEME="${SCHEME:-$JERBOA_HOME/.chez/bin/scheme}"
 LIBDIRS="$JERBOA_HOME/lib"
 VERSION="0.1.0"
 
+if [ ! -x "$SCHEME" ]; then
+    echo "Error: Chez Scheme not found at $SCHEME" >&2
+    echo "Run 'make chez' from $JERBOA_HOME to build the repo-local Scheme." >&2
+    exit 1
+fi
+
 # Colors for test output (disabled if not a terminal)
 if [ -t 1 ]; then
     GREEN='\033[0;32m'
diff --git a/support/build-binary.sh b/support/build-binary.sh
index 8a175b8..3160204 100755
--- a/support/build-binary.sh
+++ b/support/build-binary.sh
@@ -4,9 +4,8 @@
 # Usage:
 #   support/build-binary.sh <entry.ss> <output-name>
 #
-# Portable across FreeBSD, Linux, and macOS — uses the system Chez install
-# (libkernel.a + petite.boot + scheme.boot) discovered by globbing standard
-# prefixes for csv*/<machine-type>/.
+# Portable across FreeBSD, Linux, and macOS — uses the repo-local Chez install
+# by default, falling back to standard prefixes when explicitly overridden.
 #
 # Output: ./<output-name>  (a real ELF/Mach-O binary that runs Jerboa)
 
@@ -21,7 +20,8 @@ SCRIPT="$1"
 OUTPUT="$2"
 
 JERBOA_HOME="${JERBOA_HOME:-$(cd "$(dirname "$0")/.." && pwd)}"
-SCHEME="${SCHEME:-scheme}"
+SCHEME="${SCHEME:-$JERBOA_HOME/.chez/bin/scheme}"
+JERBOA_CHEZ_PREFIX="${JERBOA_CHEZ_PREFIX:-$JERBOA_HOME/.chez}"
 LIBDIRS="${JERBOA_HOME}/lib"
 
 # ── Detect OS and pick compiler + base link flags ────────────────────────────
@@ -58,7 +58,7 @@ EOF
 )
 
 CSV_DIR=""
-for prefix in /usr/local/lib /usr/lib /usr/lib64 /opt/homebrew/lib /opt/local/lib; do
+for prefix in "$JERBOA_CHEZ_PREFIX/lib" /usr/local/lib /usr/lib /usr/lib64 /opt/homebrew/lib /opt/local/lib; do
     for d in "$prefix"/csv*/"$MACHINE_TYPE"; do
         if [ -f "$d/libkernel.a" ] && [ -f "$d/scheme.h" ] && [ -f "$d/petite.boot" ]; then
             CSV_DIR="$d"
@@ -70,7 +70,7 @@ done
 if [ -z "$CSV_DIR" ]; then
     echo "ERROR: cannot find Chez install for machine-type '$MACHINE_TYPE'." >&2
     echo "       Searched csv*/$MACHINE_TYPE under:" >&2
-    echo "         /usr/local/lib /usr/lib /usr/lib64 /opt/homebrew/lib /opt/local/lib" >&2
+    echo "         $JERBOA_CHEZ_PREFIX/lib /usr/local/lib /usr/lib /usr/lib64 /opt/homebrew/lib /opt/local/lib" >&2
     exit 1
 fi
 
diff --git a/support/detect-chez-machine.sh b/support/detect-chez-machine.sh
new file mode 100755
index 0000000..3b36e6b
--- /dev/null
+++ b/support/detect-chez-machine.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+# Print the host machine type that the vendored Chez Scheme configure
+# infers, e.g. "tarm64osx" on macOS arm64, "ta6le" on x86_64 Linux.
+#
+# Used by the Makefile's `chez` target to pick XM= when bootstrapping
+# native boot files from the committed pb boot files.
+
+set -eu
+
+SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
+exec "$SCRIPT_DIR/../vendor/ChezScheme/configure" --help 2>&1 \
+    | sed -n 's/.*--machine=<machine type>.*(\([^)]*\)).*/\1/p' \
+    | head -1