Add jerbuild target builds
ober
5b18cdd7b9d9d6b04ce581426e2d9db0ce1d8c63
new file mode 100644 --- /dev/null +++ b/.jerbuild @@ -0,0 +1,41 @@ +;; Native host build config for jerboa-emacs TUI. +;; +;; Build with: +;; JERBUILD=/path/to/jerbuild jerbuild build +;; +;; The pre-build hook uses the standalone jerbuild bundle to transpile this +;; repo and vendored dependencies. It does not require an installed full Jerboa +;; runtime or a sibling Jerboa source checkout. + +(entry "main.ss") +(output "jemacs") + +(requires "jerbuild" "cc" "pkg-config" "libpcre2" "libvterm") + +(libdirs "lib" + "vendor/jerboa-shell/_jerbuild-stage" + "vendor/jerboa-shell/src" + "vendor/jerboa-shell/vendor/jerboa-coreutils/lib" + "vendor/jerboa-shell/vendor/jerboa-awk/lib" + "vendor/jerboa-shell/vendor/jerboa-sed/lib" + "vendor/jerboa-shell/vendor/jerboa-ssh/src" + "vendor/jerboa-shell/vendor/jerboa-sqlite/src" + "vendor/jerboa-shell/vendor/jerboa-crypto/src" + "vendor/jerboa-shell/vendor/jerboa-fuse/lib" + "vendor/jerboa-pcre2/lib" + "vendor/jerboa-scintilla/lib") + +(main-c "support/jemacs-jerbuild-main.c") + +(ffi-symbols "support/jemacs-jerbuild-symbols.list") + +(extra-sources "support/repl_shim.c" + "vendor/jerboa-shell/ffi-shim.c" + "vendor/jerboa-shell/vendor/jerboa-coreutils/support/libcoreutils.c" + "support/jsh_coreutils_stubs.c" + "support/jsh_embed_crypto_stubs.c" + "support/jerboa_native_stubs.c" + "support/jemacs_ssh_agent_stubs.c" + "support/jemacs_tls_stubs.c") + +(pre-build "support/stage-for-jerbuild.sh") new file mode 100644 --- /dev/null +++ b/.jerbuild.freebsd-amd64 @@ -0,0 +1,47 @@ +;; Native FreeBSD amd64 build config for jerboa-emacs TUI. +;; +;; Build on a FreeBSD amd64 host with: +;; JERBUILD=/path/to/jerbuild jerbuild build --config .jerbuild.freebsd-amd64 +;; +;; This uses installed/project-local jerbuild, cc, pkg-config, and vendored +;; project dependencies. It has no dependency on an installed full Jerboa +;; runtime or sibling Jerboa source checkout. + +(entry "main.ss") +(output "jemacs-freebsd-amd64") + +(cc "cc") + +(requires "jerbuild" "cc" "pkg-config" "libpcre2" "libvterm") + +;; FreeBSD has dlopen in libc. -lutil covers forkpty/openpty, termcap backs +;; Chez's expeditor, and GNU libiconv is commonly under /usr/local/lib. +(os-libs "-lm -lpthread -lutil -ltermcap -L/usr/local/lib -liconv") + +(libdirs "lib" + "vendor/jerboa-shell/_jerbuild-stage" + "vendor/jerboa-shell/src" + "vendor/jerboa-shell/vendor/jerboa-coreutils/lib" + "vendor/jerboa-shell/vendor/jerboa-awk/lib" + "vendor/jerboa-shell/vendor/jerboa-sed/lib" + "vendor/jerboa-shell/vendor/jerboa-ssh/src" + "vendor/jerboa-shell/vendor/jerboa-sqlite/src" + "vendor/jerboa-shell/vendor/jerboa-crypto/src" + "vendor/jerboa-shell/vendor/jerboa-fuse/lib" + "vendor/jerboa-pcre2/lib" + "vendor/jerboa-scintilla/lib") + +(main-c "support/jemacs-jerbuild-main.c") + +(ffi-symbols "support/jemacs-jerbuild-symbols.list") + +(extra-sources "support/repl_shim.c" + "vendor/jerboa-shell/ffi-shim.c" + "vendor/jerboa-shell/vendor/jerboa-coreutils/support/libcoreutils.c" + "support/jsh_coreutils_stubs.c" + "support/jsh_embed_crypto_stubs.c" + "support/jerboa_native_stubs.c" + "support/jemacs_ssh_agent_stubs.c" + "support/jemacs_tls_stubs.c") + +(pre-build "support/stage-for-jerbuild.sh") new file mode 100644 --- /dev/null +++ b/.jerbuild.linux-amd64 @@ -0,0 +1,45 @@ +;; Native Linux amd64 build config for jerboa-emacs TUI. +;; +;; Build on a Linux amd64 host with: +;; JERBUILD=/path/to/jerbuild jerbuild build --config .jerbuild.linux-amd64 +;; +;; This uses installed/project-local jerbuild, cc, pkg-config, and vendored +;; project dependencies. It has no dependency on an installed full Jerboa +;; runtime or sibling Jerboa source checkout. + +(entry "main.ss") +(output "jemacs-linux-amd64") + +(cc "cc") + +(requires "jerbuild" "cc" "pkg-config" "libpcre2" "libvterm") + +(os-libs "-lm -ldl -lpthread -lutil -lncurses") + +(libdirs "lib" + "vendor/jerboa-shell/_jerbuild-stage" + "vendor/jerboa-shell/src" + "vendor/jerboa-shell/vendor/jerboa-coreutils/lib" + "vendor/jerboa-shell/vendor/jerboa-awk/lib" + "vendor/jerboa-shell/vendor/jerboa-sed/lib" + "vendor/jerboa-shell/vendor/jerboa-ssh/src" + "vendor/jerboa-shell/vendor/jerboa-sqlite/src" + "vendor/jerboa-shell/vendor/jerboa-crypto/src" + "vendor/jerboa-shell/vendor/jerboa-fuse/lib" + "vendor/jerboa-pcre2/lib" + "vendor/jerboa-scintilla/lib") + +(main-c "support/jemacs-jerbuild-main.c") + +(ffi-symbols "support/jemacs-jerbuild-symbols.list") + +(extra-sources "support/repl_shim.c" + "vendor/jerboa-shell/ffi-shim.c" + "vendor/jerboa-shell/vendor/jerboa-coreutils/support/libcoreutils.c" + "support/jsh_coreutils_stubs.c" + "support/jsh_embed_crypto_stubs.c" + "support/jerboa_native_stubs.c" + "support/jemacs_ssh_agent_stubs.c" + "support/jemacs_tls_stubs.c") + +(pre-build "support/stage-for-jerbuild.sh") new file mode 100644 --- /dev/null +++ b/.jerbuild.linux-arm64 @@ -0,0 +1,45 @@ +;; Native Linux arm64/aarch64 build config for jerboa-emacs TUI. +;; +;; Build on a Linux arm64 host with: +;; JERBUILD=/path/to/jerbuild jerbuild build --config .jerbuild.linux-arm64 +;; +;; This uses installed/project-local jerbuild, cc, pkg-config, and vendored +;; project dependencies. It has no dependency on an installed full Jerboa +;; runtime or sibling Jerboa source checkout. + +(entry "main.ss") +(output "jemacs-linux-arm64") + +(cc "cc") + +(requires "jerbuild" "cc" "pkg-config" "libpcre2" "libvterm") + +(os-libs "-lm -ldl -lpthread -lutil -lncurses") + +(libdirs "lib" + "vendor/jerboa-shell/_jerbuild-stage" + "vendor/jerboa-shell/src" + "vendor/jerboa-shell/vendor/jerboa-coreutils/lib" + "vendor/jerboa-shell/vendor/jerboa-awk/lib" + "vendor/jerboa-shell/vendor/jerboa-sed/lib" + "vendor/jerboa-shell/vendor/jerboa-ssh/src" + "vendor/jerboa-shell/vendor/jerboa-sqlite/src" + "vendor/jerboa-shell/vendor/jerboa-crypto/src" + "vendor/jerboa-shell/vendor/jerboa-fuse/lib" + "vendor/jerboa-pcre2/lib" + "vendor/jerboa-scintilla/lib") + +(main-c "support/jemacs-jerbuild-main.c") + +(ffi-symbols "support/jemacs-jerbuild-symbols.list") + +(extra-sources "support/repl_shim.c" + "vendor/jerboa-shell/ffi-shim.c" + "vendor/jerboa-shell/vendor/jerboa-coreutils/support/libcoreutils.c" + "support/jsh_coreutils_stubs.c" + "support/jsh_embed_crypto_stubs.c" + "support/jerboa_native_stubs.c" + "support/jemacs_ssh_agent_stubs.c" + "support/jemacs_tls_stubs.c") + +(pre-build "support/stage-for-jerbuild.sh") --- a/Makefile +++ b/Makefile @@ -1,5 +1,24 @@ VENDOR ?= $(CURDIR)/vendor +# Standalone jerbuild toolchain. This mirrors the bootstrap path used by +# jerboa-code/jerboa-shell: prefer project-local tools, then sibling Jerboa, +# then PATH, and otherwise fetch a release into .jerboa/bin. +JERBOA_VERSION ?= v0.2.0 +JERBOA_TOOL_DIR ?= $(CURDIR)/.jerboa/bin +JERBUILD_TOOL ?= $(shell if [ -x ./jerbuild ] && [ -x ./jerboa ]; then echo ./jerbuild; \ + elif [ -x "$(JERBOA_TOOL_DIR)/jerbuild" ] && [ -x "$(JERBOA_TOOL_DIR)/jerboa" ]; then echo "$(JERBOA_TOOL_DIR)/jerbuild"; \ + elif [ -x ../jerboa/dist/jerbuild ] && [ -x ../jerboa/dist/jerboa ]; then echo ../jerboa/dist/jerbuild; \ + elif [ -x ../jerboa/jerbuild ]; then echo ../jerboa/jerbuild; \ + elif command -v jerbuild >/dev/null 2>&1 && command -v jerboa >/dev/null 2>&1; then command -v jerbuild; \ + else echo "$(JERBOA_TOOL_DIR)/jerbuild"; fi) +JH = $(shell "$(JERBUILD_TOOL)" --jerboa-home 2>/dev/null) +SSH ?= ssh +SCP ?= scp +LINUX_BUILD_HOST ?= linux.cons.io +LINUX_BUILD_ROOT ?= ~/mine/jerboa-emacs +LINUX_ARM64_BUILD_HOST ?= +LINUX_ARM64_BUILD_ROOT ?= $(LINUX_BUILD_ROOT) + JERBOA_REPO ?= https://git.sr.ht/~lisp/jerboa JERBOA_SHELL_REPO ?= https://git.sr.ht/~lisp/jerboa-shell JERBOA_PCRE2_REPO ?= https://git.sr.ht/~lisp/jerboa-pcre2 @@ -122,7 +141,7 @@ SCHEME_CHEZ_DIR = $(shell if [ -n "$(SCHEME_MT)" ]; then ls -d "$(SCHEME_PREFIX) CHEZ_DIR ?= $(SCHEME_CHEZ_DIR) export CHEZ_DIR -.PHONY: all vendor-deps vendor-update check-pcre2-system-deps check-vterm-system-deps deps ensure-vendor-jerboa-tools scintilla-vendor-deps scintilla-vendor-clean build rebuild run test-tier0 test-tier2 test-tier3 test-tier4 test-tier5 test-org test-extra test clean clean-generated \ +.PHONY: all vendor-deps vendor-update check-pcre2-system-deps check-vterm-system-deps deps ensure-vendor-jerboa-tools ensure-jerboa-tools build-jerbuild jemacs-jerbuild jerbuild-check scintilla-vendor-deps scintilla-vendor-clean build rebuild run test-tier0 test-tier2 test-tier3 test-tier4 test-tier5 test-org test-extra test clean clean-generated \ test-org-duration test-org-element test-org-fold test-org-footnote \ test-org-lint test-org-num test-org-property test-org-src test-org-tempo \ test-vtscreen test-debug-repl test-qt test-qt-e2e build-qt binary-qt \ @@ -130,6 +149,8 @@ export CHEZ_DIR podman-deps ensure-podman-deps static-qt static-tui clean-podman check-podman check-root \ linux-static-qt-podman linux-static-tui-podman \ build-jemacs-qt-static build-jemacs-tui-static binary macos \ + linux linux-amd64 linux-arm64 jemacs-linux-amd64 jemacs-linux-arm64 freebsd freebsd-amd64 jemacs-freebsd-amd64 \ + jemacs-linux-amd64-local jemacs-linux-arm64-local jemacs-linux-amd64-remote jemacs-linux-arm64-remote \ linux-tui linux-tui-local \ linux-qt linux-qt-local \ stress-run stress-run-static stress-test stress-burn stress-burn-static \ @@ -143,14 +164,20 @@ all: @echo "Available targets:" @echo " vendor-deps Clone required dependencies into vendor/" @echo " ensure-vendor-jerboa-tools Build vendor/jerboa/dist/{jerboa,jerbuild}" + @echo " ensure-jerboa-tools Ensure standalone project-local jerboa/jerbuild are available" @echo " scintilla-vendor-deps Fetch/build Scintilla, Lexilla, and termbox archives" @echo " build Translate src/*.ss → lib/*.sls (incremental)" + @echo " build-jerbuild Translate src/*.ss → lib/*.sls using standalone jerbuild" @echo " rebuild Force full retranslation" @echo " run Build and run TUI editor" @echo " run-qt Build and run Qt editor" @echo " binary Build TUI binary (./jemacs) — embeds Scheme, links system libs" + @echo " jemacs-jerbuild Build host TUI launcher via 'jerbuild build' (.jerbuild)" @echo " static-tui Build fully static TUI binary via Podman (./jemacs)" @echo " static-qt Build static jemacs-qt binary via Podman" + @echo " linux-amd64 Build Linux amd64 TUI artifact via jerbuild (local Linux or SSH)" + @echo " linux-arm64 Build Linux arm64 TUI artifact via jerbuild on a Linux arm64 host" + @echo " freebsd-amd64 Build FreeBSD amd64 TUI artifact via jerbuild on FreeBSD" @echo " macos Build native jemacs-qt binary for macOS" @echo " test Full test suite (all tiers + org)" @echo " test-functional 250 dispatch-chain integration tests" @@ -289,6 +316,41 @@ ensure-vendor-jerboa-tools: vendor-deps $(MAKE) -C $(JERBOA) jerboa; \ fi +ensure-jerboa-tools: + @set -e; \ + if [ -x "$(JERBUILD_TOOL)" ] && "$(JERBUILD_TOOL)" --jerboa-home >/dev/null 2>&1; then \ + echo "=== Using Jerboa toolchain: $(JERBUILD_TOOL) ==="; \ + elif [ -x ./jerbuild ] && [ -x ./jerboa ] && ./jerbuild --jerboa-home >/dev/null 2>&1; then \ + echo "=== Using project-local ./jerbuild ==="; \ + elif [ -x "$(JERBOA_TOOL_DIR)/jerbuild" ] && [ -x "$(JERBOA_TOOL_DIR)/jerboa" ] && "$(JERBOA_TOOL_DIR)/jerbuild" --jerboa-home >/dev/null 2>&1; then \ + echo "=== Using downloaded Jerboa toolchain: $(JERBOA_TOOL_DIR) ==="; \ + elif [ -x ../jerboa/dist/jerbuild ] && [ -x ../jerboa/dist/jerboa ] && ../jerboa/dist/jerbuild --jerboa-home >/dev/null 2>&1; then \ + echo "=== Using sibling Jerboa build: ../jerboa/dist/jerbuild ==="; \ + elif [ -x ../jerboa/jerbuild ] && ../jerboa/jerbuild --jerboa-home >/dev/null 2>&1; then \ + echo "=== Using sibling Jerboa build: ../jerboa/jerbuild ==="; \ + elif command -v jerbuild >/dev/null 2>&1 && command -v jerboa >/dev/null 2>&1 && jerbuild --jerboa-home >/dev/null 2>&1; then \ + echo "=== Using Jerboa toolchain from PATH: $$(command -v jerbuild) ==="; \ + else \ + echo "=== Fetching Jerboa $(JERBOA_VERSION) release tools into $(JERBOA_TOOL_DIR) ==="; \ + sh support/ensure-jerboa.sh "$(JERBOA_VERSION)" "$(JERBOA_TOOL_DIR)"; \ + fi + @"$(JERBUILD_TOOL)" --jerboa-home >/dev/null || { \ + echo "ERROR: Jerboa toolchain is unavailable; set JERBUILD_TOOL=/path/to/jerbuild or JERBOA_VERSION=<tag>"; \ + exit 1; \ + } + +build-jerbuild: ensure-jerboa-tools vendor-deps + JERBUILD="$(JERBUILD_TOOL)" support/stage-for-jerbuild.sh + +jerbuild-check: ensure-jerboa-tools + @for cfg in .jerbuild .jerbuild.linux-amd64 .jerbuild.linux-arm64 .jerbuild.freebsd-amd64; do \ + echo "=== $$cfg ==="; \ + "$(JERBUILD_TOOL)" check --config "$$cfg"; \ + done + +jemacs-jerbuild: ensure-jerboa-tools vendor-deps repl_shim.$(SHLIB_EXT) pty_shim.$(SHLIB_EXT) vterm_shim.$(SHLIB_EXT) jerboa_scintilla_shim.$(SHLIB_EXT) jerboa_pcre2_shim.$(SHLIB_EXT) + JERBUILD="$(JERBUILD_TOOL)" "$(JERBUILD_TOOL)" build --config .jerbuild + # Generate lib/jerboa-emacs/*.sls from src/jerboa-emacs/*.ss (incremental) build: deps $(JERBUILD) src/ lib/ @@ -784,6 +846,67 @@ ensure-podman-deps: check-podman # Builds only jemacs-qt itself (~5-10 min). Output: ./jemacs-qt (static ELF). static-qt: linux-static-qt-podman +linux: linux-amd64 + +linux-amd64: + @case "$$(uname -s)-$$(uname -m)" in \ + Linux-x86_64|Linux-amd64) $(MAKE) jemacs-linux-amd64-local ;; \ + *) $(MAKE) jemacs-linux-amd64-remote ;; \ + esac + +jemacs-linux-amd64-local: ensure-jerboa-tools vendor-deps + @case "$$(uname -s)-$$(uname -m)" in \ + Linux-x86_64|Linux-amd64) ;; \ + *) echo "ERROR: run locally on Linux amd64, or use 'make jemacs-linux-amd64-remote LINUX_BUILD_HOST=host'." >&2; exit 1 ;; \ + esac + JERBUILD="$(JERBUILD_TOOL)" "$(JERBUILD_TOOL)" build --config .jerbuild.linux-amd64 + @ls -lh jemacs-linux-amd64 + @file jemacs-linux-amd64 + +jemacs-linux-amd64-remote: + $(SSH) $(LINUX_BUILD_HOST) 'cd $(LINUX_BUILD_ROOT) && git pull --ff-only && make linux-amd64' + $(SCP) $(LINUX_BUILD_HOST):$(LINUX_BUILD_ROOT)/jemacs-linux-amd64 ./jemacs-linux-amd64 + @ls -lh jemacs-linux-amd64 + @file jemacs-linux-amd64 + +linux-arm64: + @case "$$(uname -s)-$$(uname -m)" in \ + Linux-aarch64|Linux-arm64) $(MAKE) jemacs-linux-arm64-local ;; \ + *) test -n "$(LINUX_ARM64_BUILD_HOST)" || { echo "ERROR: run on Linux arm64 or set LINUX_ARM64_BUILD_HOST for SSH target-host build." >&2; exit 1; }; \ + $(MAKE) jemacs-linux-arm64-remote ;; \ + esac + +jemacs-linux-arm64-local: ensure-jerboa-tools vendor-deps + @case "$$(uname -s)-$$(uname -m)" in \ + Linux-aarch64|Linux-arm64) ;; \ + *) echo "ERROR: run locally on Linux arm64, or set LINUX_ARM64_BUILD_HOST and use make linux-arm64." >&2; exit 1 ;; \ + esac + JERBUILD="$(JERBUILD_TOOL)" "$(JERBUILD_TOOL)" build --config .jerbuild.linux-arm64 + @ls -lh jemacs-linux-arm64 + @file jemacs-linux-arm64 + +jemacs-linux-arm64-remote: + $(SSH) $(LINUX_ARM64_BUILD_HOST) 'cd $(LINUX_ARM64_BUILD_ROOT) && git pull --ff-only && make linux-arm64' + $(SCP) $(LINUX_ARM64_BUILD_HOST):$(LINUX_ARM64_BUILD_ROOT)/jemacs-linux-arm64 ./jemacs-linux-arm64 + @ls -lh jemacs-linux-arm64 + @file jemacs-linux-arm64 + +jemacs-linux-amd64: linux-amd64 +jemacs-linux-arm64: linux-arm64 + +freebsd: freebsd-amd64 + +freebsd-amd64: ensure-jerboa-tools vendor-deps + @case "$$(uname -s)-$$(uname -m)" in \ + FreeBSD-amd64|FreeBSD-x86_64) ;; \ + *) echo "ERROR: build freebsd-amd64 natively on a FreeBSD amd64 host." >&2; exit 1 ;; \ + esac + JERBUILD="$(JERBUILD_TOOL)" "$(JERBUILD_TOOL)" build --config .jerbuild.freebsd-amd64 + @ls -lh jemacs-freebsd-amd64 + @file jemacs-freebsd-amd64 + +jemacs-freebsd-amd64: freebsd-amd64 + clean-podman: check-podman -$(PODMAN) run --rm $(PODMAN_RUN_FLAGS) -v $(CURDIR):/src:z alpine sh -c "rm -rf /src/jemacs-qt /src/jemacs-qt.boot /src/qt-main.so /src/qt-main.wpo /src/jemacs-qt-all.so 2>/dev/null; true" --- a/README.md +++ b/README.md @@ -52,6 +52,49 @@ All commands run from the project root. toolchain at `vendor/jerboa/dist/{jerboa,jerbuild}`. The editor vendors and builds its native Scheme/FFI dependencies under `vendor/`. +For systems that have the standalone Jerboa release toolchain but no full +Jerboa runtime checkout, use: + +```bash +make ensure-jerboa-tools +make build-jerbuild +make jerbuild-check +``` + +`ensure-jerboa-tools` follows the same convention as `jerboa-code` and +`jerboa-shell`: it prefers project-local tools, a sibling `../jerboa` build, or +`PATH`, and otherwise downloads `jerboa-${JERBOA_VERSION}` into `.jerboa/bin`. +The `.jerbuild*` configs describe native target-host builds for macOS/Linux/ +FreeBSD without requiring an installed full Jerboa runtime. + +### Cross and target builds + +Linux and FreeBSD target artifacts are built with `jerbuild` on the target OS. +From macOS, the Linux amd64 target uses SSH by default: + +```bash +make linux-amd64 # writes ./jemacs-linux-amd64 +``` + +The default SSH host is `linux.cons.io`; override it with +`LINUX_BUILD_HOST=host` and `LINUX_BUILD_ROOT=/path/to/jerboa-emacs`. + +Linux arm64 and FreeBSD follow the `jerboa-shell` pattern and are built on a +matching target host: + +```bash +make linux-arm64 # on Linux arm64, or set LINUX_ARM64_BUILD_HOST +make freebsd-amd64 # writes ./jemacs-freebsd-amd64 +``` + +Native target-host jerbuild configs are also available: + +```bash +jerbuild build --config .jerbuild.linux-amd64 +jerbuild build --config .jerbuild.linux-arm64 +jerbuild build --config .jerbuild.freebsd-amd64 +``` + ### Vendor dependencies ```bash --- a/build-binary.ss +++ b/build-binary.ss @@ -49,6 +49,13 @@ (if (eof-object? line) default line)) default))) +(define (env-nonempty name) + (let ((v (getenv name))) + (and v (not (string=? v "")) v))) + +(define (env-or-shell name cmd default) + (or (env-nonempty name) (shell-output cmd default))) + ;; --- Locate Chez install directory --- (define chez-dir (or (getenv "CHEZ_DIR") @@ -133,6 +140,11 @@ (let ((v (getenv "JEMACS_STATIC"))) (and v (not (string=? v "0")) (not (string=? v ""))))) +(define cc (or (env-nonempty "CC") "gcc")) +(define cxx (or (env-nonempty "CXX") "g++")) +(define cflags (or (env-nonempty "CFLAGS") "-O2")) +(define output-name (or (env-nonempty "JEMACS_OUTPUT") "jemacs")) + ;; Check critical dependencies (for-each (lambda (path label) @@ -265,9 +277,9 @@ (printf "[5/6] Compiling C sources...~n") ;; pcre2 shim -(let* ((pcre2-cflags (shell-output "pkg-config --cflags libpcre2-8" "-I/usr/include")) - (cmd (format "gcc -c -O2 -o jemacs-pcre2-shim.o ~a/jerboa_pcre2_shim.c ~a -Wall 2>&1" - pcre2-root pcre2-cflags))) +(let* ((pcre2-cflags (env-or-shell "PCRE2_CFLAGS" "pkg-config --cflags libpcre2-8" "-I/usr/include")) + (cmd (format "~a -c ~a -o jemacs-pcre2-shim.o ~a/jerboa_pcre2_shim.c ~a -Wall 2>&1" + cc cflags pcre2-root pcre2-cflags))) (unless (= 0 (system cmd)) (display "Error: pcre2 shim compilation failed\n") (exit 1))) @@ -275,28 +287,30 @@ ;; Static-only C sources (when jemacs-static? ;; jsh FFI shim - (let* ((cmd (format "gcc -c -O2 -o jemacs-jsh-ffi.o ~a/ffi-shim.c -Wall 2>&1" - jsh-root))) + (let* ((cmd (format "~a -c ~a -o jemacs-jsh-ffi.o ~a/ffi-shim.c -Wall 2>&1" + cc cflags jsh-root))) (unless (= 0 (system cmd)) (display "Error: jsh ffi-shim.c compilation failed\n") (exit 1))) ;; libcoreutils.c (terminal/raw-mode symbols) - (let* ((cmd (format "gcc -c -O2 -o jemacs-libcoreutils.o ~a -Wall 2>&1" - libcoreutils-c))) + (let* ((cmd (format "~a -c ~a -o jemacs-libcoreutils.o ~a -Wall 2>&1" + cc cflags libcoreutils-c))) (unless (= 0 (system cmd)) (display "Error: libcoreutils.c compilation failed\n") (exit 1))) ;; jsh coreutils stubs (Rust uutils symbols — stubs for static binary) - (let* ((cmd "gcc -c -O2 -o jemacs-jsh-coreutils-stubs.o support/jsh_coreutils_stubs.c -Wall 2>&1")) + (let* ((cmd (format "~a -c ~a -o jemacs-jsh-coreutils-stubs.o support/jsh_coreutils_stubs.c -Wall 2>&1" + cc cflags))) (unless (= 0 (system cmd)) (display "Error: jsh_coreutils_stubs.c compilation failed\n") (exit 1))) ;; jerboa native Rust crypto stubs. The TUI binary does not ship ;; libjerboa_native, but some vendored modules bind these symbols at load. - (let* ((cmd "gcc -c -O2 -o jemacs-jerboa-native-stubs.o support/jerboa_native_stubs.c -Wall 2>&1")) + (let* ((cmd (format "~a -c ~a -o jemacs-jerboa-native-stubs.o support/jerboa_native_stubs.c -Wall 2>&1" + cc cflags))) (unless (= 0 (system cmd)) (display "Error: jerboa_native_stubs.c compilation failed\n") (exit 1))) @@ -307,8 +321,8 @@ (let* ((embed-src (format "~a/embed-crypto.c" jsh-root)) (fallback-src "support/jsh_embed_crypto_stubs.c") (src (if (file-exists? embed-src) embed-src fallback-src)) - (cmd (format "gcc -c -O2 -o jemacs-embed-crypto.o ~a -I~a -Wall 2>&1" - src jsh-root))) + (cmd (format "~a -c ~a -o jemacs-embed-crypto.o ~a -I~a -Wall 2>&1" + cc cflags src jsh-root))) (unless (= 0 (system cmd)) (display "Error: embed-crypto.c compilation failed\n") (exit 1))) @@ -321,34 +335,37 @@ (fprintf out "void jerboa_ssh_agent_stop(void) {}~n") (fprintf out "int jerboa_ssh_agent_is_running(void) { return 0; }~n")) 'replace) - (let ((cmd "gcc -c -O2 -o jemacs-ssh-agent-stub.o jemacs-ssh-agent-stub.c -Wall 2>&1")) + (let ((cmd (format "~a -c ~a -o jemacs-ssh-agent-stub.o jemacs-ssh-agent-stub.c -Wall 2>&1" + cc cflags))) (unless (= 0 (system cmd)) (display "Error: ssh-agent stub compilation failed\n") (exit 1)))) ;; pty shim - (let* ((cmd "gcc -c -O2 -o jemacs-pty-shim.o support/pty_shim.c -Wall 2>&1")) + (let* ((cmd (format "~a -c ~a -o jemacs-pty-shim.o support/pty_shim.c -Wall 2>&1" + cc cflags))) (unless (= 0 (system cmd)) (display "Error: pty_shim.c compilation failed\n") (exit 1))) ;; vterm shim - (let* ((cmd "gcc -c -O2 -o jemacs-vterm-shim.o support/vterm_shim.c -Wall 2>&1")) + (let* ((cmd (format "~a -c ~a -o jemacs-vterm-shim.o support/vterm_shim.c -Wall 2>&1" + cc cflags))) (unless (= 0 (system cmd)) (display "Error: vterm_shim.c compilation failed\n") (exit 1))) ;; repl shim - (let* ((cmd (format "gcc -c -O2 -o jemacs-repl-shim.o support/repl_shim.c -I~a -Wall 2>&1" - chez-dir))) + (let* ((cmd (format "~a -c ~a -o jemacs-repl-shim.o support/repl_shim.c -I~a -Wall 2>&1" + cc cflags chez-dir))) (unless (= 0 (system cmd)) (display "Error: repl_shim.c compilation failed\n") (exit 1))) ;; jerboa landlock shim (let* ((jerboa-root (path-parent jerboa-dir)) - (cmd (format "gcc -c -O2 -o jemacs-jerboa-landlock.o ~a/support/landlock-shim.c -Wall 2>&1" - jerboa-root))) + (cmd (format "~a -c ~a -o jemacs-jerboa-landlock.o ~a/support/landlock-shim.c -Wall 2>&1" + cc cflags jerboa-root))) (unless (= 0 (system cmd)) (display "Error: landlock-shim.c compilation failed\n") (exit 1))) @@ -358,8 +375,8 @@ (let* ((sci-include (format "-I~a/scintilla/include -I~a/scintilla/src -I~a/scintilla/termbox -I~a/scintilla/termbox/termbox_next/src -I~a/lexilla/include" sci-vendor-dir sci-vendor-dir sci-vendor-dir sci-vendor-dir sci-vendor-dir)) (sci-shim-c (repo-path "jerboa_scintilla_shim.c")) - (cmd (format "gcc -c -O2 -o jemacs-sci-shim.o ~a ~a -Wall 2>&1" - sci-shim-c sci-include))) + (cmd (format "~a -c ~a -o jemacs-sci-shim.o ~a ~a -Wall 2>&1" + cc cflags sci-shim-c sci-include))) (unless (= 0 (system cmd)) (display "Error: jerboa_scintilla_shim.c compilation failed\n") (exit 1))) @@ -408,8 +425,8 @@ echo OK" (exit 1)) (let* ((count (shell-output "grep -c 'Sforeign_symbol' tui_static_symbols.c" "0"))) (printf " Generated tui_static_symbols.c with ~a symbol registrations~n" count)) - (let* ((cmd (format "gcc -c -O2 -o tui_static_symbols.o tui_static_symbols.c -I~a -Wall 2>&1" - include-dir))) + (let* ((cmd (format "~a -c ~a -o tui_static_symbols.o tui_static_symbols.c -I~a -Wall 2>&1" + cc cflags include-dir))) (unless (= 0 (system cmd)) (display "Error: tui_static_symbols.c compilation failed\n") (exit 1))))) @@ -418,20 +435,20 @@ echo OK" ;; Linked with -rdynamic so foreign-procedure finds them via dlopen(NULL). (when (not jemacs-static?) ;; repl shim (repl_poll, repl_nanosleep, etc.) - (let* ((cmd (format "gcc -c -O2 -o jemacs-repl-shim.o support/repl_shim.c -I~a -Wall 2>&1" - chez-dir))) + (let* ((cmd (format "~a -c ~a -o jemacs-repl-shim.o support/repl_shim.c -I~a -Wall 2>&1" + cc cflags chez-dir))) (unless (= 0 (system cmd)) (display "Error: repl_shim.c (dynamic) compilation failed\n") (exit 1))) ;; jsh FFI shim (ffi_file_type, ffi_*, etc.) - (let* ((cmd (format "gcc -c -O2 -o jemacs-jsh-ffi.o ~a/ffi-shim.c -Wall 2>&1" - jsh-root))) + (let* ((cmd (format "~a -c ~a -o jemacs-jsh-ffi.o ~a/ffi-shim.c -Wall 2>&1" + cc cflags jsh-root))) (unless (= 0 (system cmd)) (display "Error: jsh ffi-shim.c (dynamic) compilation failed\n") (exit 1))) ;; libcoreutils (coreutils_raw_mode_*, coreutils_terminal_*, etc.) - (let* ((cmd (format "gcc -c -O2 -o jemacs-libcoreutils.o ~a -Wall 2>&1" - libcoreutils-c))) + (let* ((cmd (format "~a -c ~a -o jemacs-libcoreutils.o ~a -Wall 2>&1" + cc cflags libcoreutils-c))) (unless (= 0 (system cmd)) (display "Error: libcoreutils.c (dynamic) compilation failed\n") (exit 1))) @@ -439,8 +456,8 @@ echo OK" (let* ((embed-src (format "~a/embed-crypto.c" jsh-root)) (fallback-src "support/jsh_embed_crypto_stubs.c") (src (if (file-exists? embed-src) embed-src fallback-src)) - (cmd (format "gcc -c -O2 -o jemacs-embed-crypto.o ~a -I~a -Wall 2>&1" - src jsh-root))) + (cmd (format "~a -c ~a -o jemacs-embed-crypto.o ~a -I~a -Wall 2>&1" + cc cflags src jsh-root))) (unless (= 0 (system cmd)) (display "Error: embed-crypto.c (dynamic) compilation failed\n") (exit 1))) @@ -452,17 +469,20 @@ echo OK" (fprintf out "void jerboa_ssh_agent_stop(void) {}~n") (fprintf out "int jerboa_ssh_agent_is_running(void) { return 0; }~n")) 'replace) - (let ((cmd "gcc -c -O2 -o jemacs-ssh-agent-stub.o jemacs-ssh-agent-stub.c -Wall 2>&1")) + (let ((cmd (format "~a -c ~a -o jemacs-ssh-agent-stub.o jemacs-ssh-agent-stub.c -Wall 2>&1" + cc cflags))) (unless (= 0 (system cmd)) (display "Error: ssh-agent stub (dynamic) compilation failed\n") (exit 1)))) ;; jsh coreutils stubs (jsh_* Rust uutils symbols) - (let* ((cmd "gcc -c -O2 -o jemacs-jsh-coreutils-stubs.o support/jsh_coreutils_stubs.c -Wall 2>&1")) + (let* ((cmd (format "~a -c ~a -o jemacs-jsh-coreutils-stubs.o support/jsh_coreutils_stubs.c -Wall 2>&1" + cc cflags))) (unless (= 0 (system cmd)) (display "Error: jsh_coreutils_stubs.c (dynamic) compilation failed\n") (exit 1))) ;; jerboa native Rust crypto stubs - (let* ((cmd "gcc -c -O2 -o jemacs-jerboa-native-stubs.o support/jerboa_native_stubs.c -Wall 2>&1")) + (let* ((cmd (format "~a -c ~a -o jemacs-jerboa-native-stubs.o support/jerboa_native_stubs.c -Wall 2>&1" + cc cflags))) (unless (= 0 (system cmd)) (display "Error: jerboa_native_stubs.c (dynamic) compilation failed\n") (exit 1))) @@ -487,15 +507,16 @@ echo OK" (fprintf out "int jerboa_tls_get_fd(uint64_t s) { return -1; }~n") (fprintf out "/* jerboa_last_error is provided by jerboa_native_stubs.c. */~n")) 'replace) - (let ((cmd "gcc -c -O2 -o jemacs-tls-stubs.o jemacs-tls-stubs.c -Wall 2>&1")) + (let ((cmd (format "~a -c ~a -o jemacs-tls-stubs.o jemacs-tls-stubs.c -Wall 2>&1" + cc cflags))) (unless (= 0 (system cmd)) (display "Error: TLS stubs compilation failed\n") (exit 1))))) ;; jemacs-main.c (let* ((static-flag (if jemacs-static? "-DJEMACS_STATIC_BUILD" "")) - (cmd (format "gcc -c -O2 ~a -o jemacs-main.o jemacs-main.c -I~a -I. -Wall 2>&1" - static-flag chez-dir))) + (cmd (format "~a -c ~a ~a -o jemacs-main.o jemacs-main.c -I~a -I. -Wall 2>&1" + cc cflags static-flag chez-dir))) (unless (= 0 (system cmd)) (display "Error: jemacs-main.c compilation failed\n") (exit 1))) @@ -504,14 +525,16 @@ echo OK" (printf "[6/6] Linking native binary...~n") (if jemacs-static? ;; ─── Static link (Podman musl build) ─────────────────────────────────── - (let* ((pcre2-libs (shell-output "pkg-config --static --libs libpcre2-8" "-lpcre2-8")) - (ncurses-libs (shell-output "pkg-config --static --libs ncurses" "-lncurses")) - (vterm-libs (shell-output "pkg-config --static --libs vterm" "-lvterm")) + (let* ((pcre2-libs (env-or-shell "PCRE2_LIBS" "pkg-config --static --libs libpcre2-8" "-lpcre2-8")) + (ncurses-libs (env-or-shell "NCURSES_LIBS" "pkg-config --static --libs ncurses" "-lncurses")) + (vterm-libs (env-or-shell "VTERM_LIBS" "pkg-config --static --libs vterm" "-lvterm")) (sci-a (format "~a/scintilla/bin/scintilla.a" sci-vendor-dir)) (lex-a (format "~a/lexilla/bin/liblexilla.a" sci-vendor-dir)) (tbx-a (format "~a/scintilla/termbox/termbox_next/bin/termbox.a" sci-vendor-dir)) (jsh-coreutils-lib (or (getenv "JSH_COREUTILS_LIB") "")) - (cmd (format "g++ -static -Wl,--export-dynamic -o jemacs \ + (static-ldflags (or (env-nonempty "JEMACS_STATIC_LDFLAGS") "-static -Wl,--export-dynamic")) + (os-libs (or (env-nonempty "JEMACS_OS_LIBS") "-lm -ldl -lpthread -luuid -lstdc++")) + (cmd (format "~a ~a -o ~a \ jemacs-main.o jemacs-pcre2-shim.o jemacs-jsh-ffi.o \ jemacs-libcoreutils.o jemacs-jsh-coreutils-stubs.o \ jemacs-jerboa-native-stubs.o jemacs-embed-crypto.o jemacs-ssh-agent-stub.o \ @@ -522,11 +545,13 @@ tui_static_symbols.o \ -L~a -lkernel -llz4 -lz \ -Wl,--whole-archive ~a ~a ~a -Wl,--no-whole-archive \ ~a ~a ~a \ --lm -ldl -lpthread -luuid -lstdc++ 2>&1" +~a 2>&1" + cxx static-ldflags output-name jsh-coreutils-lib chez-dir sci-a lex-a tbx-a - pcre2-libs ncurses-libs vterm-libs))) + pcre2-libs ncurses-libs vterm-libs + os-libs))) (printf " ~a~n" cmd) (unless (= 0 (system cmd)) (display "Error: Static link failed\n") @@ -534,21 +559,25 @@ tui_static_symbols.o \ ;; ─── Dynamic link (default local build) ──────────────────────────────── ;; -rdynamic: export all compiled-in symbols to dlsym(RTLD_DEFAULT) so ;; Chez's foreign-procedure finds them via dlopen(NULL)/dlopen(""). - (let* ((pcre2-libs (shell-output "pkg-config --libs libpcre2-8" "-lpcre2-8")) - (ncurses-libs (shell-output "pkg-config --libs ncurses" "-lncurses")) + (let* ((pcre2-libs (env-or-shell "PCRE2_LIBS" "pkg-config --libs libpcre2-8" "-lpcre2-8")) + (ncurses-libs (env-or-shell "NCURSES_LIBS" "pkg-config --libs ncurses" "-lncurses")) (iconv-libs (if darwin? "-liconv" "")) - (cmd (format "gcc -rdynamic -o jemacs \ + (dynamic-ldflags (or (env-nonempty "JEMACS_DYNAMIC_LDFLAGS") "-rdynamic")) + (os-libs (or (env-nonempty "JEMACS_OS_LIBS") + (format "-lm -ldl -lpthread ~a" iconv-libs))) + (cmd (format "~a ~a -o ~a \ jemacs-main.o jemacs-pcre2-shim.o jemacs-repl-shim.o \ jemacs-jsh-ffi.o jemacs-libcoreutils.o jemacs-embed-crypto.o \ jemacs-ssh-agent-stub.o jemacs-jsh-coreutils-stubs.o \ jemacs-jerboa-native-stubs.o jemacs-tls-stubs.o \ -L~a -lkernel -llz4 -lz \ ~a ~a \ --lm -ldl -lpthread ~a 2>&1" - chez-dir pcre2-libs ncurses-libs iconv-libs))) +~a 2>&1" + cc dynamic-ldflags output-name + chez-dir pcre2-libs ncurses-libs os-libs))) (printf " ~a~n" cmd) (unless (= 0 (system cmd)) (display "Error: Dynamic link failed\n") (exit 1)))) -(printf "~nDone! Binary: ./jemacs~n") +(printf "~nDone! Binary: ./~a~n" output-name) new file mode 100755 --- /dev/null +++ b/support/ensure-jerboa.sh @@ -0,0 +1,119 @@ +#!/bin/sh +# Bootstrap a project-local Jerboa toolchain from SourceHut release artifacts. +# +# Usage: +# support/ensure-jerboa.sh v0.2.0 .jerboa/bin +# +# Override artifact resolution with: +# JERBOA_RELEASE_BASE=https://example.org/releases/v0.2.0 +# JERBOA_RELEASE_REPO=~lisp/jerboa +# JERBOA_RELEASE_TARGET=linux-amd64 + +set -eu + +usage() { + echo "Usage: $0 VERSION [BINDIR]" >&2 +} + +[ "${1:-}" ] || { usage; exit 2; } + +version=$1 +bindir=${2:-.jerboa/bin} +repo=${JERBOA_RELEASE_REPO:-~lisp/jerboa} +origin=${JERBOA_RELEASE_ORIGIN:-https://git.sr.ht} + +if [ "${JERBOA_RELEASE_TARGET:-}" ]; then + target=$JERBOA_RELEASE_TARGET +else + os=$(uname -s) + arch=$(uname -m) + case "$os-$arch" in + Darwin-arm64) target=macos-arm64 ;; + Linux-x86_64|Linux-amd64) target=linux-amd64 ;; + Linux-aarch64|Linux-arm64) target=linux-arm64 ;; + FreeBSD-amd64|FreeBSD-x86_64) target=freebsd-amd64 ;; + *) + echo "ERROR: unsupported platform for Jerboa release artifacts: $os $arch" >&2 + echo " set JERBUILD_TOOL=/path/to/jerbuild or build Jerboa locally for this host" >&2 + exit 1 + ;; + esac +fi + +case "$target" in + macos-arm64|linux-amd64|linux-arm64|freebsd-amd64) ;; + *) + echo "ERROR: unsupported release target: $target" >&2 + exit 1 + ;; +esac + +file="jerboa-${version}-${target}.tar.gz" +base=${JERBOA_RELEASE_BASE:-${origin}/${repo}/refs/download/${version}} +url="${base%/}/${file}" +sum_url="${url}.sha256" + +download() { + src=$1 + dst=$2 + if command -v curl >/dev/null 2>&1; then + curl -fsSL "$src" -o "$dst" + elif command -v fetch >/dev/null 2>&1; then + fetch -q -o "$dst" "$src" + elif command -v wget >/dev/null 2>&1; then + wget -q -O "$dst" "$src" + else + echo "ERROR: need curl, fetch, or wget to download Jerboa" >&2 + exit 1 + fi +} + +sha256_file() { + path=$1 + if command -v sha256sum >/dev/null 2>&1; then + sha256sum "$path" | awk '{print $1}' + elif command -v shasum >/dev/null 2>&1; then + shasum -a 256 "$path" | awk '{print $1}' + elif command -v sha256 >/dev/null 2>&1; then + sha256 -q "$path" + else + echo "ERROR: need sha256sum, shasum, or sha256" >&2 + exit 1 + fi +} + +tmp=$(mktemp -d "${TMPDIR:-/tmp}/jerboa-bootstrap.XXXXXX") +trap 'rm -rf "$tmp"' EXIT HUP INT TERM + +archive="$tmp/$file" +sum_file="$tmp/$file.sha256" + +echo "fetching $url" +download "$url" "$archive" +download "$sum_url" "$sum_file" + +expected=$(awk '{print $1; exit}' "$sum_file") +actual=$(sha256_file "$archive") +if [ "$expected" != "$actual" ]; then + echo "ERROR: checksum mismatch for $file" >&2 + echo "expected: $expected" >&2 + echo "actual: $actual" >&2 + exit 1 +fi + +mkdir -p "$tmp/extract" +tar -xzf "$archive" -C "$tmp/extract" +root="$tmp/extract/jerboa-${version}-${target}" +[ -x "$root/bin/jerboa" ] || { + echo "ERROR: archive did not contain bin/jerboa" >&2 + exit 1 +} + +mkdir -p "$bindir" +cp "$root/bin/jerboa" "$bindir/jerboa" +chmod 0755 "$bindir/jerboa" +for link in jmcp jlsp jerbuild jpkg; do + ln -sf jerboa "$bindir/$link" +done + +echo "installed $bindir/{jerboa,jmcp,jlsp,jerbuild,jpkg}" new file mode 100644 --- /dev/null +++ b/support/jemacs-jerbuild-main.c @@ -0,0 +1,154 @@ +/* + * Custom entry point for jemacs binaries built by `jerbuild build`. + * + * It matches jemacs-main.c's runtime behavior but uses jerbuild's generated + * header names: petite_boot.h, scheme_boot.h, program_boot.h, ffi_symbols.h. + * The program image is loaded with Sscheme_script so Chez threads keep working. + */ + +#define _GNU_SOURCE +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <stdint.h> +#include <errno.h> +#include <unistd.h> +#include <libgen.h> +#include <sys/stat.h> +#ifdef __linux__ +#include <sys/mman.h> +#elif defined(__FreeBSD__) +#include <sys/sysctl.h> +#elif defined(__APPLE__) +#include <mach-o/dyld.h> +#endif + +#include "scheme.h" +#include "petite_boot.h" +#include "scheme_boot.h" +#include "program_boot.h" +#include "ffi_symbols.h" + +static int write_all(int fd, const unsigned char *data, unsigned int size) { + const unsigned char *cursor = data; + size_t remaining = size; + + while (remaining > 0) { + ssize_t written = write(fd, cursor, remaining); + if (written < 0) { + if (errno == EINTR) + continue; + return -1; + } + if (written == 0) + return -1; + cursor += written; + remaining -= (size_t)written; + } + + return 0; +} + +static int resolve_exe(char *buf, size_t size) { +#ifdef __APPLE__ + uint32_t len = (uint32_t)size; + if (_NSGetExecutablePath(buf, &len) != 0) + return 0; + { + char real_buf[4096]; + char *resolved = realpath(buf, real_buf); + if (resolved) { + strncpy(buf, resolved, size - 1); + buf[size - 1] = '\0'; + } + } + return 1; +#elif defined(__FreeBSD__) + ssize_t len = readlink("/proc/curproc/file", buf, size - 1); + if (len > 0) { + buf[len] = '\0'; + return 1; + } + { + int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 }; + size_t out_len = size; + if (sysctl(mib, 4, buf, &out_len, NULL, 0) == 0 && out_len > 0) { + buf[out_len - 1] = '\0'; + return 1; + } + } + return 0; +#else + ssize_t len = readlink("/proc/self/exe", buf, size - 1); + if (len > 0) { + buf[len] = '\0'; + return 1; + } + return 0; +#endif +} + +int main(int argc, char *argv[]) { + char exe_buf[4096]; + char exe_dir[4096]; + + if (resolve_exe(exe_buf, sizeof(exe_buf))) { + setenv("JEMACS_EXE", exe_buf, 1); + strncpy(exe_dir, exe_buf, sizeof(exe_dir) - 1); + exe_dir[sizeof(exe_dir) - 1] = '\0'; + char *dir = dirname(exe_dir); + if (!getenv("JERBOA_SCINTILLA_LIB")) + setenv("JERBOA_SCINTILLA_LIB", dir, 0); + if (!getenv("JERBOA_PCRE2_LIB")) + setenv("JERBOA_PCRE2_LIB", dir, 0); + if (!getenv("JERBOA_EMACS_SUPPORT")) + setenv("JERBOA_EMACS_SUPPORT", dir, 0); + if (!getenv("JEMACS_BINARY_DIR")) + setenv("JEMACS_BINARY_DIR", dir, 0); + } + + char prog_path[4096]; +#ifdef __linux__ + int fd = memfd_create("jemacs-program", MFD_CLOEXEC); + if (fd < 0) { + perror("memfd_create"); + return 1; + } +#else + const char *tmpdir = getenv("TMPDIR"); + if (!tmpdir || !tmpdir[0]) tmpdir = "/tmp"; + snprintf(prog_path, sizeof(prog_path), "%s/jemacs-program-XXXXXX", tmpdir); + int fd = mkstemp(prog_path); + if (fd < 0) { + perror("mkstemp"); + return 1; + } +#endif + + if (write_all(fd, program_boot_data, program_boot_size) != 0) { + perror("write embedded program"); + close(fd); +#ifndef __linux__ + unlink(prog_path); +#endif + return 1; + } +#ifdef __linux__ + snprintf(prog_path, sizeof(prog_path), "/proc/self/fd/%d", fd); +#endif + + 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); + Sbuild_heap(NULL, NULL); + register_ffi_symbols(); + + int status = Sscheme_script(prog_path, argc, (const char **)argv); + + close(fd); +#ifndef __linux__ + unlink(prog_path); +#endif + Sscheme_deinit(); + return status; +} new file mode 100644 --- /dev/null +++ b/support/jemacs-jerbuild-symbols.list @@ -0,0 +1,251 @@ +repl_poll +repl_nanosleep