build: parameterize cross-compile by TARGET_ARCH (amd64|arm64)
ober
976fc91e3476d3c4b9b7476c2b8fffb1b7f992a7
--- a/Makefile +++ b/Makefile @@ -15,7 +15,7 @@ TUI_SHIM_DIR := $(CURDIR)/vendor/termbox2 NATIVE_LIB_DIR := $(JERBOA_HOME)/lib LDPATH := $(SHIM_DIR):$(TUI_SHIM_DIR):$(SQLITE_LIB_DIR):$(NATIVE_LIB_DIR) -.PHONY: all help build gen run test test-providers clean repl binary install tui-shim run-tui jcode-musl linux linux-amd64 jcode-linux-amd64 linux-docker linux-check linux-local docker test-linux test-linux-amd64 purge-stale sqlite-shim android android-clean +.PHONY: all help build gen run test test-providers clean repl binary install tui-shim run-tui jcode-musl linux linux-amd64 linux-arm64 jcode-linux-amd64 linux-docker linux-check linux-local docker test-linux test-linux-amd64 purge-stale sqlite-shim android android-clean all: help @@ -31,7 +31,8 @@ help: @echo " binary Build native binary (macOS)" @echo " install Install binary to ~/.local/bin" @echo " linux Build Linux x86_64 static binary (cross-compile from this host)" - @echo " linux-amd64 Same as 'linux' (explicit arch name)" + @echo " linux-amd64 Cross-compile static jcode-linux-amd64 (default)" + @echo " linux-arm64 Cross-compile static jcode-linux-arm64" @echo " linux-docker Build static musl binary via Docker (slower; canonical)" @echo " linux-local Build static musl binary on host (Linux only)" @echo " linux-check Fast drift check for musl build path" @@ -254,7 +255,21 @@ linux-amd64: gen @command -v cargo >/dev/null 2>&1 || { \ echo "ERROR: cargo not found on PATH. Install rustup from rustup.rs"; \ exit 1; } - JERBOA_HOME=$(JERBOA_HOME) $(SCHEME) -q --libdirs "$(XC_LIBDIRS)" --script build-jcode-cross.ss + JERBOA_HOME=$(JERBOA_HOME) TARGET_ARCH=amd64 $(SCHEME) -q --libdirs "$(XC_LIBDIRS)" --script build-jcode-cross.ss + +linux-arm64: gen + @command -v aarch64-linux-musl-gcc >/dev/null 2>&1 || { \ + echo "ERROR: aarch64-linux-musl-gcc not found on PATH."; \ + echo "Install with: brew install FiloSottile/musl-cross/musl-cross"; \ + exit 1; } + @test -d $(JERBOA_HOME)/.chez-cross-tarm64le || { \ + echo "ERROR: cross-built Chez not found at $(JERBOA_HOME)/.chez-cross-tarm64le"; \ + echo "Build it with: cd $(JERBOA_HOME) && make chez-cross-tarm64le"; \ + exit 1; } + @command -v cargo >/dev/null 2>&1 || { \ + echo "ERROR: cargo not found on PATH. Install rustup from rustup.rs"; \ + exit 1; } + JERBOA_HOME=$(JERBOA_HOME) TARGET_ARCH=arm64 $(SCHEME) -q --libdirs "$(XC_LIBDIRS)" --script build-jcode-cross.ss # Friendly alias — same target, more explicit name. jcode-linux-amd64: linux-amd64 @@ -309,6 +324,7 @@ jcode-freebsd-amd64: freebsd-amd64 # `make build` from a FreeBSD host instead. freebsd: freebsd-amd64 + clean: find lib/jcode -name "*.sls" -delete 2>/dev/null; true find . -name "*.so" -delete --- a/build-jcode-cross.ss +++ b/build-jcode-cross.ss @@ -1,17 +1,19 @@ #!chezscheme -;;; build-jcode-cross.ss — Cross-compile jcode from macOS arm64 to Linux x86_64 musl +;;; build-jcode-cross.ss — Cross-compile jcode from macOS to Linux musl ;;; ;;; Usage: -;;; JERBOA_HOME=/Users/user/mine/jerboa scheme --libdirs <libs> \ -;;; --script build-jcode-cross.ss +;;; JERBOA_HOME=/Users/user/mine/jerboa TARGET_ARCH=amd64 scheme \ +;;; --libdirs <libs> --script build-jcode-cross.ss +;;; +;;; TARGET_ARCH selects the cross target: +;;; amd64 (default) — chez ta6le + x86_64-linux-musl-gcc → jcode-linux-amd64 +;;; arm64 — chez tarm64le + aarch64-linux-musl-gcc → jcode-linux-arm64 ;;; ;;; Cross-compile analogue of build-jcode-musl.ss that runs on a non-Linux host. ;;; Uses: -;;; - $JERBOA_HOME/.chez-cross-ta6le/ — cross-built Chez install -;;; - $JERBOA_HOME/build/chez/xc-ta6le/s/xpatch — host compiler → ta6le emit -;;; - x86_64-linux-musl-gcc — C compile + final static link -;;; -;;; Produces: jcode-linux-amd64 (static Linux x86_64 ELF, no shared library deps) +;;; - $JERBOA_HOME/.chez-cross-<machine>/ — cross-built Chez install +;;; - $JERBOA_HOME/build/chez/xc-<machine>/s/xpatch — host compiler emit mode +;;; - <toolchain>-linux-musl-gcc — C compile + final static link ;;; ;;; This is the "WPO as program" pattern: main-binary.ss + all imports are ;;; bundled into one .so via compile-whole-program, loaded at runtime via @@ -23,11 +25,26 @@ (define jerboa-home (or (getenv "JERBOA_HOME") "/Users/user/mine/jerboa")) -(define cross-prefix (format "~a/.chez-cross-ta6le" jerboa-home)) -(define xpatch (format "~a/build/chez/xc-ta6le/s/xpatch" jerboa-home)) -(define cross-cc (or (getenv "CROSS_CC") "x86_64-linux-musl-gcc")) +(define target-arch (or (getenv "TARGET_ARCH") "amd64")) + +;; Per-arch dispatch: (arch chez-machine c-toolchain rust-target output-name) +(define arch-table + '(("amd64" "ta6le" "x86_64-linux-musl-gcc" "x86_64-unknown-linux-musl" "jcode-linux-amd64") + ("arm64" "tarm64le" "aarch64-linux-musl-gcc" "aarch64-unknown-linux-musl" "jcode-linux-arm64"))) + +(define arch-row + (or (assoc target-arch arch-table) + (error 'build-jcode-cross + (format "unknown TARGET_ARCH (expected amd64|arm64): ~a" target-arch)))) + +(define chez-machine (list-ref arch-row 1)) +(define rust-target (list-ref arch-row 3)) + +(define cross-prefix (format "~a/.chez-cross-~a" jerboa-home chez-machine)) +(define xpatch (format "~a/build/chez/xc-~a/s/xpatch" jerboa-home chez-machine)) +(define cross-cc (or (getenv "CROSS_CC") (list-ref arch-row 2))) -(define output "jcode-linux-amd64") +(define output (list-ref arch-row 4)) (define entry-script "main-binary.ss") ;; jcode uses only this subset of jerboa-native-rs features: @@ -38,8 +55,8 @@ (define jerboa-native-a (or (getenv "JERBOA_NATIVE_A") - (format "~a/jerboa-native-rs/target/x86_64-unknown-linux-musl/release/libjerboa_native.a" - jerboa-home))) + (format "~a/jerboa-native-rs/target/~a/release/libjerboa_native.a" + jerboa-home rust-target))) (define cross-csv-dir (let ([lib (format "~a/lib" cross-prefix)]) @@ -52,7 +69,7 @@ entries)]) (when (null? csvs) (error 'build-jcode-cross "no csv* in cross lib" lib)) - (format "~a/~a/ta6le" lib (car csvs))))) + (format "~a/~a/~a" lib (car csvs) chez-machine)))) (define (require-file p) (unless (file-exists? p) @@ -79,8 +96,8 @@ ;; set, rebuild to match what jcode needs. Sentinel file records features. (define native-features-sentinel - (format "~a/jerboa-native-rs/target/x86_64-unknown-linux-musl/release/.built-with-~a" - jerboa-home + (format "~a/jerboa-native-rs/target/~a/release/.built-with-~a" + jerboa-home rust-target (let ([s (string-copy cargo-features)]) (let loop ([i 0]) (cond [(= i (string-length s)) s] @@ -139,8 +156,8 @@ (define (rebuild-native-lib!) (let* ([nrs-dir (format "~a/jerboa-native-rs" jerboa-home)] - [cargo-args (format "build --release --no-default-features --features ~a --target x86_64-unknown-linux-musl" - cargo-features)] + [cargo-args (format "build --release --no-default-features --features ~a --target ~a" + cargo-features rust-target)] [via-rustup (and rustup-bin-dir (format "cd '~a' && env PATH='~a':$PATH RUSTC='~a/rustc' '~a/cargo' ~a" @@ -150,11 +167,13 @@ (try-cargo-build via-path))]) (unless ok? (error 'build-jcode-cross - (string-append - "failed to build jerboa-native-rs for x86_64-unknown-linux-musl. " - "Required: `rustup target add x86_64-unknown-linux-musl`, plus the " - "FiloSottile/musl-cross toolchain on PATH so cargo finds " - "x86_64-linux-musl-gcc as the linker."))) + (format + (string-append + "failed to build jerboa-native-rs for ~a. " + "Required: `rustup target add ~a`, plus the " + "FiloSottile/musl-cross toolchain on PATH so cargo finds " + "~a as the linker.") + rust-target rust-target cross-cc))) (unless (file-exists? jerboa-native-a) (error 'build-jcode-cross "cargo succeeded but .a missing" jerboa-native-a)) (call-with-output-file native-features-sentinel @@ -218,7 +237,7 @@ ;; ── Stage 1: load xpatch (target=ta6le emit mode) ────────────────────────── (define orig-libdirs (library-directories)) -(printf "==> [1/6] loading xpatch (compiler -> ta6le emit mode)~n") +(printf "==> [1/6] loading xpatch (compiler -> ~a emit mode)~n" chez-machine) (load xpatch) (library-directories orig-libdirs) @@ -533,7 +552,7 @@ (restore-patched-files!) ;; Clean up intermediate compile-program outputs so the next dev cycle on -;; host scheme doesn't pick up ta6le-flavored .so files. +;; host scheme doesn't pick up cross-flavored .so files. (for-each (lambda (f) (when (file-exists? f) (delete-file f))) '("main-binary.so" "main-binary.wpo"))