multicall: cross-compile jerboa binary for linux-amd64 + freebsd-amd64
ober
bf3912bce176fab78f842c47d8ca395a747152b7
--- a/Makefile +++ b/Makefile @@ -45,6 +45,8 @@ help: @echo " binary-cross Build a jerboa-bin for a foreign target (same args as chez-cross)" @echo " jerboa Build the busybox-style multicall binary: dist/jerboa" @echo " + symlinks dist/{jmcp,jlsp,jerbuild} (one image, all four modes)" + @echo " jerboa-portable Build the multicall binary for host + linux-amd64 + freebsd-amd64" + @echo " (cross targets need: make chez-cross CHEZ_TARGET_MACHINE=ta6le|ta6fb ...)" @echo " native-cross Cross-build Rust native lib for a target" @echo " Args: CHEZ_TARGET_MACHINE=<mt> CROSS_CC=<cc> [CROSS_NATIVE_FEATURES=tls,...]" @echo " typecheck Typecheck Typed Jerboa sources" @@ -222,6 +224,56 @@ jerboa-smoke: jerboa rm -f /tmp/jms.ss; \ [ $$fail -eq 0 ] && echo "jerboa-smoke: PASS" || { echo "jerboa-smoke: FAIL" >&2; exit 1; } +# ── Cross-compiled multicall binary ────────────────────────────────────────── +# Builds dist/<os-arch>/{jerboa,jmcp,jlsp,jerbuild} for a foreign target, all +# four modes runnable on that target. The xpatch retargets the host Chez's +# codegen; the cross Chez supplies target boot files + libkernel.a. +# +# LIMITATION: on-target `jerbuild binary` does NOT work from a cross binary yet. +# Chez cross-compilation emits host-tagged .wpo (only .so get the target tag), +# and target-tagged .wpo can only be produced natively ON the target. The +# running multicall image has the stdlib internalized, so it cannot regenerate +# them in-process. Enabling self-build needs a bare-Chez subprocess mode (TODO). +# +# Generic form (builds the cross Chez on demand via chez-cross): +# make jerboa-cross CHEZ_TARGET_MACHINE=ta6le CROSS_CC=x86_64-linux-musl-gcc +.PHONY: jerboa-cross jerboa-linux-amd64 jerboa-freebsd-amd64 jerboa-portable +jerboa-cross: chez build mcp-check lsp-gen chez-cross + @test -n "$(CHEZ_TARGET_MACHINE)" \ + || { echo "ERROR: set CHEZ_TARGET_MACHINE=<machine-type>" >&2; exit 1; } + JERBOA_HOME=$(JERBOA_HOME) \ + TARGET_MACHINE=$(CHEZ_TARGET_MACHINE) \ + JERBOA_CROSS_PREFIX=$(CHEZ_CROSS_PREFIX) \ + JERBOA_XPATCH=$(CHEZ_XPATCH) \ + CC="$(CROSS_CC)" \ + $(SCHEME) --script support/build-jerboa-multicall.ss + +# Convenience targets: assume `make chez-cross` already produced the cross Chez. +jerboa-linux-amd64: chez build mcp-check lsp-gen + @command -v x86_64-linux-musl-gcc >/dev/null 2>&1 || { echo "ERROR: x86_64-linux-musl-gcc not on PATH" >&2; exit 1; } + @test -d "$(JERBOA_HOME)/.chez-cross-ta6le" || { echo "ERROR: .chez-cross-ta6le not found (make chez-cross CHEZ_TARGET_MACHINE=ta6le CROSS_CC=x86_64-linux-musl-gcc)" >&2; exit 1; } + @test -f "$(CHEZ_BUILD_DIR)/xc-ta6le/s/xpatch" || { echo "ERROR: ta6le xpatch not found" >&2; exit 1; } + @echo "=== Cross-building jerboa multicall: linux-amd64 (ta6le) ===" + @JERBOA_HOME=$(JERBOA_HOME) TARGET_MACHINE=ta6le \ + JERBOA_CROSS_PREFIX=$(JERBOA_HOME)/.chez-cross-ta6le \ + JERBOA_XPATCH=$(CHEZ_BUILD_DIR)/xc-ta6le/s/xpatch \ + CC=x86_64-linux-musl-gcc \ + $(SCHEME) --script support/build-jerboa-multicall.ss + +jerboa-freebsd-amd64: chez build mcp-check lsp-gen + @test -x "$(JERBOA_HOME)/support/cross-cc-freebsd-amd64" || { echo "ERROR: support/cross-cc-freebsd-amd64 not found/executable" >&2; exit 1; } + @test -d "$(JERBOA_HOME)/.chez-cross-ta6fb" || { echo "ERROR: .chez-cross-ta6fb not found (make chez-cross CHEZ_TARGET_MACHINE=ta6fb CROSS_CC=...)" >&2; exit 1; } + @test -f "$(CHEZ_BUILD_DIR)/xc-ta6fb/s/xpatch" || { echo "ERROR: ta6fb xpatch not found" >&2; exit 1; } + @echo "=== Cross-building jerboa multicall: freebsd-amd64 (ta6fb) ===" + @JERBOA_HOME=$(JERBOA_HOME) TARGET_MACHINE=ta6fb \ + JERBOA_CROSS_PREFIX=$(JERBOA_HOME)/.chez-cross-ta6fb \ + JERBOA_XPATCH=$(CHEZ_BUILD_DIR)/xc-ta6fb/s/xpatch \ + CC="$(JERBOA_HOME)/support/cross-cc-freebsd-amd64" \ + $(SCHEME) --script support/build-jerboa-multicall.ss + +# Host + the two cross targets. +jerboa-portable: jerboa jerboa-linux-amd64 jerboa-freebsd-amd64 + # Cross-compiled jerbuild. Drives support/build-jerbuild.sh with TARGET_* env, # producing ./jerbuild-<machine> alongside the host ./jerbuild. # --- a/support/build-jerboa-multicall.ss +++ b/support/build-jerboa-multicall.ss @@ -251,20 +251,61 @@ script (format "~a/~a" (current-directory) script))]) (path-parent (path-parent abs))))) -(define machine (symbol->string (machine-type))) -(define csv-dir (or (getenv "CHEZ_DIR") - (find-csv-dir (format "~a/.chez/lib" repo) machine))) -(unless csv-dir (error 'build-multicall "no Chez csv dir for" machine (format "~a/.chez/lib" repo))) +;; ── cross-compilation params (mirror support/build-jerbuild.sh) ─────────────── +;; TARGET_MACHINE set => cross build. JERBOA_CROSS_PREFIX is the install prefix +;; of the cross-built Chez (`.chez-cross-<mt>`, holding lib/csv*/<mt>/...) and +;; JERBOA_XPATCH is xc-<mt>/s/xpatch, loaded before compile so the host Chez +;; emits target FASL. All produced by `make chez-cross`. +(define target-machine (env "TARGET_MACHINE" #f)) +(define cross? (and target-machine #t)) +(define xpatch (and cross? (env "JERBOA_XPATCH" #f))) +(define cross-prefix (and cross? (env "JERBOA_CROSS_PREFIX" #f))) +(when cross? + (unless cross-prefix (error 'build-multicall "TARGET_MACHINE set but JERBOA_CROSS_PREFIX is not")) + (unless xpatch (error 'build-multicall "TARGET_MACHINE set but JERBOA_XPATCH is not")) + (unless (file-exists? xpatch) (error 'build-multicall "xpatch not found" xpatch))) + +(define machine (if cross? target-machine (symbol->string (machine-type)))) + +;; Map machine-type suffix -> target OS, and -> a friendly dist subdir label. +(define (machine->os m) + (cond [(string-suffix? m "osx") 'darwin] + [(string-suffix? m "fb") 'freebsd] + [(string-suffix? m "nt") 'windows] + [else 'linux])) +(define target-os (machine->os machine)) +(define (machine->label m) + (cond [(string=? m "ta6le") "linux-amd64"] + [(string=? m "tarm64le") "linux-arm64"] + [(string=? m "ta6fb") "freebsd-amd64"] + [(string=? m "tarm64fb") "freebsd-arm64"] + [(string=? m "ta6osx") "macos-amd64"] + [(string=? m "tarm64osx") "macos-arm64"] + [else m])) -(define out-dir (env "OUTPUT_DIR" (format "~a/dist" repo))) +(define csv-dir (or (getenv "CHEZ_DIR") + (find-csv-dir (format "~a/lib" (if cross? cross-prefix (format "~a/.chez" repo))) + machine))) +(unless csv-dir (error 'build-multicall "no Chez csv dir for" machine + (if cross? cross-prefix (format "~a/.chez/lib" repo)))) + +(define out-dir (env "OUTPUT_DIR" (if cross? + (format "~a/dist/~a" repo (machine->label machine)) + (format "~a/dist" repo)))) (define output (format "~a/jerboa" out-dir)) -(define build-dir (format "~a/build/jerboa-multicall" repo)) +(define build-dir (format "~a/build/jerboa-multicall~a" repo + (if cross? (format "-~a" machine) ""))) (define gen-dir (format "~a/gen" build-dir)) (define obj-dir (format "~a/obj" build-dir)) (define program-wp-so (format "~a/program.wp.so" build-dir)) +(define libdirs (list (cons gen-dir obj-dir) + (cons (format "~a/lib" repo) obj-dir) + (cons repo obj-dir))) (printf "=== jerboa multicall build ===~n") (printf " repo: ~a~n" repo) +(printf " mode: ~a~n" (if cross? (format "CROSS (~a -> ~a, ~a)" (machine-type) target-os machine) "native")) +(when cross? (printf " xpatch: ~a~n" xpatch)) (printf " machine: ~a~n" machine) (printf " chez: ~a~n" csv-dir) (printf " output: ~a~n" output) @@ -286,9 +327,15 @@ (write-unified-entry entry-ss) (printf "==> [2/6] WPO compile shared image~n") -(library-directories (list (cons gen-dir obj-dir) - (cons (format "~a/lib" repo) obj-dir) - (cons repo obj-dir))) +(library-directories libdirs) +;; Load the xpatch AFTER setting library-directories (it may mutate them) and +;; re-assert ours, so subsequent compile-* emit target FASL. Safe to do +;; in-process: this builder's image imports only (chezscheme); no Jerboa libs +;; are loaded as the host machine-type to collide with the retargeted codegen. +(when cross? + (printf " loading xpatch ~a~n" xpatch) + (load xpatch) + (library-directories libdirs)) (compile-imported-libraries #t) (generate-wpo-files #t) (compile-program entry-ss (format "~a/program.so" obj-dir)) @@ -324,10 +371,18 @@ (lambda (o) (fprintf o "static const char bundle_sha256[] = \"~a\";~n" bundle-sha)) 'replace) (printf "==> [5/6] compile + link -> ~a~n" output) +;; Cross Chez is configured --disable-curses --disable-x11 --disable-iconv, so +;; libkernel.a has no ncurses/iconv refs; native host Chez is built --as-is. (define os-libs - (cond [(string-suffix? machine "osx") "-lm -lpthread -lncurses -liconv"] - [(string-suffix? machine "fb") "-lm -lpthread -lncurses -L/usr/local/lib -liconv"] - [else "-lm -ldl -lpthread -lncurses"])) + (if cross? + (case target-os + [(linux) "-lm -ldl -lpthread -static"] + [(freebsd) "-lm -lpthread"] + [(darwin) "-lm -lpthread"] + [else "-lm -lpthread"]) + (cond [(string-suffix? machine "osx") "-lm -lpthread -lncurses -liconv"] + [(string-suffix? machine "fb") "-lm -lpthread -lncurses -L/usr/local/lib -liconv"] + [else "-lm -ldl -lpthread -lncurses"]))) (define extra-archives (apply string-append (map (lambda (a) (if (file-exists? (format "~a/~a" csv-dir a)) (format " ~a/~a" csv-dir a) ""))