Fix static Qt Podman build
ober
11ac67ff9538b715e5d3622489f3b62280e25211
--- a/CLAUDE.md +++ b/CLAUDE.md @@ -17,7 +17,7 @@ make build # Translate src/*.ss → lib/*.sls (incremental) make rebuild # Force full retranslation make run # Build and run TUI editor make run-qt # Build and run Qt editor -make static-qt # Build static jemacs-qt binary via Docker +make static-qt # Build static jemacs-qt binary via Podman ``` ## MANDATORY: Build, Compile, and Verify After EVERY Change @@ -27,14 +27,14 @@ make static-qt # Build static jemacs-qt binary via Docker After ANY code change to `.ss` files, you MUST run these steps IN ORDER before responding to the user: 1. `make build` — rebuild `.sls` files from `.ss` sources. Fix any errors before proceeding. -2. `make static-qt` — rebuild the static Docker binary. Fix any errors before proceeding. +2. `make static-qt` — rebuild the static Podman binary. Fix any errors before proceeding. 3. `./jemacs-qt --version` — verify binary launches without exceptions. If ANY step fails, the fix is NOT done. Do NOT tell the user anything is fixed, working, or ready until all 3 steps pass. Do NOT skip step 2 or 3 — interpreted mode (`make run-qt`) does NOT prove the static binary works. Common pitfalls when step 3 fails: -- **`library (std ...) not found`**: The Docker image has a stale jerboa `std/` tree. New modules must be added to the sync list in the `linux-static-qt-docker` Makefile target AND compiled into the WPO step in `build-binary-qt.ss`. +- **`library (std ...) not found`**: The Podman image has a stale jerboa `std/` tree. New modules must be added to the sync list in the `linux-static-qt-podman` Makefile target AND compiled into the WPO step in `build-binary-qt.ss`. - **`Dynamic loading not supported`**: Any `load-shared-object` call must be guarded with the `JEMACS_STATIC` env var check (the binary sets `JEMACS_STATIC=1`). - **`final:` or other unsupported keywords**: jerbuild doesn't support all Gerbil `defstruct` keywords — remove them. - **Vendored dependencies**: run `make vendor-deps` and use `vendor/chez-*` plus `vendor/jerboa-*` checkouts. Do not rely on developer-local dependency paths or `gerbil-*` shim repos. The Qt shim sources live in this repo's `vendor/` directory. --- a/Dockerfile +++ b/Dockerfile @@ -1,13 +1,13 @@ -# Intermediate Docker image for jemacs-qt static builds. +# Intermediate Podman image for jemacs-qt static builds. # Bakes static Qt6 + QScintilla from source, plus all Chez Scheme # dependencies (jerboa, gherkin, jsh, chez-pcre2, chez-scintilla, # chez-qt) so that subsequent jemacs-qt builds only compile jemacs # itself (~5-10 min instead of ~30 min). # # Build with: -# make docker-deps +# make podman-deps # -# Uses BuildKit --build-context to pull dependency sources without +# Uses Podman --build-context to pull dependency sources without # copying them into the project directory. ARG ARCH=x86_64 @@ -272,40 +272,11 @@ COPY vendor/qt_chez_shim.c vendor/qt_shim.h /deps/chez-qt/ # Pre-compile all Chez library dependencies. # These .so files are baked into the image so jemacs builds only # need to compile jemacs-specific modules. +COPY support/static-precompile-deps.ss /tmp/static-precompile-deps.ss RUN /opt/chez/bin/scheme \ --libdirs /deps/jerboa/lib:/deps/gherkin:/deps/jsh/src:/deps/chez-pcre2:/deps/chez-scintilla/src:/deps/chez-qt \ --compile-imported-libraries \ - --script /dev/stdin <<'EOF' -#!chezscheme -(import - (except (chezscheme) make-hash-table hash-table? iota 1+ 1- - getenv path-extension path-absolute? thread? - make-mutex mutex? mutex-name) - (jerboa core) - (jerboa runtime) - (std sugar) - (std format) - (std sort) - (std pregexp) - (std foreign) - (std misc list) - (std misc thread) - (std os path) - (std os signal) - (compat types) - (compat gambit-compat) - (runtime util) - (runtime table) - (runtime c3) - (runtime mop) - (compat gambit) - (jsh ffi) - (jsh static-compat) - (chez-scintilla constants) - (chez-qt ffi) - (chez-qt qt)) -(display "Chez deps pre-compiled OK\n") -EOF + --script /tmp/static-precompile-deps.ss # Build static pcre2 shim object RUN PCRE2_CFLAGS=$(pkg-config --cflags libpcre2-8 2>/dev/null || echo "") && \ --- a/Dockerfile.qt +++ b/Dockerfile.qt @@ -1,4 +1,4 @@ -# Dockerfile.qt — Build jemacs-qt static binary using jerboa21/jerboa + Qt6 +# Podman-compatible container recipe for building static jemacs-qt with Qt6. # # Multi-stage build: # Stage 1 (Alpine): Build Qt6 static, QScintilla, tree-sitter, libvterm (musl) @@ -6,9 +6,9 @@ # Stage 2 (jerboa21/jerboa): Copy Qt artifacts + Jerboa deps, build jemacs-qt # # Usage: -# docker build -f Dockerfile.qt -t jemacs-qt-builder . -# id=$(docker create jemacs-qt-builder) -# docker cp $id:/out/jemacs-qt ./jemacs-qt && docker rm $id +# podman build -f Dockerfile.qt -t jemacs-qt-builder . +# id=$(podman create jemacs-qt-builder) +# podman cp $id:/out/jemacs-qt ./jemacs-qt && podman rm $id # chmod +x jemacs-qt # ── Stage 1: Build Qt6 + QScintilla + tree-sitter + libvterm on Alpine ─────── --- a/Dockerfile.tui +++ b/Dockerfile.tui @@ -1,11 +1,11 @@ -# Dockerfile.tui — Build jemacs (TUI) static binary using jerboa21/jerboa +# Podman-compatible container recipe for building static jemacs (TUI). # # Produces a fully static jemacs binary with zero runtime dependencies. # # Usage: -# docker build -f Dockerfile.tui -t jemacs-tui-builder . -# id=$(docker create jemacs-tui-builder) -# docker cp $id:/out/jemacs ./jemacs && docker rm $id +# podman build -f Dockerfile.tui -t jemacs-tui-builder . +# id=$(podman create jemacs-tui-builder) +# podman cp $id:/out/jemacs ./jemacs && podman rm $id # chmod +x jemacs FROM jerboa21/jerboa AS builder --- a/Makefile +++ b/Makefile @@ -80,7 +80,8 @@ endif 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 \ test-pty test-emacs test-functional test-term-hang \ - docker-deps static-qt static-tui clean-docker check-root \ + 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-tui linux-tui-local \ linux-qt linux-qt-local \ @@ -96,8 +97,8 @@ all: @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 " static-tui Build fully static TUI binary via Docker (./jemacs)" - @echo " static-qt Build static jemacs-qt binary via Docker" + @echo " static-tui Build fully static TUI binary via Podman (./jemacs)" + @echo " static-qt Build static jemacs-qt binary via Podman" @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" @@ -472,17 +473,22 @@ binary: build vterm_shim.$(SHLIB_EXT) chez_scintilla_shim.$(SHLIB_EXT) pcre2_shi $(SCHEME) $(LIBDIRS) --script build-binary.ss # ============================================================================= -# Static binary builds (Docker-based, Alpine musl) +# Static binary builds (Podman-based, Alpine musl) # ============================================================================= ARCH := $(shell uname -m) UID := $(shell id -u) GID := $(shell id -g) +PODMAN ?= podman +PODMAN_PLATFORM ?= linux/amd64 +PODMAN_BUILD_FLAGS ?= +PODMAN_RUN_FLAGS ?= # Dependency source directories (vendored clones) JERBOA_SRC ?= $(JERBOA) GHERKIN_SRC ?= $(CURDIR)/vendor/gherkin-runtime JSH_SRC ?= $(JSH_ROOT) +JSH_VENDOR_SRC ?= $(JSH_SRC)/vendor PCRE2_SRC ?= $(CHEZ_PCRE2_ROOT) SCI_SRC ?= $(CHEZ_SCINTILLA_ROOT) QT_SRC ?= $(CQT) @@ -495,12 +501,16 @@ JSH_COREUTILS_LIB ?= $(shell test -f $(_RUST_COREUTILS) && echo $(_RUST_COREUTIL DEPS_IMAGE := jemacs-deps:$(ARCH) -# Build intermediate deps Docker image (run once, or when deps change). +check-podman: + @command -v $(PODMAN) >/dev/null 2>&1 || \ + { echo "ERROR: Podman executable '$(PODMAN)' not found. Install Podman or set PODMAN=/path/to/podman."; exit 1; } + +# Build intermediate deps Podman image (run once, or when deps change). # Takes ~45-60 min: Qt6 static + QScintilla + Chez Scheme + all shims. CHEZ_COMMIT ?= 902a10098603481afce0ec8588114234c09d6318 -docker-deps: - DOCKER_BUILDKIT=1 docker build \ +podman-deps: check-podman + $(PODMAN) build $(PODMAN_BUILD_FLAGS) \ --build-arg ARCH=$(ARCH) \ --build-arg CHEZ_COMMIT=$(CHEZ_COMMIT) \ --build-context jerboa-src=$(JERBOA_SRC) \ @@ -515,19 +525,23 @@ docker-deps: -t $(DEPS_IMAGE) \ $(CURDIR) -# Fast static Qt binary via Docker (requires deps image from `make docker-deps`). +ensure-podman-deps: check-podman + @$(PODMAN) image exists $(DEPS_IMAGE) || \ + { echo "Deps image '$(DEPS_IMAGE)' not found; building with 'make podman-deps'."; $(MAKE) podman-deps; } + +# Fast static Qt binary via Podman. # Builds only jemacs-qt itself (~5-10 min). Output: ./jemacs-qt (static ELF). -static-qt: linux-static-qt-docker +static-qt: linux-static-qt-podman -clean-docker: - -docker run --rm -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" +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" check-root: @if [ "$$(id -u)" = "0" ]; then \ git config --global --add safe.directory '*'; \ fi -# In-container build target (called by linux-static-qt-docker) +# In-container build target (called by linux-static-qt-podman) # Chez machine type on Alpine x86_64 is ta6le (same as glibc Linux). # Auto-detect the versioned csv* subdirectory (e.g. csv10.4.0-pre-release.3/ta6le). CHEZ_MT ?= ta6le @@ -538,7 +552,11 @@ build-jemacs-qt-static: check-root cp /src/vendor/jerboa-shell/embed-crypto.c /deps/jsh/ 2>/dev/null; \ cp /src/vendor/jerboa-shell/embed-crypto.h /deps/jsh/ 2>/dev/null; \ cp /src/vendor/jerboa-shell/ffi-shim.c /deps/jsh/ 2>/dev/null; \ - cp /src/vendor/jerboa-shell/libcoreutils.c /deps/jsh/ 2>/dev/null; \ + if [ -f /src/vendor/jerboa-shell/vendor/jerboa-coreutils/support/libcoreutils.c ]; then \ + cp /src/vendor/jerboa-shell/vendor/jerboa-coreutils/support/libcoreutils.c /deps/jsh/libcoreutils.c; \ + elif [ -f /src/vendor/jerboa-shell/patches/libcoreutils.c ]; then \ + cp /src/vendor/jerboa-shell/patches/libcoreutils.c /deps/jsh/libcoreutils.c; \ + fi; \ if [ -f /src/vendor/jerboa-shell/crypto_stub.c ]; then \ gcc -c -O2 /src/vendor/jerboa-shell/crypto_stub.c -o /tmp/jemacs-build/crypto_stub.o; \ fi; \ @@ -564,16 +582,13 @@ build-jemacs-qt-static: check-root find /deps/chez-qt -name '*.wpo' -delete && \ /opt/chez/bin/scheme --libdirs /deps/chez-qt \ --compile-imported-libraries --script /deps/chez-qt/compile-libs.ss && \ - rm -f /deps/chez-qt/chez-qt/*.wpo && \ - cp /src/vendor/chez-pcre2-ffi-static.ss /deps/chez-pcre2/chez-pcre2/ffi.ss && \ - /opt/chez/bin/scheme --libdirs /deps/chez-pcre2 \ - --compile-imported-libraries --script /src/vendor/chez-pcre2-compile-libs.ss && \ - rm -f /deps/chez-pcre2/chez-pcre2/*.wpo && \ - cp /src/vendor/chez-scintilla-ffi-static.sls /deps/chez-scintilla/src/chez-scintilla/ffi.sls && \ - JEMACS_STATIC=1 /opt/chez/bin/scheme --libdirs /deps/chez-scintilla/src \ - --compile-imported-libraries --script /src/vendor/chez-scintilla-compile-libs.ss && \ - rm -f /deps/chez-scintilla/src/chez-scintilla/*.wpo && \ - cp /src/vendor/jerboa-net-tcp-static.sls /deps/jerboa/lib/std/net/tcp.sls && \ + cp /src/vendor/chez-pcre2-ffi-static.ss /deps/chez-pcre2/chez-pcre2/ffi.ss && \ + /opt/chez/bin/scheme --libdirs /deps/chez-pcre2 \ + --compile-imported-libraries --script /src/vendor/chez-pcre2-compile-libs.ss && \ + cp /src/vendor/chez-scintilla-ffi-static.sls /deps/chez-scintilla/src/chez-scintilla/ffi.sls && \ + JEMACS_STATIC=1 /opt/chez/bin/scheme --libdirs /deps/chez-scintilla/src \ + --compile-imported-libraries --script /src/vendor/chez-scintilla-compile-libs.ss && \ + cp /src/vendor/jerboa-net-tcp-static.sls /deps/jerboa/lib/std/net/tcp.sls && \ cp /src/vendor/jerboa-net-tcp-raw-static.sls /deps/jerboa/lib/std/net/tcp-raw.sls && \ cp /src/vendor/jerboa-net-uri.sls /deps/jerboa/lib/std/net/uri.sls && \ rm -f /deps/jerboa/lib/std/net/*.wpo /deps/jerboa/lib/std/net/*.so && \ @@ -586,21 +601,19 @@ build-jemacs-qt-static: check-root rm -f /deps/jerboa/lib/std/os/landlock.wpo /deps/jerboa/lib/std/os/landlock.so && \ JEMACS_STATIC=1 /opt/chez/bin/scheme --libdirs /deps/jerboa/lib \ --compile-imported-libraries --script /src/vendor/jerboa-compile-tcp.ss && \ - JEMACS_STATIC=1 /opt/chez/bin/scheme --libdirs /deps/jerboa/lib \ - --compile-imported-libraries --script /src/vendor/jerboa-compile-tcp-raw.ss && \ - /opt/chez/bin/scheme --libdirs /deps/jerboa/lib \ - --compile-imported-libraries --script /src/vendor/jerboa-compile-uri.ss && \ - rm -f /deps/jerboa/lib/std/net/*.wpo && \ - cp /src/vendor/jerboa-repl-static.sls /deps/jerboa/lib/std/repl.sls && \ + JEMACS_STATIC=1 /opt/chez/bin/scheme --libdirs /deps/jerboa/lib \ + --compile-imported-libraries --script /src/vendor/jerboa-compile-tcp-raw.ss && \ + /opt/chez/bin/scheme --libdirs /deps/jerboa/lib \ + --compile-imported-libraries --script /src/vendor/jerboa-compile-uri.ss && \ + cp /src/vendor/jerboa-repl-static.sls /deps/jerboa/lib/std/repl.sls && \ rm -f /deps/jerboa/lib/std/repl.wpo /deps/jerboa/lib/std/repl.so && \ - cd /deps/jerboa/lib && /opt/chez/bin/scheme --libdirs /deps/jerboa/lib \ - --compile-imported-libraries --script /src/vendor/jerboa-compile-repl.ss && \ - rm -f /deps/jerboa/lib/std/repl.wpo && cd /src && \ - rm -f /src/lib/jerboa/*.wpo /src/lib/jerboa/*.so && \ - JEMACS_STATIC=1 /opt/chez/bin/scheme --libdirs /src/lib \ - --compile-imported-libraries --script /src/vendor/jerboa-compile-repl-socket.ss && \ - rm -f /src/lib/jerboa/*.wpo && \ - echo "Building tree-sitter shim + queries..." && \ + cd /deps/jerboa/lib && /opt/chez/bin/scheme --libdirs /deps/jerboa/lib \ + --compile-imported-libraries --script /src/vendor/jerboa-compile-repl.ss && \ + cd /src && \ + rm -f /src/lib/jerboa/*.wpo /src/lib/jerboa/*.so && \ + JEMACS_STATIC=1 /opt/chez/bin/scheme --libdirs /src/lib \ + --compile-imported-libraries --script /src/vendor/jerboa-compile-repl-socket.ss && \ + echo "Building tree-sitter shim + queries..." && \ gcc -c -O2 -I/opt/tree-sitter-include -o /tmp/jemacs-build/treesitter_shim.o \ /src/support/treesitter_shim.c -Wall && \ gcc -c -O2 -o /tmp/jemacs-build/treesitter_queries.o \ @@ -610,19 +623,16 @@ build-jemacs-qt-static: check-root find /deps/chez-ssl -name '*.so' -delete && find /deps/chez-ssl -name '*.wpo' -delete && \ find /deps/chez-https -name '*.so' -delete && find /deps/chez-https -name '*.wpo' -delete && \ find /deps/jerboa-aws -name '*.so' -delete && find /deps/jerboa-aws -name '*.wpo' -delete && \ - JEMACS_STATIC=1 /opt/chez/bin/scheme \ - --libdirs /deps/chez-ssl/src:/deps/jerboa/lib \ - --compile-imported-libraries -q --script /src/vendor/chez-ssl-compile-libs.ss && \ - find /deps/chez-ssl -name '*.wpo' -delete && \ - JEMACS_STATIC=1 /opt/chez/bin/scheme \ - --libdirs /deps/chez-https/src:/deps/chez-ssl/src \ - --compile-imported-libraries -q --script /src/vendor/chez-https-compile-libs.ss && \ - find /deps/chez-https -name '*.wpo' -delete && \ - JEMACS_STATIC=1 /opt/chez/bin/scheme \ - --libdirs /deps/jerboa-aws:/deps/chez-https/src:/deps/chez-ssl/src:/deps/jerboa/lib \ - --compile-imported-libraries -q --script /src/vendor/jerboa-aws-compile-libs.ss && \ - find /deps/jerboa-aws -name '*.wpo' -delete && \ - JEMACS_STATIC=1 \ + JEMACS_STATIC=1 /opt/chez/bin/scheme \ + --libdirs /deps/chez-ssl/src:/deps/jerboa/lib \ + --compile-imported-libraries -q --script /src/vendor/chez-ssl-compile-libs.ss && \ + JEMACS_STATIC=1 /opt/chez/bin/scheme \ + --libdirs /deps/chez-https/src:/deps/chez-ssl/src \ + --compile-imported-libraries -q --script /src/vendor/chez-https-compile-libs.ss && \ + JEMACS_STATIC=1 /opt/chez/bin/scheme \ + --libdirs /deps/jerboa-aws:/deps/chez-https/src:/deps/chez-ssl/src:/deps/jerboa/lib \ + --compile-imported-libraries -q --script /src/vendor/jerboa-aws-compile-libs.ss && \ + JEMACS_STATIC=1 \ CHEZ_DIR=$(CHEZ_MUSL_DIR) \ JERBOA_DIR=/deps/jerboa/lib \ JSH_DIR=/deps/jsh/src \ @@ -645,15 +655,14 @@ build-jemacs-qt-static: check-root --libdirs lib:/deps/jerboa/lib:/deps/jsh/src:/deps/jsh/vendor/jerboa-coreutils/lib:/deps/jsh/vendor/jerboa-awk/lib:/deps/jsh/vendor/jerboa-sed/lib:/deps/jsh/vendor/chez-ssh/src:/deps/jsh/vendor/chez-sqlite/src:/deps/jsh/vendor/chez-crypto/src:/deps/jsh/vendor/chez-fuse/lib:/src/vendor/gherkin-runtime:/deps/chez-pcre2:/deps/chez-scintilla/src:/deps/chez-qt:/deps/jerboa-aws:/deps/chez-ssl/src:/deps/chez-https/src \ --script build-binary-qt.ss -linux-static-qt-docker: - @docker image inspect $(DEPS_IMAGE) >/dev/null 2>&1 || \ - { echo "ERROR: Deps image '$(DEPS_IMAGE)' not found. Run 'make docker-deps' first."; exit 1; } - docker run --rm \ +linux-static-qt-podman: ensure-podman-deps + $(PODMAN) run --rm $(PODMAN_RUN_FLAGS) \ --ulimit nofile=8192:8192 \ -v $(CURDIR):/src:z \ -v $(JERBOA)/lib/std:/host-jerboa-std:ro \ -v $(JERBOA)/lib/jerboa:/host-jerboa-core:ro \ -v $(JSH_SRC)/src:/host-jsh-src:ro \ + -v $(JSH_VENDOR_SRC):/host-jsh-vendor:ro \ -v $(JSH_COREUTILS_LIB):/host-jsh-coreutils.a:ro \ -v $(JAWS_SRC):/host-jaws:ro \ -v $(CSSL_SRC):/host-chez-ssl:ro \ @@ -670,30 +679,28 @@ linux-static-qt-docker: fi; \ cp /host-jsh-coreutils.a /deps/jsh/libjsh_coreutils.a; \ cp -a /host-jsh-src/. /deps/jsh/src/; \ + mkdir -p /deps/jsh/vendor && cp -a /host-jsh-vendor/. /deps/jsh/vendor/; \ echo 'SYNC: bulk-copying host jerboa std/ and jerboa/ into container...'; \ cp -a /host-jerboa-std/. /deps/jerboa/lib/std/ && \ cp -a /host-jerboa-core/. /deps/jerboa/lib/jerboa/ && \ find /deps/jerboa/lib -name '*.so' -delete && \ find /deps/jerboa/lib -name '*.wpo' -delete && \ - echo '(import (chezscheme)) (compile-imported-libraries #t) (import (jerboa core)) (import (jerboa prelude))' \ + echo '(import (chezscheme)) (compile-imported-libraries #t) (generate-wpo-files #t) (import (jerboa core)) (import (jerboa prelude))' \ > /tmp/compile-jerboa-core.ss && \ cd /deps/jerboa/lib && /opt/chez/bin/scheme --libdirs /deps/jerboa/lib \ -q --script /tmp/compile-jerboa-core.ss && \ - rm -f /deps/jerboa/lib/jerboa/*.wpo && \ echo 'COMPILED: jerboa core + prelude'; \ mkdir -p /deps/jerboa-aws /deps/chez-ssl/src /deps/chez-https/src && \ cp -a /host-jaws/. /deps/jerboa-aws/ && \ cp -a /host-chez-ssl/. /deps/chez-ssl/ && \ cp -a /host-chez-https/. /deps/chez-https/ && \ echo 'SYNC: jerboa-aws, chez-ssl, chez-https copied'; \ - chmod 755 /root && \ - chown -R $(UID):$(GID) /opt/ /deps && \ - mkdir -p /tmp/jemacs-build && chown $(UID):$(GID) /tmp/jemacs-build && \ - exec su-exec $(UID):$(GID) env HOME=/tmp/jemacs-build sh -c '\ + mkdir -p /tmp/jemacs-build && \ + exec env HOME=/tmp/jemacs-build sh -c '\ cd /src && make build-jemacs-qt-static'" # ============================================================================= -# Static TUI binary (Docker-based, Alpine musl) +# Static TUI binary (Podman-based, Alpine musl) # ============================================================================= # Scintilla/termbox/Lexilla C/C++ source + headers used to build static @@ -701,29 +708,31 @@ linux-static-qt-docker: # vendored checkout. SCI_VENDOR_SRC ?= $(CHEZ_SCINTILLA_ROOT)/vendor -# Fast static TUI binary via Docker (requires deps image from `make docker-deps`). +# Fast static TUI binary via Podman. # Builds Scintilla+termbox+Lexilla from source, then ./jemacs (~5-10 min). -static-tui: linux-static-tui-docker +static-tui: linux-static-tui-podman -# In-container build target for TUI static binary (called by linux-static-tui-docker) +# In-container build target for TUI static binary (called by linux-static-tui-podman) build-jemacs-tui-static: check-root rm -f /src/src/.jerbuild-hashes; \ cp /src/vendor/jerboa-shell/embed-crypto.c /deps/jsh/ 2>/dev/null; \ cp /src/vendor/jerboa-shell/embed-crypto.h /deps/jsh/ 2>/dev/null; \ cp /src/vendor/jerboa-shell/ffi-shim.c /deps/jsh/ 2>/dev/null; \ - cp /src/vendor/jerboa-shell/libcoreutils.c /deps/jsh/ 2>/dev/null; \ + if [ -f /src/vendor/jerboa-shell/vendor/jerboa-coreutils/support/libcoreutils.c ]; then \ + cp /src/vendor/jerboa-shell/vendor/jerboa-coreutils/support/libcoreutils.c /deps/jsh/libcoreutils.c; \ + elif [ -f /src/vendor/jerboa-shell/patches/libcoreutils.c ]; then \ + cp /src/vendor/jerboa-shell/patches/libcoreutils.c /deps/jsh/libcoreutils.c; \ + fi; \ cd /src && find lib -name '*.so' -o -name '*.wpo' | xargs rm -f 2>/dev/null; \ find /src/src/jerboa-emacs -name '*.ss' | sed 's|/src/src/|/src/lib/|; s|\.ss$$|.sls|' | xargs rm -f 2>/dev/null; \ cd /src && make build SCHEME=/opt/chez/bin/scheme JERBOA=/deps/jerboa && \ cp /src/vendor/chez-pcre2-ffi-static.ss /deps/chez-pcre2/chez-pcre2/ffi.ss && \ /opt/chez/bin/scheme --libdirs /deps/chez-pcre2 \ --compile-imported-libraries --script /src/vendor/chez-pcre2-compile-libs.ss && \ - rm -f /deps/chez-pcre2/chez-pcre2/*.wpo && \ - cp /src/vendor/chez-scintilla-ffi-static.sls /deps/chez-scintilla/src/chez-scintilla/ffi.sls && \ - JEMACS_STATIC=1 /opt/chez/bin/scheme --libdirs /deps/chez-scintilla/src \ - --compile-imported-libraries --script /src/vendor/chez-scintilla-compile-libs.ss && \ - rm -f /deps/chez-scintilla/src/chez-scintilla/*.wpo && \ - cp /src/vendor/jerboa-net-tcp-static.sls /deps/jerboa/lib/std/net/tcp.sls && \ + cp /src/vendor/chez-scintilla-ffi-static.sls /deps/chez-scintilla/src/chez-scintilla/ffi.sls && \ + JEMACS_STATIC=1 /opt/chez/bin/scheme --libdirs /deps/chez-scintilla/src \ + --compile-imported-libraries --script /src/vendor/chez-scintilla-compile-libs.ss && \ + cp /src/vendor/jerboa-net-tcp-static.sls /deps/jerboa/lib/std/net/tcp.sls && \ cp /src/vendor/jerboa-net-tcp-raw-static.sls /deps/jerboa/lib/std/net/tcp-raw.sls && \ cp /src/vendor/jerboa-net-uri.sls /deps/jerboa/lib/std/net/uri.sls && \ rm -f /deps/jerboa/lib/std/net/*.wpo /deps/jerboa/lib/std/net/*.so && \ @@ -736,21 +745,19 @@ build-jemacs-tui-static: check-root rm -f /deps/jerboa/lib/std/os/landlock.wpo /deps/jerboa/lib/std/os/landlock.so && \ JEMACS_STATIC=1 /opt/chez/bin/scheme --libdirs /deps/jerboa/lib \ --compile-imported-libraries --script /src/vendor/jerboa-compile-tcp.ss && \ - JEMACS_STATIC=1 /opt/chez/bin/scheme --libdirs /deps/jerboa/lib \ - --compile-imported-libraries --script /src/vendor/jerboa-compile-tcp-raw.ss && \ - /opt/chez/bin/scheme --libdirs /deps/jerboa/lib \ - --compile-imported-libraries --script /src/vendor/jerboa-compile-uri.ss && \ - rm -f /deps/jerboa/lib/std/net/*.wpo && \ - cp /src/vendor/jerboa-repl-static.sls /deps/jerboa/lib/std/repl.sls && \ + JEMACS_STATIC=1 /opt/chez/bin/scheme --libdirs /deps/jerboa/lib \ + --compile-imported-libraries --script /src/vendor/jerboa-compile-tcp-raw.ss && \ + /opt/chez/bin/scheme --libdirs /deps/jerboa/lib \ + --compile-imported-libraries --script /src/vendor/jerboa-compile-uri.ss && \ + cp /src/vendor/jerboa-repl-static.sls /deps/jerboa/lib/std/repl.sls && \ rm -f /deps/jerboa/lib/std/repl.wpo /deps/jerboa/lib/std/repl.so && \ - cd /deps/jerboa/lib && /opt/chez/bin/scheme --libdirs /deps/jerboa/lib \ - --compile-imported-libraries --script /src/vendor/jerboa-compile-repl.ss && \ - rm -f /deps/jerboa/lib/std/repl.wpo && cd /src && \ - rm -f /src/lib/jerboa/*.wpo /src/lib/jerboa/*.so && \ - JEMACS_STATIC=1 /opt/chez/bin/scheme --libdirs /src/lib \ - --compile-imported-libraries --script /src/vendor/jerboa-compile-repl-socket.ss && \ - rm -f /src/lib/jerboa/*.wpo && \ - echo "Building Scintilla+termbox+Lexilla static archives from source..." && \ + cd /deps/jerboa/lib && /opt/chez/bin/scheme --libdirs /deps/jerboa/lib \ + --compile-imported-libraries --script /src/vendor/jerboa-compile-repl.ss && \ + cd /src && \ + rm -f /src/lib/jerboa/*.wpo /src/lib/jerboa/*.so && \ + JEMACS_STATIC=1 /opt/chez/bin/scheme --libdirs /src/lib \ + --compile-imported-libraries --script /src/vendor/jerboa-compile-repl-socket.ss && \ + echo "Building Scintilla+termbox+Lexilla static archives from source..." && \ make -C /deps/sci-vendor/scintilla/termbox/termbox_next && \ make -C /deps/sci-vendor/scintilla/termbox && \ make -C /deps/sci-vendor/lexilla/src && \ @@ -767,42 +774,39 @@ build-jemacs-tui-static: check-root --libdirs lib:/deps/jerboa/lib:/deps/jsh/src:/deps/jsh/vendor/jerboa-coreutils/lib:/deps/jsh/vendor/jerboa-awk/lib:/deps/jsh/vendor/jerboa-sed/lib:/deps/jsh/vendor/chez-ssh/src:/deps/jsh/vendor/chez-sqlite/src:/deps/jsh/vendor/chez-crypto/src:/deps/jsh/vendor/chez-fuse/lib:/src/vendor/gherkin-runtime:/deps/chez-pcre2:/deps/chez-scintilla/src \ --script build-binary.ss -linux-static-tui-docker: - @docker image inspect $(DEPS_IMAGE) >/dev/null 2>&1 || \ - { echo "ERROR: Deps image '$(DEPS_IMAGE)' not found. Run 'make docker-deps' first."; exit 1; } +linux-static-tui-podman: ensure-podman-deps @test -d $(SCI_VENDOR_SRC) || \ { echo "ERROR: SCI_VENDOR_SRC='$(SCI_VENDOR_SRC)' not found. Populate it from the chez-scintilla dependency or set SCI_VENDOR_SRC."; exit 1; } - docker run --rm \ + $(PODMAN) run --rm $(PODMAN_RUN_FLAGS) \ --ulimit nofile=8192:8192 \ -v $(CURDIR):/src:z \ -v $(SCI_VENDOR_SRC):/deps/sci-vendor:ro \ -v $(JERBOA)/lib/std:/host-jerboa-std:ro \ -v $(JERBOA)/lib/jerboa:/host-jerboa-core:ro \ -v $(JSH_SRC)/src:/host-jsh-src:ro \ + -v $(JSH_VENDOR_SRC):/host-jsh-vendor:ro \ -v $(JSH_COREUTILS_LIB):/host-jsh-coreutils.a:ro \ $(DEPS_IMAGE) \ sh -c "apk add --no-cache libvterm-dev libvterm-static; \ cp /host-jsh-coreutils.a /deps/jsh/libjsh_coreutils.a; \ cp -a /host-jsh-src/. /deps/jsh/src/; \ + mkdir -p /deps/jsh/vendor && cp -a /host-jsh-vendor/. /deps/jsh/vendor/; \ echo 'SYNC: bulk-copying host jerboa std/ and jerboa/ into container...'; \ cp -a /host-jerboa-std/. /deps/jerboa/lib/std/ && \ cp -a /host-jerboa-core/. /deps/jerboa/lib/jerboa/ && \ find /deps/jerboa/lib -name '*.so' -delete && \ find /deps/jerboa/lib -name '*.wpo' -delete && \ - echo '(import (chezscheme)) (compile-imported-libraries #t) (import (jerboa core)) (import (jerboa prelude))' \ + echo '(import (chezscheme)) (compile-imported-libraries #t) (generate-wpo-files #t) (import (jerboa core)) (import (jerboa prelude))' \ > /tmp/compile-jerboa-core.ss && \ cd /deps/jerboa/lib && /opt/chez/bin/scheme --libdirs /deps/jerboa/lib \ -q --script /tmp/compile-jerboa-core.ss && \ - rm -f /deps/jerboa/lib/jerboa/*.wpo && \ echo 'COMPILED: jerboa core + prelude'; \ - chmod 755 /root && \ - chown -R $(UID):$(GID) /opt/ /deps && \ - mkdir -p /tmp/jemacs-build && chown $(UID):$(GID) /tmp/jemacs-build && \ - exec su-exec $(UID):$(GID) env HOME=/tmp/jemacs-build sh -c '\ + mkdir -p /tmp/jemacs-build && \ + exec env HOME=/tmp/jemacs-build sh -c '\ cd /src && make build-jemacs-tui-static'" # ============================================================================= -# Static TUI via jerboa21/jerboa Docker image (like jerboa-gitsafe) +# Static TUI via jerboa21/jerboa Podman image (like jerboa-gitsafe) # ============================================================================= JERBOA_IMAGE ?= jerboa21/jerboa @@ -816,13 +820,13 @@ MUSL_JSH_ROOT ?= $(MUSL_DEPS)/jerboa-shell MUSL_JSH ?= $(MUSL_JSH_ROOT)/src MUSL_SCI_VENDOR ?= /build/sci-vendor -# Docker build: produces ./jemacs static binary -linux-tui: - @echo "=== Building jemacs static TUI binary in Docker ===" - docker build --platform linux/amd64 -f Dockerfile.tui -t jemacs-tui-builder . - @id=$$(docker create --platform linux/amd64 jemacs-tui-builder) && \ - docker cp $$id:/out/jemacs ./jemacs && \ - docker rm $$id >/dev/null +# Podman build: produces ./jemacs static binary +linux-tui: check-podman + @echo "=== Building jemacs static TUI binary in Podman ===" + $(PODMAN) build $(PODMAN_BUILD_FLAGS) --platform $(PODMAN_PLATFORM) -f Dockerfile.tui -t jemacs-tui-builder . + @id=$$($(PODMAN) create jemacs-tui-builder) && \ + $(PODMAN) cp $$id:/out/jemacs ./jemacs && \ + $(PODMAN) rm $$id >/dev/null @chmod +x jemacs @echo "" @ls -lh jemacs @@ -903,22 +907,22 @@ linux-tui-local: vendor-deps @file jemacs # ============================================================================= -# Static Qt binary via jerboa21/jerboa Docker image +# Static Qt binary via jerboa21/jerboa Podman image # ============================================================================= -# Docker build: produces ./jemacs-qt static binary -linux-qt: - @echo "=== Building jemacs-qt static binary in Docker ===" - docker build --platform linux/amd64 -f Dockerfile.qt -t jemacs-qt-builder . - @id=$$(docker create --platform linux/amd64 jemacs-qt-builder) && \ - docker cp $$id:/out/jemacs-qt ./jemacs-qt && \ - docker rm $$id >/dev/null +# Podman build: produces ./jemacs-qt static binary +linux-qt: check-podman + @echo "=== Building jemacs-qt static binary in Podman ===" + $(PODMAN) build $(PODMAN_BUILD_FLAGS) --platform $(PODMAN_PLATFORM) -f Dockerfile.qt -t jemacs-qt-builder . + @id=$$($(PODMAN) create jemacs-qt-builder) && \ + $(PODMAN) cp $$id:/out/jemacs-qt ./jemacs-qt && \ + $(PODMAN) rm $$id >/dev/null @chmod +x jemacs-qt @echo "" @ls -lh jemacs-qt @file jemacs-qt -# In-container build target (called inside Dockerfile.qt → jerboa21/jerboa stage) +# In-container build target (called inside the Podman Qt build container) # Qt6 static libs are at /opt/qt6-static (copied from Alpine stage). # Tree-sitter is at /opt/tree-sitter-* (copied from Alpine stage). # Pre-compiled libqt_shim.a is at /opt/qt-shim/ (Alpine-musl g++, ABI-compatible). --- a/build-binary-qt.ss +++ b/build-binary-qt.ss @@ -162,214 +162,76 @@ ;; --- Step 2: Whole-program optimization --- (printf "[2/7] Running whole-program optimization...~n") +(define wpo-missing-libraries '()) (let ((missing (compile-whole-program "qt-main.wpo" "jemacs-qt-all.so"))) + (set! wpo-missing-libraries missing) (unless (null? missing) (printf " WPO: ~a libraries not incorporated (missing .wpo):~n" (length missing)) (for-each (lambda (lib) (printf " ~a~n" lib)) missing))) ;; --- Step 3: Make libs-only boot file --- (printf "[3/7] Creating libs-only boot file...~n") +(define (symbol-path parts) + (let loop ((rest parts) (acc "")) + (cond + ((null? rest) acc) + ((string=? acc "") + (loop (cdr rest) (symbol->string (car rest)))) + (else + (loop (cdr rest) (string-append acc "/" (symbol->string (car rest)))))))) + +(define (library-ref->so-path lib) + (and (pair? lib) + (let ((head (car lib)) + (tail (cdr lib))) + (case head + ((std) + (format "~a/std/~a.so" jerboa-dir (symbol-path tail))) + ((jerboa) + (if (and (pair? tail) (eq? (car tail) 'repl-socket)) + "lib/jerboa/repl-socket.so" + (format "~a/jerboa/~a.so" jerboa-dir (symbol-path tail)))) + ((jsh) + (format "~a/jsh/~a.so" jsh-dir (symbol-path tail))) + ((compat) + (if (and (pair? tail) (eq? (car tail) 'gambit)) + (format "~a/compat/gambit.so" jsh-dir) + (format "~a/compat/~a.so" gherkin-dir (symbol-path tail)))) + ((runtime) + (format "~a/runtime/~a.so" gherkin-dir (symbol-path tail))) + ((chez-pcre2) + (format "~a/chez-pcre2/~a.so" pcre2-dir (symbol-path tail))) + ((chez-scintilla) + (format "~a/chez-scintilla/~a.so" sci-dir (symbol-path tail))) + ((chez-qt) + (format "~a/chez-qt/~a.so" qt-dir (symbol-path tail))) + ((chez-ssl) + (format "~a/src/chez-ssl.so" chez-ssl-dir)) + ((chez-https) + (format "~a/chez-https.so" chez-https-dir)) + ((jerboa-aws) + (format "~a/jerboa-aws/~a.so" jaws-dir (symbol-path tail))) + ((jerboa-emacs) + (format "lib/jerboa-emacs/~a.so" (symbol-path tail))) + (else #f))))) + +(define (wpo-missing-so-files) + (filter values (map library-ref->so-path wpo-missing-libraries))) + +(define (unique-strings strings) + (let loop ((rest strings) (seen '()) (acc '())) + (cond + ((null? rest) (reverse acc)) + ((member (car rest) seen) (loop (cdr rest) seen acc)) + (else (loop (cdr rest) (cons (car rest) seen) (cons (car rest) acc)))))) + (define (existing-so-files paths) (filter file-exists? paths)) -(apply make-boot-file "jemacs-qt.boot" '("scheme" "petite") - (existing-so-files - (append - ;; Jerboa runtime (no deps on other jerboa libs) - (map (lambda (m) (format "~a/~a.so" jerboa-dir m)) - '("jerboa/runtime")) - ;; Jerboa stdlib - (map (lambda (m) (format "~a/~a.so" jerboa-dir m)) - '("std/error" - "std/format" - "std/sort" - "std/pregexp" - "std/foreign" - "std/misc/string" - "std/misc/list" - "std/misc/alist" - "std/misc/thread" - "std/misc/fmt" - "std/os/path" - "std/os/signal" - "std/os/fdio" - "std/misc/custodian" - "std/misc/config" - "std/misc/memoize" - "std/misc/terminal" - "std/misc/trie" - "std/misc/lru-cache" - "std/misc/ports" - "std/srfi/srfi-13" - "std/text/json" - "std/actor/mpsc" - "std/actor/core" - "std/actor/transport" - "std/crypto/native" - "std/crypto/random" - "std/os/sandbox" - "std/os/landlock" - "std/security/capsicum")) - ;; Jerboa core + sugar + repl + dependencies - ;; std/typed: jerboa/core imports it - ;; std/result: std/sugar imports it - (map (lambda (m) (format "~a/~a.so" jerboa-dir m)) - '("std/result" - "std/typed" - "jerboa/core" - "std/sugar" - "std/repl")) - ;; std/net/tcp and std/net/uri (compiled by step 1) - (map (lambda (m) (format "~a/~a.so" jerboa-dir m)) - '("std/net/tcp" - "std/net/tcp-raw" - "std/net/uri")) - ;; jerboa/repl-socket (non-blocking socket FFI for debug REPL + IPC) - (list "lib/jerboa/repl-socket.so") - ;; Gherkin MOP modules (WPO-missing, must be in boot file) - (map (lambda (m) (format "~a/~a.so" gherkin-dir m)) - '("compat/types" - "compat/gambit-compat" - "runtime/util" - "runtime/table" - "runtime/c3" - "runtime/mop")) - ;; compat/gambit lives in jsh (not gherkin) - (list (format "~a/compat/gambit.so" jsh-dir)) - ;; jsh modules (WPO-missing, all needed transitively) - (map (lambda (m) (format "~a/jsh/~a.so" jsh-dir m)) - '("embed" - "embed-data" - "ffi" - "static-compat" - "pregexp-compat" - "util" - "arithmetic" - "ast" - "environment" - "registry" - "functions" - "signals" - "glob" - "expander" - "lexer" - "parser" - "redirect" - "pipeline" - "jobs" - "builtins" - "executor" - "control" - "script" - "macros" - "completion" - "fuzzy" - "fzf" - "history" - "prompt" - "lineedit" - "startup" - "stage" - "recording-index" - "recorder" - "player" - "conditions" - "config" - "sandbox" - "lib")) - ;; chez-pcre2 (compiled by step 1) - (map (lambda (m) (format "~a/chez-pcre2/~a.so" pcre2-dir m)) - '("ffi" "pcre2")) - ;; std/net/request (WPO-missing) - (list (format "~a/std/net/request.so" jerboa-dir)) - ;; chez-ssl + chez-https (TLS for AWS API) - (list (format "~a/src/chez-ssl.so" chez-ssl-dir) - (format "~a/chez-https.so" chez-https-dir)) - ;; jerboa-aws EC2 modules - (map (lambda (m) (format "~a/jerboa-aws/~a.so" jaws-dir m)) - '("creds" "crypto" "xml" "json" "time" "uri" "sigv4" "request" "api")) - (map (lambda (m) (format "~a/jerboa-aws/ec2/~a.so" jaws-dir m)) - '("xml" "params" "api" "instances")) - ;; chez-scintilla (all modules — WPO-missing) - (map (lambda (m) (format "~a/chez-scintilla/~a.so" sci-dir m)) - '("ffi" "constants" "style" "lexer" "scintilla" "tui")) - ;; chez-qt - (map (lambda (m) (format "~a/chez-qt/~a.so" qt-dir m)) - '("ffi" "qt")) - ;; jerboa-emacs shared modules (topological order) - (map (lambda (m) (format "lib/jerboa-emacs/~a.so" m)) - '(;; Tier 0: no jerboa-emacs deps - "customize" "themes" "pregexp-compat" "macros" - "vtscreen" "pty" "ipc" "debug-repl" "snippets" - ;; Tier 1: face - "face" - ;; Tier 2: core - "core" - ;; Tier 3: base editor modules - "buffer" "echo" "keymap" "repl" "shell-history" - "subprocess" "gsh-subprocess" "async" "chat" - "highlight" - ;; Tier 4: window system - "window" "modeline" "persist" - ;; Tier 5: org + shell - "org-parse" "gsh-eshell" "eshell" "shell" - "org-export" "org-highlight" "org-list" "org-table" - "org-clock" "org-babel" "org-capture" "org-agenda" - ;; Tier 6: helm + terminal - "helm" "terminal" - "helm-sources" "helm-tui" - ;; Tier 7: helm commands + editor extras - "helm-commands" "editor-extra-helpers" - ;; Tier 8: editor core - "editor-core" - ;; Tier 9: editor UI - "editor-ui" "editor-text" - ;; Tier 10: advanced editor - "editor-advanced" - ;; Tier 11-13: editor commands - "editor-cmds-a" "editor-cmds-b" "editor-cmds-c" - ;; Tier 14+: editor extras chain - "editor-extra-ai" - "editor-extra-editing" "editor-extra-editing2" - "editor-extra-media" "editor-extra-media2" - "editor-extra-modes" - "editor-extra-org" - "editor-extra-regs" "editor-extra-regs2" - "editor-extra-tools" "editor-extra-tools2" - "editor-extra-vcs" "editor-extra-web" - "editor-extra-final" "editor-extra" - ;; TUI top-level (editor shared with Qt) - "editor")) - ;; Qt-specific modules - (map (lambda (m) (format "lib/jerboa-emacs/qt/~a.so" m)) - '(;; Foundation - "sci-shim" "keymap")) - ;; treesitter must come before qt/buffer (which imports it) - (list "lib/jerboa-emacs/treesitter.so") - (map (lambda (m) (format "lib/jerboa-emacs/qt/~a.so" m)) - '("buffer" "echo" - "image" "magit" - "highlight" "modeline" "window" - "lsp-client" "helm-qt" - "snippets" "menubar" - ;; Commands (pairs: base + extended) - "commands-core" "commands-core2" - "commands-edit" "commands-edit2" - "commands-file" "commands-file2" - "commands-search" "commands-search2" - "commands-sexp" "commands-sexp2" - "commands-shell" "commands-shell2" - "commands-vcs" "commands-vcs2" - "commands-ide" "commands-ide2" - "commands-lsp" - "commands-modes" "commands-modes2" - "commands-parity" "commands-parity2" - "commands-parity3" "commands-parity3b" - "commands-parity4" "commands-parity5" - "commands-config" "commands-config2" - "commands-aliases" "commands-aliases2" - "commands" - ;; Qt app - "app" "main"))))) +(let ((boot-so-files (existing-so-files (unique-strings (wpo-missing-so-files))))) + (unless (null? boot-so-files) + (printf " Boot file includes ~a WPO-missing libraries:~n" (length boot-so-files)) + (for-each (lambda (path) (printf " ~a~n" path)) boot-so-files)) + (apply make-boot-file "jemacs-qt.boot" '("scheme" "petite") boot-so-files)) ;; --- Step 4: Generate C headers with embedded data --- (printf "[4/7] Embedding boot files + program as C headers...~n") @@ -436,7 +298,8 @@ (include-dir chez-dir) ;; Generate the C file by scanning ALL FFI source files: ;; chez-qt/ffi.ss, chez-pcre2/ffi.ss — specific files - ;; jsh-dir/, jerboa-dir/, lib/jerboa-emacs/ — recursive (catches all transitive deps) + ;; jsh-dir/, jerboa-dir/, chez-ssl-dir/src, lib/jerboa-emacs/ — recursive + ;; (catches all transitive deps) ;; Strip Scheme line comments (;; ...) before matching to avoid placeholder strings ;; like "c_name", "c_func", "c_function_name" that appear in macro doc comments. ;; Two patterns extracted: @@ -444,19 +307,20 @@ ;; define-foreign name "c-name" — jsh macro (C name is the second string) (gen-cmd (format - "{ { cat ~a ~a; find ~a ~a/jerboa ~a/std/os ~a/std/net ~a/std/crypto ~a/std/security ~a/chez-scintilla lib/jerboa-emacs lib/jerboa vendor -name '*.sls' -o -name '*.ss' | xargs cat 2>/dev/null; } | \ + "{ { cat ~a ~a; find ~a ~a/jerboa ~a/std/os ~a/std/net ~a/std/crypto ~a/std/security ~a/chez-scintilla ~a/src lib/jerboa-emacs lib/jerboa -name '*.sls' -o -name '*.ss' | xargs cat 2>/dev/null; } | \ sed 's/;;.*//' | grep -oE '(foreign-procedure|foreign-entry\\?) \"[^\"]*\"' | sed 's/.* \"//;s/\"//'; \ { cat ~a ~a; } | sed 's/;;.*//' | grep -o 'define-optional-ffi [^ ]* \"[^\"]*\"' | sed 's/.*define-optional-ffi [^ ]* \"//;s/\"//'; \ find ~a -name '*.sls' -o -name '*.ss' | \ xargs cat 2>/dev/null | tr '\\n' ' ' | \ grep -oE 'define-foreign [^ ]+ +\"[^\"]+\"' | \ sed 's/.*define-foreign [^ ]* *\"//;s/\".*//'; } | \ -sort -u | grep -v '^$' | grep -v '^_NSGetExecutablePath$' | grep -v '^io_uring_' | \ +sort -u | grep -v '^$' | grep -E '^[A-Za-z_][A-Za-z0-9_]*$' | grep -v '^_NSGetExecutablePath$' | grep -v '^io_uring_' | \ grep -v '^jerboa_' | grep -v '^SSL_' | grep -v '^TLS_' | grep -v '^EVP_' | \ grep -v '^CRYPTO_' | grep -v '^PKCS5_' | grep -v '^RAND_' | \ grep -v '^QRcode_' | grep -v '^embed_encrypt$' | grep -v '^embed_random_bytes$' | \ grep -v '^kqueue$' | grep -v '^kevent$' | grep -v '^sandbox_' | \ -grep -v '^__error$' > /tmp/ffi_syms.txt && \ +grep -v '^__error$' | grep -v '^__errno$' | grep -v '^cap_' | \ +grep -v '^host_statistics' | grep -v '^mach_' | grep -v '^sysctlbyname$' > /tmp/ffi_syms.txt && \ awk '\ BEGIN{ print \"/* Auto-generated — do not edit */\"; \ print \"#include \\\"scheme.h\\\"\"; print \"\"; } \ @@ -469,7 +333,7 @@ echo \"}\" >> qt_static_symbols.c && \ rm /tmp/ffi_syms.txt && \ echo OK" ffi-path pcre2-ffi-path - jsh-dir jerboa-dir jerboa-dir jerboa-dir jerboa-dir jerboa-dir sci-dir + jsh-dir jerboa-dir jerboa-dir jerboa-dir jerboa-dir jerboa-dir sci-dir chez-ssl-dir ffi-path pcre2-ffi-path jsh-dir)) (result (shell-output gen-cmd ""))) @@ -511,7 +375,7 @@ echo OK" (exit 1)))) ;; jsh coreutils stubs (jsh_* Rust uutils symbols — stubs for static binary) -;; The Rust libjsh_coreutils.a is not in the Docker image; these stubs allow linking. +;; The Rust libjsh_coreutils.a is not in the deps image; these stubs allow linking. ;; At runtime, in-process coreutils commands return an error; vterm PTY is unaffected. (when jemacs-static? (let* ((cmd "gcc -c -O2 -o jemacs-qt-jsh-coreutils-stubs.o support/jsh_coreutils_stubs.c -Wall 2>&1")) @@ -519,11 +383,16 @@ echo OK" (display "Error: jsh_coreutils_stubs.c compilation failed\n") (exit 1)))) -;; jsh embed-crypto (pure C crypto for embed encryption — no external deps) +;; jsh embed-crypto. Older jsh trees had embed-crypto.c; newer ones use +;; libjerboa_native. If neither is available, compile explicit failing stubs +;; so non-embed editor features still link and encrypted embed calls fail. (when (or jemacs-static? macos-build?) (let* ((jsh-root (path-parent jsh-dir)) - (cmd (format "gcc -c -O2 -o jemacs-qt-embed-crypto.o ~a/embed-crypto.c -I~a -Wall 2>&1" - jsh-root jsh-root))) + (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-qt-embed-crypto.o ~a -I~a -Wall 2>&1" + src jsh-root))) (unless (= 0 (system cmd)) (display "Error: embed-crypto.c compilation failed\n") (exit 1)))) @@ -681,7 +550,7 @@ grep -v '^$' | grep -v '^register_static_foreign_symbols$'") ;; --- Step 6: Link native binary --- (printf "[6/7] Linking native binary...~n") (if jemacs-static? - ;; ─── Static link (Docker musl build) ─────────────────────────────────── + ;; ─── Static link (Podman musl build) ─────────────────────────────────── ;; -static: fully static binary (musl embeds dynamic linker, dlopen works) ;; -Wl,--export-dynamic: export main binary symbols so the embedded .so ;; (loaded via Sscheme_script/dlopen from memfd) can find Chez kernel symbols --- a/build-binary.ss +++ b/build-binary.ss @@ -148,191 +148,76 @@ ;; --- Step 2: Whole-program optimization --- (printf "[2/6] Running whole-program optimization...~n") +(define wpo-missing-libraries '()) (let ((missing (compile-whole-program "main.wpo" "jemacs-all.so"))) + (set! wpo-missing-libraries missing) (unless (null? missing) (printf " WPO: ~a libraries not incorporated (missing .wpo):~n" (length missing)) (for-each (lambda (lib) (printf " ~a~n" lib)) missing))) ;; --- Step 3: Make libs-only boot file --- (printf "[3/6] Creating libs-only boot file...~n") +(define (symbol-path parts) + (let loop ((rest parts) (acc "")) + (cond + ((null? rest) acc) + ((string=? acc "") + (loop (cdr rest) (symbol->string (car rest)))) + (else + (loop (cdr rest) (string-append acc "/" (symbol->string (car rest)))))))) + +(define (library-ref->so-path lib) + (and (pair? lib) + (let ((head (car lib)) + (tail (cdr lib))) + (case head + ((std) + (format "~a/std/~a.so" jerboa-dir (symbol-path tail))) + ((jerboa) + (if (and (pair? tail) (eq? (car tail) 'repl-socket)) + "lib/jerboa/repl-socket.so" + (format "~a/jerboa/~a.so" jerboa-dir (symbol-path tail)))) + ((jsh) + (format "~a/jsh/~a.so" jsh-dir (symbol-path tail))) + ((compat) + (if (and (pair? tail) (eq? (car tail) 'gambit)) + (format "~a/compat/gambit.so" jsh-dir) + (format "~a/compat/~a.so" gherkin-dir (symbol-path tail)))) + ((runtime) + (format "~a/runtime/~a.so" gherkin-dir (symbol-path tail))) + ((chez-pcre2) + (format "~a/chez-pcre2/~a.so" pcre2-dir (symbol-path tail))) + ((chez-scintilla) + (format "~a/chez-scintilla/~a.so" sci-dir (symbol-path tail))) + ((chez-qt) + (format "~a/chez-qt/~a.so" qt-dir (symbol-path tail))) + ((chez-ssl) + (format "~a/src/chez-ssl.so" chez-ssl-dir)) + ((chez-https) + (format "~a/chez-https.so" chez-https-dir)) + ((jerboa-aws) + (format "~a/jerboa-aws/~a.so" jaws-dir (symbol-path tail))) + ((jerboa-emacs) + (format "lib/jerboa-emacs/~a.so" (symbol-path tail))) + (else #f))))) + +(define (wpo-missing-so-files) + (filter values (map library-ref->so-path wpo-missing-libraries))) + +(define (unique-strings strings) + (let loop ((rest strings) (seen '()) (acc '())) + (cond + ((null? rest) (reverse acc)) + ((member (car rest) seen) (loop (cdr rest) seen acc)) + (else (loop (cdr rest) (cons (car rest) seen) (cons (car rest) acc)))))) + (define (existing-so-files paths) (filter file-exists? paths)) -(apply make-boot-file "jemacs.boot" '("scheme" "petite") - (existing-so-files - (append - ;; Jerboa runtime (no deps on other jerboa libs) - (map (lambda (m) (format "~a/~a.so" jerboa-dir m)) - '("jerboa/runtime")) - ;; Jerboa stdlib — include all available .so modules (existing-so-files filters missing ones) - (map (lambda (m) (format "~a/~a.so" jerboa-dir m)) - '("std/error" - "std/format" - "std/sort" - "std/pregexp" - "std/foreign" - "std/iter" - "std/log"