updates
ober
46c3660450704df1bd0d380dea987d2299838224
--- a/data/cookbooks.sexp +++ b/data/cookbooks.sexp @@ -6184,4 +6184,15 @@ "make-boot-file" "wpo" "runtime-import") ("title" . - "Bundle lazy optional libraries in static cross builds"))) + "Bundle lazy optional libraries in static cross builds")) + (("code" + . + "# Avoid gen-embed prompting for an encrypted ~/.embed when verifying builds.\n# Run without a TTY and point JSH_EMBED at a path that does not exist.\nJSH_EMBED=/tmp/jsh-empty-embed make jsh-macos-minimal\n\n# Smoke-test the resulting binary.\n./jsh-macos-minimal -c 'echo ok'") ("id" . "jsh-minimal-build-with-empty-embed") ("imports") + ("notes" + . + "If ~/.embed exists and the build has a TTY, gen-embed prompts for the embed encryption passphrase. For CI or verification runs where embed contents are not under test, use a non-interactive command and override JSH_EMBED to an empty/nonexistent path so Makefile generates empty embed-data.sls. The build may still warn about Cargo global cache cleanup permissions; that warning is non-fatal if compilation continues.") + ("tags" "jsh" "build" "embed" "minimal" "macos" + "noninteractive") + ("title" + . + "Build jsh minimal without embed passphrase prompt"))) --- a/jerbuild.ss +++ b/jerbuild.ss @@ -7,7 +7,7 @@ ;;; on stock Chez Scheme. ;;; ;;; Usage: -;;; scheme --libdirs lib --script jerbuild.ss <src-dir> <lib-dir> [--force] [--verbose] +;;; jerboa jerbuild transpile <src-dir> <lib-dir> [--force] [--verbose] (import (chezscheme) (jerboa build)) ;; compute-file-hash, module-changed? @@ -967,17 +967,18 @@ [(or (null? imports) (entry-imports-chez? imports)) (maybe-copy-shebangless-entry entry obj-dir)] [else - (let* ([chez-set (environment-symbols (environment '(chezscheme)))] - [conflicts (delete-duplicates - (append - (apply append - (map (lambda (s) (spec-conflict-candidates s chez-set)) - imports)) - (collect-local-defs body)) - eq?)] - [wrapped (format "~a/jerboa-entry.ss" obj-dir)]) - (printf " Jerboa entry: injecting (chezscheme) base (~a name(s) excepted)\n" - (length conflicts)) + (let* ([chez-set (environment-symbols (environment '(chezscheme)))] + [conflicts (delete-duplicates + (append + (apply append + (map (lambda (s) (spec-conflict-candidates s chez-set)) + imports)) + (filter (lambda (s) (memq s chez-set)) + (collect-local-defs body))) + eq?)] + [wrapped (format "~a/jerboa-entry.ss" obj-dir)]) + (printf " Jerboa entry: injecting base language (~a name(s) excepted)\n" + (length conflicts)) (call-with-output-file wrapped (lambda (port) (parameterize ([print-extended-identifiers #t]) @@ -2181,16 +2182,15 @@ int main(int argc, const char *argv[]) { (current-directory) rest))))))))))))))) -;; Find a usable Chez scheme binary to spawn subprocess WPO compiles. -;; Tries $SCHEME, then ~/mine/jerboa/.chez/bin/scheme, then `command -v scheme`. -(define (find-scheme-binary) - (or (let ([e (getenv "SCHEME")]) +;; Find a usable Jerboa command to spawn subprocess WPO compiles. +;; Tries $JERBOA, $JERBOA_CMD, then `command -v jerboa`. +(define (find-jerboa-command) + (or (let ([e (getenv "JERBOA")]) (and e (file-exists? e) e)) - (let* ([home (or (getenv "HOME") "")] - [p (string-append home "/mine/jerboa/.chez/bin/scheme")]) - (and (file-exists? p) p)) - (let* ([tmp (format "/tmp/jerbuild-scheme-which-~a" (get-process-id))] - [rc (system (format "command -v scheme > ~a 2>/dev/null" tmp))]) + (let ([e (getenv "JERBOA_CMD")]) + (and e (file-exists? e) e)) + (let* ([tmp (format "/tmp/jerbuild-jerboa-which-~a" (get-process-id))] + [rc (system (format "command -v jerboa > ~a 2>/dev/null" tmp))]) (let ([path (and (zero? rc) (file-exists? tmp) (call-with-input-file tmp get-line))]) (when (file-exists? tmp) (delete-file tmp)) @@ -2199,7 +2199,7 @@ int main(int argc, const char *argv[]) { [(file-exists? path) path] [else #f]))) (error 'jerbuild - "find-scheme-binary: no scheme found (set SCHEME env var)"))) + "find-jerboa-command: no jerboa found (set JERBOA env var)"))) ;; Path-leaf: basename of a path (no trailing slash). Used to make per-libdir ;; cache dirs unique in obj-dir. @@ -2213,17 +2213,16 @@ int main(int argc, const char *argv[]) { ;; Command that runs the WPO helper script in a fresh process with an empty ;; library table. Inside the multicall binary (JERBOA_SELF_EXE set) we -;; re-invoke ourselves in bare-Chez mode (`<self> scheme <helper>`), since no -;; external `scheme` exists on a target host; otherwise use a stock external -;; scheme (`scheme --quiet --script <helper>`). +;; re-invoke ourselves as Jerboa with the helper script path; otherwise locate +;; the installed Jerboa command for source-tree development builds. (define (wpo-subprocess-command helper) (let ([self (getenv "JERBOA_SELF_EXE")]) (if (and self (file-exists? self)) - (format "~a scheme ~a" (shell-quote self) (shell-quote helper)) - (format "~a --quiet --script ~a" - (shell-quote (find-scheme-binary)) (shell-quote helper))))) + (format "~a runtime ~a" (shell-quote self) (shell-quote helper)) + (format "~a runtime ~a" + (shell-quote (find-jerboa-command)) (shell-quote helper))))) -;; Run compile-program + compile-whole-program in a fresh Chez subprocess so a +;; Run compile-program + compile-whole-program in a fresh runtime subprocess so a ;; clean library table is used. Needed (a) for cross builds, where xpatch ;; retargets codegen and recompiled target libraries must not collide with ;; jerbuild's host image; and (b) inside the multicall binary, whose running @@ -2414,15 +2413,15 @@ int main(int argc, const char *argv[]) { ;; loading xpatch, Chez's codegen switches to the target machine-type. ;; Recompiling those libs to the new machine-type would trigger ;; "attempting to re-install compile-time part of library" because they - ;; are already loaded. Run the WPO step in a fresh Chez subprocess so it + ;; are already loaded. Run the WPO step in a fresh runtime subprocess so it ;; sees a clean library table. ;; Run WPO in a fresh subprocess when (a) cross (xpatch retargets), or ;; (b) we are the multicall binary (JERBOA_SELF_EXE set): our running ;; image has the stdlib internalized, so an in-process compile-whole- ;; program would need their .wpo on disk, and a cross bundle's .wpo are ;; the build host's machine-type. A fresh bare-Chez process recompiles - ;; bundled sources to native .wpo. Plain `scheme --script jerbuild.ss` - ;; keeps the in-process path (its bundle .wpo already match the host). + ;; bundled sources to native .wpo. Source-tree direct runtime execution + ;; keeps the in-process path when its bundle .wpo already match the host. (cond [(or xpatch (getenv "JERBOA_SELF_EXE")) (printf "==> [1/5] WPO compile in isolated subprocess~a\n" --- a/support/build-boot.ss +++ b/support/build-boot.ss @@ -2,7 +2,7 @@ ;;; build-boot.ss — Compile a Jerboa script with Whole-Program Optimization ;;; ;;; Usage: -;;; scheme --libdirs <libdirs> --script build-boot.ss <entry.ss> <output.so> [<obj-dir>] +;;; jerboa jerbuild exec --libdirs <libdirs> build-boot.ss <entry.ss> <output.so> [<obj-dir>] ;;; ;;; <obj-dir> Optional writable directory for compiled library and entry ;;; .so/.wpo output. @@ -20,7 +20,10 @@ (and (>= slen xlen) (string=? (substring str (- slen xlen) slen) suffix)))) -(let ([args (cdr (command-line))]) ;; strip argv[0] (build-boot.ss path) +(let* ([script-args (command-line-arguments)] + [args (if (null? script-args) + (cdr (command-line)) + script-args)]) (when (< (length args) 2) (display "Usage: build-boot.ss <entry.ss> <output.so> [<obj-dir>]\n" (current-error-port)) --- a/support/build-jerboa-multicall.ss +++ b/support/build-jerboa-multicall.ss @@ -13,7 +13,7 @@ ;;; a *-main procedure, generate a dispatcher program importing all three, then ;;; WPO-compile one shared image and link support/multicall-main.c around it. ;;; -;;; Usage: scheme --script support/build-jerboa-multicall.ss +;;; Usage: jerboa support/build-jerboa-multicall.ss ;;; Output: dist/jerboa + relative symlinks dist/{jmcp,jlsp,jerbuild,jpkg} (import (chezscheme)) @@ -52,6 +52,18 @@ (let ([rc (system cmd)]) (unless (zero? rc) (error 'build-multicall "command failed" rc cmd)))) +(define entry-build-id + (string->symbol (format "build-~a" (get-process-id)))) + +(define (entry-library-name name) + `(jerboa multicall ,entry-build-id entry ,name)) + +(define (entry-library-path gen-dir name) + (format "~a/jerboa/multicall/~a/entry/~a.sls" + gen-dir + (symbol->string entry-build-id) + name)) + (define (directory-list* p) (guard (e [else '()]) (if (file-directory? p) (directory-list p) '()))) (define (require-file p) (unless (file-exists? p) (error 'build-multicall "missing file" p))) @@ -145,7 +157,7 @@ (cddr trailing)) (define (lib-form name export-name import-sets body main-def) - `(library (jerboa entry ,name) + `(library ,(entry-library-name name) (export ,export-name) (import ,@import-sets) ,@body @@ -212,15 +224,15 @@ (call-with-output-file path (lambda (out) (display "#!chezscheme\n" out) - (write '(import (except (chezscheme) + (write `(import (except (chezscheme) make-hash-table hash-table? sort sort! printf fprintf path-extension path-absolute? with-input-from-string with-output-to-string iota 1+ 1- partition make-date make-time meta atom?) (jerboa prelude) - (jerboa entry mcp) - (jerboa entry lsp) - (jerboa entry jerbuild) + ,(entry-library-name 'mcp) + ,(entry-library-name 'lsp) + ,(entry-library-name 'jerbuild) (only (std pkg cli) jpkg-main)) out) (newline out) @@ -232,7 +244,7 @@ [(string=? mode "jerbuild") (jerbuild-main args)] [(string=? mode "jpkg") (exit (jpkg-main args))] [(null? args) - (displayln "Jerboa Scheme — type (exit) to quit") + (displayln "Jerboa — type (exit) to quit") (let loop () (display "jerboa> ") (flush-output-port (current-output-port)) @@ -246,14 +258,15 @@ (loop)])))] [(or (string=? (car args) "--version") (string=? (car args) "-v")) (displayln ,(string-append "jerboa " project-version " (multicall: jerboa/jmcp/jlsp/jerbuild/jpkg)")) - (displayln (string-append "Bundled " (scheme-version) + (displayln (string-append "Bundled Chez runtime " + (scheme-version) " (Apache 2.0, (c) Cisco Systems, Inc.)")) - (displayln "See LICENSE-CHEZ for Chez Scheme's NOTICE and license.")] + (displayln "See LICENSE-CHEZ for the runtime NOTICE and license.")] [(or (string=? (car args) "--help") (string=? (car args) "-h")) (for-each displayln (list "Usage: jerboa [<script.ss> | <mode> ...] [--version]" " (no args) start the Jerboa REPL" - " <script.ss> load and run a Scheme script" + " <script.ss> load and run a Jerboa script" " jmcp|mcp ... run the MCP server" " jlsp|lsp ... run the LSP server" " jerbuild ... transpile/build a Jerboa project" @@ -342,14 +355,26 @@ (shell-quote gen-dir) (shell-quote obj-dir) (shell-quote out-dir))) (printf "==> [1/6] generate entry libraries + dispatcher~n") -(write-library (transform-jerbuild repo) (format "~a/jerboa/entry/jerbuild.sls" gen-dir)) -(write-library (transform-lsp repo) (format "~a/jerboa/entry/lsp.sls" gen-dir)) -(write-library (transform-mcp repo) (format "~a/jerboa/entry/mcp.sls" gen-dir)) +(write-library (transform-jerbuild repo) (entry-library-path gen-dir 'jerbuild)) +(write-library (transform-lsp repo) (entry-library-path gen-dir 'lsp)) +(write-library (transform-mcp repo) (entry-library-path gen-dir 'mcp)) (define entry-ss (format "~a/jerboa-multicall-entry.ss" gen-dir)) (write-unified-entry entry-ss) (printf "==> [2/6] WPO compile shared image~n") (library-directories libdirs) +;; When this script is launched through the installed multicall Jerboa, some +;; core libraries are already resident in the image and will not be recompiled +;; by compile-imported-libraries. Seed the native object directory from the +;; running image's bundle cache when available so compile-whole-program can +;; still see matching compilation instances. +(unless cross? + (let* ([bundle (getenv "JERBUILD_BUNDLE_DIR")] + [seed-lib (if (and bundle (> (string-length bundle) 0)) + (format "~a/lib" bundle) + (format "~a/lib" repo))]) + (run (format "cd ~a && find . \\( -name '*.so' -o -name '*.wpo' \\) -type f | tar -cf - -T - | (cd ~a && tar -xf -)" + (shell-quote seed-lib) (shell-quote obj-dir))))) ;; 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 --- a/support/build-static-script.sh +++ b/support/build-static-script.sh @@ -25,7 +25,7 @@ JERBOA_HOME="${JERBOA_HOME:-/build/mine/jerboa}" MUSL_CHEZ="${JERBOA_MUSL_CHEZ_PREFIX:-/build/chez-musl}" NATIVE_A="${JERBOA_NATIVE_STATIC_ARCHIVE:-${JERBOA_HOME}/jerboa-native-rs/target/x86_64-unknown-linux-musl/release/libjerboa_native.a}" LIBDIRS="${BINARY_LIBDIRS:-${LIBDIRS:-${JERBOA_HOME}/lib}}" -SCHEME="${SCHEME:-scheme}" +JERBOA_CMD="${JERBOA_CMD:-jerboa}" TARGET_MACHINE="${TARGET_MACHINE:-}" MUSL_CC="${MUSL_CC:-musl-gcc}" MUSL_STRIP="${MUSL_STRIP:-${MUSL_CC%-gcc}-strip}" @@ -38,10 +38,12 @@ echo "" # ── Locate musl Chez libkernel.a ───────────────────────────────────────────── MACHINE_TYPE="${TARGET_MACHINE}" if [ -z "${MACHINE_TYPE}" ]; then -MACHINE_TYPE=$(${SCHEME} -q <<'EOF' -(display (machine-type)) (exit) -EOF -) + for d in "${MUSL_CHEZ}/lib/csv"*/*; do + if [ -f "${d}/libkernel.a" ]; then + MACHINE_TYPE="$(basename "${d}")" + break + fi + done fi CSV_DIR="" @@ -79,8 +81,8 @@ echo " Library object cache: ${OBJ_DIR}" LD_LIBRARY_PATH="${JERBOA_HOME}/jerboa-native-rs/target/release:${LD_LIBRARY_PATH:-}" \ JERBOA_XPATCH="${JERBOA_XPATCH:-}" \ - ${SCHEME} --libdirs "${LIBDIRS}" \ - --script "${JERBOA_HOME}/support/build-boot.ss" "${SCRIPT}" "${WPO_SO}" "${OBJ_DIR}" + ${JERBOA_CMD} jerbuild exec --libdirs "${LIBDIRS}" \ + "${JERBOA_HOME}/support/build-boot.ss" "${SCRIPT}" "${WPO_SO}" "${OBJ_DIR}" echo "" --- a/support/multicall-main.c +++ b/support/multicall-main.c @@ -6,10 +6,10 @@ * jlsp -> LSP server (lsp/main-binary.ss) * jerbuild -> .ss -> .sls transpiler / project builder (jerbuild.ss) * - * The mode is passed to the embedded Scheme program via the + * The mode is passed to the embedded Jerboa program via the * JERBOA_MULTICALL_NAME environment variable, because Chez's Sscheme_program * overwrites command-line[0] with the program path (so argv[0] is otherwise - * lost to Scheme). + * lost to the runtime). * * The generated headers below (boot files, the WPO program image, and the * jerbuild lib bundle) are produced by support/build-jerboa-multicall.ss. @@ -225,7 +225,7 @@ static const char *basename_of(const char *p) { } /* Absolute path to this executable, so `jerbuild binary` can re-invoke itself - * in bare-Chez mode for the WPO subprocess. Exported as JERBOA_SELF_EXE. */ + * in clean runtime mode for the WPO subprocess. Exported as JERBOA_SELF_EXE. */ static int self_exe_path(char *buf, size_t n) { #if defined(__APPLE__) uint32_t sz = (uint32_t)n; @@ -251,7 +251,7 @@ static const char JERBUILD_USAGE[] = " jerbuild <src> <lib> # transpile .ss -> .sls\n" " jerbuild transpile <src> <lib> [--force]\n" " jerbuild compile --libdirs <p> [--wpo] FILE...\n" - " jerbuild exec --libdirs <p> FILE [args...] # load+run a Scheme script\n" + " jerbuild exec --libdirs <p> FILE [args...] # load+run a Jerboa script\n" " jerbuild binary [--libdirs <p>] [--cc CC] <entry.ss> <output>\n" " jerbuild build [--cc CC] [--config PATH] # read .jerbuild, build\n" " jerbuild --jerboa-home # extract+print stdlib path\n" @@ -275,12 +275,12 @@ int main(int argc, const char *argv[]) { if (!strcmp(mode, "lsp")) mode = "jlsp"; if (!strcmp(mode, "pkg")) mode = "jpkg"; - /* Bare-Chez mode: `jerboa scheme [script [args...]]` boots petite+scheme - * WITHOUT the embedded program image, behaving as a stock `scheme`. Used by + /* Clean runtime mode: `jerboa runtime [script [args...]]` boots the + * language runtime WITHOUT the embedded program image. Used by * `jerbuild binary` on a target host to run the WPO compile in a fresh * process with an empty library table, so bundled stdlib sources recompile * to native .wpo (cross-built .wpo carry the build host's machine-type). */ - if (!strcmp(name, "jerboa") && argc > 1 && !strcmp(argv[1], "scheme")) { + if (!strcmp(name, "jerboa") && argc > 1 && !strcmp(argv[1], "runtime")) { Sscheme_init(NULL); Sregister_boot_file_bytes("petite", (void *)petite_boot_data, petite_boot_size); Sregister_boot_file_bytes("scheme", (void *)scheme_boot_data, scheme_boot_size); @@ -291,7 +291,7 @@ int main(int argc, const char *argv[]) { return st; } - /* jerbuild mode: C-side fast paths that avoid booting Chez, plus bundle + /* jerbuild mode: C-side fast paths that avoid booting the runtime, plus bundle * pre-extraction for the subcommands that link binaries. a1 is the first * real jerbuild argument (the token after the mode selector). */ if (!strcmp(mode, "jerbuild")) {