updates
ober
3aa663ed0d6b3daaaf4700e7bf36ad39a459a9b3
new file mode 100644 --- /dev/null +++ b/.containerignore @@ -0,0 +1,18 @@ +# Compiled Chez Scheme artifacts — must be rebuilt from source inside the +# image so they match the in-image Chez (10.4-pre-release) and not whatever +# version happened to be on the host. Otherwise stale .so files baked from a +# previous source revision can mask source changes (e.g. an env-var rename +# that's already applied to .sls files but not yet recompiled into .so). +*.so +*.wpo + +# Build artifacts and caches that shouldn't be copied into the image +target/ +.cargo/ +*.log +*.tmp + +# VCS metadata (Containerfile uses COPY of specific paths, not .git, but be +# explicit so a future global COPY doesn't pull it in) +.git/ +.gitignore deleted file mode 100644 --- a/.dockerignore +++ /dev/null @@ -1,18 +0,0 @@ -# Compiled Chez Scheme artifacts — must be rebuilt from source inside the -# image so they match the in-image Chez (10.4-pre-release) and not whatever -# version happened to be on the host. Otherwise stale .so files baked from a -# previous source revision can mask source changes (e.g. an env-var rename -# that's already applied to .sls files but not yet recompiled into .so). -*.so -*.wpo - -# Build artifacts and caches that shouldn't be copied into the image -target/ -.cargo/ -*.log -*.tmp - -# VCS metadata (Dockerfile uses COPY of specific paths, not .git, but be -# explicit so a future global COPY doesn't pull it in) -.git/ -.gitignore --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,7 +10,7 @@ on: - cron: '23 9 * * *' env: - IMAGE: jerboa21/jerboa + IMAGE: docker.io/jerboa21/jerboa jobs: build-and-test: @@ -18,8 +18,6 @@ jobs: steps: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - - uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0 - - name: Verify immutable container inputs id: container-lock run: | @@ -27,19 +25,14 @@ jobs: echo "base_image=$(support/container-inputs.sh field ubuntu-24.04 3)" >> "$GITHUB_OUTPUT" - name: Build base image (loaded locally) - uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5.4.0 - with: - context: . - build-args: JERBOA_BASE_IMAGE=${{ steps.container-lock.outputs.base_image }} - platforms: linux/amd64 - tags: ${{ env.IMAGE }}:ci - load: true - cache-from: type=gha - cache-to: type=gha,mode=max + run: | + podman build --platform linux/amd64 -f Containerfile \ + --build-arg JERBOA_BASE_IMAGE="${{ steps.container-lock.outputs.base_image }}" \ + -t "${{ env.IMAGE }}:ci" . - name: Run core tests run: | - docker run --rm \ + podman run --rm \ -v "${{ github.workspace }}:/workspace" -w /workspace \ -e JERBOA=/workspace/lib -e JERBOA_HOME=/workspace \ ${{ env.IMAGE }}:ci \ @@ -47,7 +40,7 @@ jobs: - name: Build libraries run: | - docker run --rm \ + podman run --rm \ -v "${{ github.workspace }}:/workspace" -w /workspace \ -e JERBOA=/workspace/lib -e JERBOA_HOME=/workspace \ ${{ env.IMAGE }}:ci \ @@ -55,7 +48,7 @@ jobs: - name: Run production security audit run: | - docker run --rm \ + podman run --rm \ -v "${{ github.workspace }}:/workspace" -w /workspace \ -e JERBOA=/workspace/lib -e JERBOA_HOME=/workspace \ ${{ env.IMAGE }}:ci \ @@ -64,7 +57,7 @@ jobs: - name: Run fuzz smoke timeout-minutes: 15 run: | - docker run --rm \ + podman run --rm \ -v "${{ github.workspace }}:/workspace" -w /workspace \ -e JERBOA=/workspace/lib -e JERBOA_HOME=/workspace \ ${{ env.IMAGE }}:ci \ @@ -74,7 +67,7 @@ jobs: if: github.event_name == 'schedule' timeout-minutes: 60 run: | - docker run --rm \ + podman run --rm \ -v "${{ github.workspace }}:/workspace" -w /workspace \ -e JERBOA=/workspace/lib -e JERBOA_HOME=/workspace \ ${{ env.IMAGE }}:ci \ @@ -84,7 +77,7 @@ jobs: continue-on-error: true timeout-minutes: 10 run: | - docker run --rm \ + podman run --rm \ -v "${{ github.workspace }}:/workspace" -w /workspace \ -e JERBOA=/workspace/lib -e JERBOA_HOME=/workspace \ ${{ env.IMAGE }}:ci \ @@ -96,7 +89,7 @@ jobs: continue-on-error: true timeout-minutes: 10 run: | - docker run --rm \ + podman run --rm \ -v "${{ github.workspace }}:/workspace" -w /workspace \ -e JERBOA=/workspace/lib -e JERBOA_HOME=/workspace \ ${{ env.IMAGE }}:ci \ @@ -106,7 +99,7 @@ jobs: continue-on-error: true timeout-minutes: 15 run: | - docker run --rm \ + podman run --rm \ -v "${{ github.workspace }}:/workspace" -w /workspace \ -e JERBOA=/workspace/lib -e JERBOA_HOME=/workspace \ ${{ env.IMAGE }}:ci \ @@ -119,29 +112,23 @@ jobs: steps: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - - uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0 - - name: Verify immutable container inputs id: container-lock run: | support/container-inputs.sh check echo "base_image=$(support/container-inputs.sh field ubuntu-24.04 3)" >> "$GITHUB_OUTPUT" - - name: Login to Docker Hub - uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Login to container registry + run: | + podman login docker.io \ + --username "${{ secrets.REGISTRY_USERNAME }}" \ + --password-stdin <<< "${{ secrets.REGISTRY_TOKEN }}" - name: Build and push (latest + sha) - uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5.4.0 - with: - context: . - build-args: JERBOA_BASE_IMAGE=${{ steps.container-lock.outputs.base_image }} - platforms: linux/amd64 - tags: | - ${{ env.IMAGE }}:latest - ${{ env.IMAGE }}:${{ github.sha }} - push: true - cache-from: type=gha - cache-to: type=gha,mode=max + run: | + podman build --platform linux/amd64 -f Containerfile \ + --build-arg JERBOA_BASE_IMAGE="${{ steps.container-lock.outputs.base_image }}" \ + -t "${{ env.IMAGE }}:latest" \ + -t "${{ env.IMAGE }}:${{ github.sha }}" . + podman push "${{ env.IMAGE }}:latest" + podman push "${{ env.IMAGE }}:${{ github.sha }}" --- a/AGENTS.md +++ b/AGENTS.md @@ -414,8 +414,8 @@ Run `jerboa_stale_static` to detect stale `.so` files before debugging "why does **ALWAYS** run a clean build **before** committing any code to this repository. Pick the right target for the *current* platform: -- **Linux**: run `make docker-build` — the Docker image must build cleanly against the full musl-static release pipeline. -- **macOS / FreeBSD / other**: run `make binary` — the native local build must succeed. Do **not** run `make docker-build` here; Docker on non-Linux hosts is slow and not the canonical pipeline for those platforms. +- **Linux**: run `make podman-build` — the Podman image must build cleanly against the full musl-static release pipeline. +- **macOS / FreeBSD / other**: run `make binary` — the native local build must succeed. Do **not** run `make podman-build` here; Podman on non-Linux hosts is slow and not the canonical pipeline for those platforms. Do not commit if the build fails. --- a/AGENTS.md.example +++ b/AGENTS.md.example @@ -64,7 +64,7 @@ The Makefile must provide these targets: - `make freebsd-amd64` cross-builds the FreeBSD amd64 binary from the current host. The cross-build targets must use the local cross toolchains and Jerboa/Chez -cross-build setup. Never use Docker or Podman for building, testing, smoke +cross-build setup. Never use container engines for building, testing, smoke testing, packaging, or verifying these targets. ## Required Verification @@ -88,4 +88,4 @@ dependency instead of committing or pushing partially verified code. - Keep changes inside the current repository unless the user explicitly names another path. - Preserve the target semantics above when editing the Makefile. - Treat the cross-build targets as release-critical, not optional follow-up work. -- Do not add Dockerfiles, container scripts, Podman invocations, or container-based verification paths. +- Do not add Containerfiles, container scripts, Podman invocations, or container-based verification paths. new file mode 100644 --- /dev/null +++ b/Containerfile @@ -0,0 +1,217 @@ +# Containerfile — jerboa21/jerboa base image for static binary builds +# +# Provides: +# - Chez Scheme (glibc) at /usr/local — built from the vendored vendor/ChezScheme +# - Musl Chez Scheme (static) at /build/chez-musl — for linking, same source +# - Jerboa library source at /build/mine/jerboa/lib +# - jerboa-native-rs source + pre-built libjerboa_native.a (musl) +# - Rust toolchain with x86_64-unknown-linux-musl target +# - All common dependency repos cloned under /build/mine/ +# - musl-gcc, build-essential, and all linking deps pre-installed +# - TUI deps: libvterm, libpcre2, pre-built Scintilla/Lexilla/Termbox archives +# - jerboa-scintilla, jerboa-pcre2 repos +# +# Downstream projects use this as their FROM image to skip the expensive +# Chez double-build, Rust toolchain install, and repo cloning. +# +# Build & push: +# make podman-build +# make podman-push +# +# Or manually: +# podman build --platform linux/amd64 -t docker.io/jerboa21/jerboa . +# podman push docker.io/jerboa21/jerboa + +ARG JERBOA_BASE_IMAGE +FROM ${JERBOA_BASE_IMAGE} + +ARG JERBOA_BASE_IMAGE + +# The base reference is deliberately supplied by the consumer-controlled lock +# rather than defaulting to a mutable tag. Direct builds without an immutable +# reference fail while resolving FROM; a substituted tag is rejected here. +COPY support/container-inputs.sh support/container-dependencies.lock /tmp/jerboa-container/ +ENV JERBOA_CONTAINER_LOCK=/tmp/jerboa-container/container-dependencies.lock +RUN /tmp/jerboa-container/container-inputs.sh check-base "$JERBOA_BASE_IMAGE" && \ + /tmp/jerboa-container/container-inputs.sh check +LABEL org.opencontainers.image.base.name="$JERBOA_BASE_IMAGE" + +ARG DEBIAN_FRONTEND=noninteractive + +# ── System dependencies for static builds ──────────────────────────────────── +RUN apt-get update && \ + apt-get install -y --no-install-recommends ca-certificates && \ + rm -rf /var/lib/apt/lists/* && \ + locked_snapshot=$(/tmp/jerboa-container/container-inputs.sh field ubuntu-noble 3) && \ + snapshot="http://${locked_snapshot#https://}" && \ + rm -f /etc/apt/sources.list /etc/apt/sources.list.d/ubuntu.sources && \ + { \ + echo "deb [check-valid-until=no] $snapshot noble main restricted universe multiverse"; \ + echo "deb [check-valid-until=no] $snapshot noble-updates main restricted universe multiverse"; \ + echo "deb [check-valid-until=no] $snapshot noble-security main restricted universe multiverse"; \ + } > /etc/apt/sources.list.d/jerboa-snapshot.list && \ + apt-get update && apt-get install -y --no-install-recommends \ + build-essential \ + musl-tools \ + musl-dev \ + git \ + openssh-client \ + ca-certificates \ + curl \ + libncurses-dev \ + uuid-dev \ + liblz4-dev \ + zlib1g-dev \ + libsqlite3-dev \ + pkg-config \ + file \ + && rm -rf /var/lib/apt/lists/* + +# musl-tools only provides musl-gcc; Rust cc-rs needs musl-g++ for C++ deps. +# Use system g++ for C++ compilation (it has <sstream> etc. that musl-gcc lacks). +RUN printf '#!/bin/sh\nexec /usr/bin/g++ -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0 "$@"\n' \ + > /usr/local/bin/x86_64-linux-musl-g++ && \ + chmod +x /usr/local/bin/x86_64-linux-musl-g++ && \ + ln -sf /usr/local/bin/x86_64-linux-musl-g++ /usr/local/bin/musl-g++ + +# ── Rust toolchain ──────────────────────────────────────────────────────────── +RUN /tmp/jerboa-container/container-inputs.sh fetch rustup-installer /tmp/rustup-init && \ + rust_version=$(/tmp/jerboa-container/container-inputs.sh field rust 4) && \ + audit_version=$(/tmp/jerboa-container/container-inputs.sh field cargo-audit 4) && \ + chmod 0755 /tmp/rustup-init && \ + /tmp/rustup-init -y --default-toolchain "$rust_version" --profile minimal && \ + rm -f /tmp/rustup-init && \ + . /root/.cargo/env && \ + rustup target add --toolchain "$rust_version" x86_64-unknown-linux-musl && \ + cargo install cargo-audit --version "=$audit_version" --locked + +ENV PATH="/root/.cargo/bin:${PATH}" +ENV RUSTUP_HOME="/root/.rustup" + +# Set HOME=/build so no real usernames or home directories leak into binaries +ENV HOME=/build +WORKDIR /build + +# ── Vendored Chez Scheme source (merged into the jerboa repo) ──────────────── +# Copied from vendor/ChezScheme in the build context (the jerboa repo root), so +# the image always tracks the in-repo Chez instead of an external fork. +COPY vendor/ChezScheme /build/chez-src + +# ── Build Chez Scheme (glibc, for compilation steps) ───────────────────────── +# Installed to /usr/local so `scheme` is on PATH +RUN cp -a /build/chez-src /build/ChezScheme && cd /build/ChezScheme && \ + ./configure --threads --enable-harden --disable-x11 --installprefix=/usr/local && \ + make -j$(nproc) && \ + make install && \ + cd /build && rm -rf /build/ChezScheme + +# ── Build Chez Scheme (musl, for static linking) ──────────────────────────── +# Two-pass build: +# Pass 1: Full build with stock gcc to generate boot files +# Pass 2: Rebuild kernel only with musl-gcc --static, reusing boot files +# Installed to /build/chez-musl +RUN cp -a /build/chez-src /build/chez-musl-src && cd /build/chez-musl-src && \ + ./configure --threads --enable-harden --disable-x11 --installprefix=/build/chez-musl && \ + make -j$(nproc) && \ + cp ta6le/boot/ta6le/petite.boot /tmp/petite.boot && \ + cp ta6le/boot/ta6le/scheme.boot /tmp/scheme.boot && \ + make clean && \ + ./configure --threads --enable-harden --disable-x11 --static CC=musl-gcc --installprefix=/build/chez-musl && \ + mkdir -p ta6le/boot/ta6le && \ + cp /tmp/petite.boot ta6le/boot/ta6le/ && \ + cp /tmp/scheme.boot ta6le/boot/ta6le/ && \ + make -j$(nproc) kernel && \ + make install && \ + cd /build && rm -rf chez-musl-src /tmp/petite.boot /tmp/scheme.boot + +# ── Copy Jerboa library + native Rust source ────────────────────────────────── +WORKDIR /build/mine +COPY jerbuild.ss /build/mine/jerboa/jerbuild.ss +COPY lib /build/mine/jerboa/lib +COPY support /build/mine/jerboa/support +COPY jerboa-native-rs /build/mine/jerboa/jerboa-native-rs + +# ── Pre-build libjerboa_native.a (musl, no duckdb) ─────────────────────────── +# Warms the Cargo registry cache under /build/.cargo so downstream builds that +# patch regex_native.rs only need to recompile that one module, not fetch crates. +# Uses CARGO_HOME=/build/.cargo so no /root/.cargo paths leak into the .a. +RUN cd /build/mine/jerboa/jerboa-native-rs && \ + grep -q '#\[cfg(feature = "duckdb")\]' src/lib.rs || \ + sed -i 's/^mod duckdb_native;/#[cfg(feature = "duckdb")]\nmod duckdb_native;/' src/lib.rs && \ + CARGO_HOME=/build/.cargo \ + RUSTFLAGS="--remap-path-prefix /build/.cargo/registry/src=crate --remap-path-prefix /build/mine=src" \ + cargo build --locked --release --target x86_64-unknown-linux-musl --no-default-features && \ + strip -S target/x86_64-unknown-linux-musl/release/libjerboa_native.a + +# ── Materialize pinned common dependency repos ─────────────────────────────── +RUN for name in \ + jerboa-ssh jerboa-sqlite jerboa-crypto jerboa-ssl jerboa-https \ + jerboa-awk jerboa-sed jerboa-aws jerboa-fuse jerboa-scintilla \ + jerboa-pcre2; do \ + /tmp/jerboa-container/container-inputs.sh fetch-git "$name"; \ + done + +# ── TUI dependencies: libvterm, libpcre2, ncurses (static) ───────────────── +RUN apt-get update && apt-get install -y --no-install-recommends \ + libvterm-dev \ + libpcre2-dev \ + && rm -rf /var/lib/apt/lists/* + +# ── Build Scintilla + Lexilla + Termbox static archives from source ──────── +# These are needed by jerboa-emacs TUI for the embedded terminal editor. +# Layout: sci-vendor/scintilla/ (stock Scintilla + termbox backend inside) +# sci-vendor/lexilla/ (Lexilla from scintilla.org) +# 1. Download stock Scintilla + Lexilla tarballs +# 2. Clone scintilla-termbox backend into scintilla/termbox/ +# 3. Clone termbox_next into scintilla/termbox/termbox_next/ +# 4. Build all three static archives +RUN mkdir -p /build/sci-vendor && \ + /tmp/jerboa-container/container-inputs.sh extract-tgz scintilla && \ + /tmp/jerboa-container/container-inputs.sh extract-tgz lexilla && \ + /tmp/jerboa-container/container-inputs.sh fetch-git scintilla-termbox && \ + /tmp/jerboa-container/container-inputs.sh fetch-git termbox-next && \ + cd /build/sci-vendor/scintilla/termbox/termbox_next && make -j$(nproc) && \ + cd /build/sci-vendor/scintilla/termbox && make -j$(nproc) && \ + cd /build/sci-vendor/lexilla/src && make -j$(nproc) && \ + echo "Scintilla/Lexilla/Termbox static archives built" + +# ── Set default environment for downstream builds ─────────────────────────── +ENV JERBOA_MUSL_CHEZ_PREFIX=/build/chez-musl +ENV JERBOA_HOME=/build/mine/jerboa +ENV JERBOA=/build/mine/jerboa/lib +ENV AWK_DIR=/build/mine/jerboa-awk/lib +ENV SED_DIR=/build/mine/jerboa-sed/lib +ENV AWS_DIR=/build/mine/jerboa-aws/lib +ENV JERBOA_FUSE_DIR=/build/mine/jerboa-fuse/lib +ENV JERBOA_SCINTILLA_DIR=/build/mine/jerboa-scintilla/src +ENV JERBOA_PCRE2_DIR=/build/mine/jerboa-pcre2 +ENV SCI_VENDOR_DIR=/build/sci-vendor + +# Retain the resolved non-Cargo graph in the image itself. The checked lock +# captures remote identity; dpkg/toolchain records capture what the snapshot +# resolver and compilers actually selected. +RUN mkdir -p /usr/local/share/jerboa/build-graph && \ + cp /tmp/jerboa-container/container-dependencies.lock \ + /usr/local/share/jerboa/build-graph/container-dependencies.lock && \ + dpkg-query -W -f='${binary:Package}\t${Version}\n' \ + | LC_ALL=C sort > /usr/local/share/jerboa/build-graph/debian-packages.tsv && \ + { \ + rustc --version; \ + cargo --version; \ + scheme --version; \ + musl-gcc --version | head -1; \ + } > /usr/local/share/jerboa/build-graph/toolchains.txt 2>&1 + +# ── Smoke test ─────────────────────────────────────────────────────────────── +RUN scheme --version && \ + musl-gcc --version | head -1 && \ + cargo --version && \ + test -d /build/chez-musl && \ + test -f /build/mine/jerboa/jerboa-native-rs/target/x86_64-unknown-linux-musl/release/libjerboa_native.a && \ + test -f /build/sci-vendor/scintilla/bin/scintilla.a && \ + test -f /build/sci-vendor/lexilla/bin/liblexilla.a && \ + test -f /build/sci-vendor/scintilla/termbox/termbox_next/bin/termbox.a && \ + echo "jerboa21/jerboa base image ready (with TUI deps)" + +WORKDIR /build +CMD ["/bin/bash"] deleted file mode 100644 --- a/Dockerfile +++ /dev/null @@ -1,213 +0,0 @@ -# Dockerfile — jerboa21/jerboa base image for static binary builds -# -# Provides: -# - Chez Scheme (glibc) at /usr/local — built from the vendored vendor/ChezScheme -# - Musl Chez Scheme (static) at /build/chez-musl — for linking, same source -# - Jerboa library source at /build/mine/jerboa/lib -# - jerboa-native-rs source + pre-built libjerboa_native.a (musl) -# - Rust toolchain with x86_64-unknown-linux-musl target -# - All common dependency repos cloned under /build/mine/ -# - musl-gcc, build-essential, and all linking deps pre-installed -# - TUI deps: libvterm, libpcre2, pre-built Scintilla/Lexilla/Termbox archives -# - jerboa-scintilla, jerboa-pcre2 repos -# -# Downstream projects use this as their FROM image to skip the expensive -# Chez double-build, Rust toolchain install, and repo cloning. -# -# Build & push: -# make docker-build -# make docker-push -# -# Or manually: -# docker build --platform linux/amd64 -t jerboa21/jerboa . -# docker push jerboa21/jerboa - -ARG JERBOA_BASE_IMAGE -FROM ${JERBOA_BASE_IMAGE} - -ARG JERBOA_BASE_IMAGE - -# The base reference is deliberately supplied by the consumer-controlled lock -# rather than defaulting to a mutable tag. Direct builds without an immutable -# reference fail while resolving FROM; a substituted tag is rejected here. -COPY support/container-inputs.sh support/container-dependencies.lock /tmp/jerboa-container/ -ENV JERBOA_CONTAINER_LOCK=/tmp/jerboa-container/container-dependencies.lock -RUN /tmp/jerboa-container/container-inputs.sh check-base "$JERBOA_BASE_IMAGE" && \ - /tmp/jerboa-container/container-inputs.sh check -LABEL org.opencontainers.image.base.name="$JERBOA_BASE_IMAGE" - -ARG DEBIAN_FRONTEND=noninteractive - -# ── System dependencies for static builds ──────────────────────────────────── -RUN snapshot=$(/tmp/jerboa-container/container-inputs.sh field ubuntu-noble 3) && \ - rm -f /etc/apt/sources.list /etc/apt/sources.list.d/ubuntu.sources && \ - { \ - echo "deb [check-valid-until=no] $snapshot noble main restricted universe multiverse"; \ - echo "deb [check-valid-until=no] $snapshot noble-updates main restricted universe multiverse"; \ - echo "deb [check-valid-until=no] $snapshot noble-security main restricted universe multiverse"; \ - } > /etc/apt/sources.list.d/jerboa-snapshot.list && \ - apt-get update && apt-get install -y --no-install-recommends \ - build-essential \ - musl-tools \ - musl-dev \ - git \ - openssh-client \ - ca-certificates \ - curl \ - libncurses-dev \ - uuid-dev \ - liblz4-dev \ - zlib1g-dev \ - libsqlite3-dev \ - pkg-config \ - file \ - && rm -rf /var/lib/apt/lists/* - -# musl-tools only provides musl-gcc; Rust cc-rs needs musl-g++ for C++ deps. -# Use system g++ for C++ compilation (it has <sstream> etc. that musl-gcc lacks). -RUN printf '#!/bin/sh\nexec /usr/bin/g++ -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0 "$@"\n' \ - > /usr/local/bin/x86_64-linux-musl-g++ && \ - chmod +x /usr/local/bin/x86_64-linux-musl-g++ && \ - ln -sf /usr/local/bin/x86_64-linux-musl-g++ /usr/local/bin/musl-g++ - -# ── Rust toolchain ──────────────────────────────────────────────────────────── -RUN /tmp/jerboa-container/container-inputs.sh fetch rustup-installer /tmp/rustup-init && \ - rust_version=$(/tmp/jerboa-container/container-inputs.sh field rust 4) && \ - audit_version=$(/tmp/jerboa-container/container-inputs.sh field cargo-audit 4) && \ - chmod 0755 /tmp/rustup-init && \ - /tmp/rustup-init -y --default-toolchain "$rust_version" --profile minimal && \ - rm -f /tmp/rustup-init && \ - . /root/.cargo/env && \ - rustup target add --toolchain "$rust_version" x86_64-unknown-linux-musl && \ - cargo install cargo-audit --version "=$audit_version" --locked - -ENV PATH="/root/.cargo/bin:${PATH}" -ENV RUSTUP_HOME="/root/.rustup" - -# Set HOME=/build so no real usernames or home directories leak into binaries -ENV HOME=/build -WORKDIR /build - -# ── Vendored Chez Scheme source (merged into the jerboa repo) ──────────────── -# Copied from vendor/ChezScheme in the build context (the jerboa repo root), so -# the image always tracks the in-repo Chez instead of an external fork. -COPY vendor/ChezScheme /build/chez-src - -# ── Build Chez Scheme (glibc, for compilation steps) ───────────────────────── -# Installed to /usr/local so `scheme` is on PATH -RUN cp -a /build/chez-src /build/ChezScheme && cd /build/ChezScheme && \ - ./configure --threads --enable-harden --disable-x11 --installprefix=/usr/local && \ - make -j$(nproc) && \ - make install && \ - cd /build && rm -rf /build/ChezScheme - -# ── Build Chez Scheme (musl, for static linking) ──────────────────────────── -# Two-pass build: -# Pass 1: Full build with stock gcc to generate boot files -# Pass 2: Rebuild kernel only with musl-gcc --static, reusing boot files -# Installed to /build/chez-musl -RUN cp -a /build/chez-src /build/chez-musl-src && cd /build/chez-musl-src && \ - ./configure --threads --enable-harden --disable-x11 --installprefix=/build/chez-musl && \ - make -j$(nproc) && \ - cp ta6le/boot/ta6le/petite.boot /tmp/petite.boot && \ - cp ta6le/boot/ta6le/scheme.boot /tmp/scheme.boot && \ - make clean && \ - ./configure --threads --enable-harden --disable-x11 --static CC=musl-gcc --installprefix=/build/chez-musl && \ - mkdir -p ta6le/boot/ta6le && \ - cp /tmp/petite.boot ta6le/boot/ta6le/ && \ - cp /tmp/scheme.boot ta6le/boot/ta6le/ && \ - make -j$(nproc) kernel && \ - make install && \ - cd /build && rm -rf chez-musl-src /tmp/petite.boot /tmp/scheme.boot - -# ── Copy Jerboa library + native Rust source ────────────────────────────────── -WORKDIR /build/mine -COPY jerbuild.ss /build/mine/jerboa/jerbuild.ss -COPY lib /build/mine/jerboa/lib -COPY support /build/mine/jerboa/support -COPY jerboa-native-rs /build/mine/jerboa/jerboa-native-rs - -# ── Pre-build libjerboa_native.a (musl, no duckdb) ─────────────────────────── -# Warms the Cargo registry cache under /build/.cargo so downstream builds that -# patch regex_native.rs only need to recompile that one module, not fetch crates. -# Uses CARGO_HOME=/build/.cargo so no /root/.cargo paths leak into the .a. -RUN cd /build/mine/jerboa/jerboa-native-rs && \ - grep -q '#\[cfg(feature = "duckdb")\]' src/lib.rs || \ - sed -i 's/^mod duckdb_native;/#[cfg(feature = "duckdb")]\nmod duckdb_native;/' src/lib.rs && \ - CARGO_HOME=/build/.cargo \ - RUSTFLAGS="--remap-path-prefix /build/.cargo/registry/src=crate --remap-path-prefix /build/mine=src" \ - cargo build --locked --release --target x86_64-unknown-linux-musl --no-default-features && \ - strip -S target/x86_64-unknown-linux-musl/release/libjerboa_native.a - -# ── Materialize pinned common dependency repos ─────────────────────────────── -RUN for name in \ - jerboa-ssh jerboa-sqlite jerboa-crypto jerboa-ssl jerboa-https \ - jerboa-awk jerboa-sed jerboa-aws jerboa-fuse jerboa-scintilla \ - jerboa-pcre2; do \ - /tmp/jerboa-container/container-inputs.sh fetch-git "$name"; \ - done - -# ── TUI dependencies: libvterm, libpcre2, ncurses (static) ───────────────── -RUN apt-get update && apt-get install -y --no-install-recommends \ - libvterm-dev \ - libpcre2-dev \ - && rm -rf /var/lib/apt/lists/* - -# ── Build Scintilla + Lexilla + Termbox static archives from source ──────── -# These are needed by jerboa-emacs TUI for the embedded terminal editor. -# Layout: sci-vendor/scintilla/ (stock Scintilla + termbox backend inside) -# sci-vendor/lexilla/ (Lexilla from scintilla.org) -# 1. Download stock Scintilla + Lexilla tarballs -# 2. Clone scintilla-termbox backend into scintilla/termbox/ -# 3. Clone termbox_next into scintilla/termbox/termbox_next/ -# 4. Build all three static archives -RUN mkdir -p /build/sci-vendor && \ - /tmp/jerboa-container/container-inputs.sh extract-tgz scintilla && \ - /tmp/jerboa-container/container-inputs.sh extract-tgz lexilla && \ - /tmp/jerboa-container/container-inputs.sh fetch-git scintilla-termbox && \ - /tmp/jerboa-container/container-inputs.sh fetch-git termbox-next && \ - cd /build/sci-vendor/scintilla/termbox/termbox_next && make -j$(nproc) && \ - cd /build/sci-vendor/scintilla/termbox && make -j$(nproc) && \ - cd /build/sci-vendor/lexilla/src && make -j$(nproc) && \ - echo "Scintilla/Lexilla/Termbox static archives built" - -# ── Set default environment for downstream builds ─────────────────────────── -ENV JERBOA_MUSL_CHEZ_PREFIX=/build/chez-musl -ENV JERBOA_HOME=/build/mine/jerboa -ENV JERBOA=/build/mine/jerboa/lib -ENV AWK_DIR=/build/mine/jerboa-awk/lib -ENV SED_DIR=/build/mine/jerboa-sed/lib -ENV AWS_DIR=/build/mine/jerboa-aws/lib -ENV JERBOA_FUSE_DIR=/build/mine/jerboa-fuse/lib -ENV JERBOA_SCINTILLA_DIR=/build/mine/jerboa-scintilla/src -ENV JERBOA_PCRE2_DIR=/build/mine/jerboa-pcre2 -ENV SCI_VENDOR_DIR=/build/sci-vendor - -# Retain the resolved non-Cargo graph in the image itself. The checked lock -# captures remote identity; dpkg/toolchain records capture what the snapshot -# resolver and compilers actually selected. -RUN mkdir -p /usr/local/share/jerboa/build-graph && \ - cp /tmp/jerboa-container/container-dependencies.lock \ - /usr/local/share/jerboa/build-graph/container-dependencies.lock && \ - dpkg-query -W -f='${binary:Package}\t${Version}\n' \ - | LC_ALL=C sort > /usr/local/share/jerboa/build-graph/debian-packages.tsv && \ - { \ - rustc --version; \ - cargo --version; \ - scheme --version; \ - musl-gcc --version | head -1; \ - } > /usr/local/share/jerboa/build-graph/toolchains.txt 2>&1 - -# ── Smoke test ─────────────────────────────────────────────────────────────── -RUN scheme --version && \ - musl-gcc --version | head -1 && \ - cargo --version && \ - test -d /build/chez-musl && \ - test -f /build/mine/jerboa/jerboa-native-rs/target/x86_64-unknown-linux-musl/release/libjerboa_native.a && \ - test -f /build/sci-vendor/scintilla/bin/scintilla.a && \ - test -f /build/sci-vendor/lexilla/bin/liblexilla.a && \ - test -f /build/sci-vendor/scintilla/termbox/termbox_next/bin/termbox.a && \ - echo "jerboa21/jerboa base image ready (with TUI deps)" - -WORKDIR /build -CMD ["/bin/bash"] --- a/Makefile +++ b/Makefile @@ -293,8 +293,8 @@ LLVM_BIN ?= $(shell if command -v llvm-as >/dev/null 2>&1; then dirname "$$(comm TYPED_WRAPPER_DIR ?= build/typed/jerboa .PHONY: typed-llvmir-focused-parity-suite typed-llvmir-bytes-parity typed-llvmir-for-parity typed-llvmir-list-parity typed-llvmir-map-parity typed-llvmir-pair-parity typed-llvmir-nullable-parity typed-llvmir-hashmap-empty-parity typed-llvmir-hashmap-single-parity typed-llvmir-hashmap-fold-parity typed-llvmir-hashmap-multi-parity typed-llvmir-regex-parity typed-llvmir-unicode-string-parity -.PHONY: help chez static-supported-check chez-cross build binary binary-typed binary-typed-smoke binary-typed-uri-smoke binary-typed-json-smoke binary-cross native-cross pure-audit typecheck typed-rust typed-rust-focused-smoke-suite typed-rust-crate-metadata-smoke typed-rust-hashmap-smoke typed-rust-list-smoke typed-rust-map-smoke typed-rust-set-smoke typed-rust-mutable-list-smoke typed-rust-pair-smoke typed-rust-nullable-smoke typed-rust-string-ops-smoke typed-rust-jvm-helpers-smoke typed-rust-jvm-arrays-smoke typed-rust-jvm-json-smoke typed-rust-try-throw-smoke typed-rust-direct-throw-smoke typed-json-value-smoke typed-json-value-corpus-check typed-json-value-diff typed-json-value-diff-repro typed-json-value-bench typed-json-value-public-smoke typed-json-scan-corpus-check typed-bench typed-uri-pilot typed-uri-corpus-check typed-uri-diff typed-uri-diff-repro typed-uri-bench typed-uri-wrapper-smoke typed-uri-public-smoke typed-json-scan-diff typed-json-scan-bench typed-llvmir typed-llvmir-check typed-llvmir-leak-check typed-llvmir-leak-suite typed-llvmir-wasm-object-smoke typed-llvmir-wasm-runtime-smoke typed-llvmir-wasm-browser-smoke typed-llvmir-wasm-suite typed-llvmir-wasm-suite-release wasm-gc-release-gate typed-llvmir-smoke typed-llvmir-parity typed-llvmir-focused-parity-suite typed-llvmir-try-throw-parity typed-llvmir-bytes-parity typed-llvmir-list-parity typed-llvmir-mutable-list-parity typed-llvmir-set-parity typed-llvmir-map-parity typed-llvmir-jvm-arrays-parity typed-llvmir-pair-parity typed-llvmir-nullable-parity typed-llvmir-regex-parity typed-llvmir-unicode-string-parity typed-wrappers typed-build typed-wrapper-smoke typed-split-tree-smoke typed-test typed-clean test test-known-flaky test-reader test-core test-runtime test-try-debug test-stdlib test-ffi test-modules test-expanded test-contract test-ergo test-sqlite-robustness test-limits-primitives test-typed-core test-typed-parser test-typed-checker test-typed-rust test-typed-kotlin test-typed-llvmir test-typed-wrappers test-pure-audit test-features test-wrappers test-phase4a test-phase4b test-phase4c test-phase4d test-phase4e test-phase5 test-phase5e test-phase6 test-phase7 test-phase8 test-functional test-repl test-security test-security-profile test-native test-gaps native clean-native audit audit-native jpkg-audit vendor-jsqlite-security-check native-export-review-check tcb-drift-check import-policy-check source-balance restrict-closure-check security-audit clean security security-production security-profile security-hardware-smoke sbom reproducibility-report reproducibility-compare verify release-evidence fuzz fuzz-smoke fuzz-deep fuzz-reader-fuzz fuzz-json-fuzz fuzz-http2-fuzz fuzz-dns-fuzz fuzz-pregexp-fuzz fuzz-csv-fuzz fuzz-format-fuzz fuzz-uri-fuzz fuzz-base64-fuzz fuzz-hex-fuzz fuzz-router-fuzz fuzz-sandbox-fuzz test-rawstring test-regex test-rx test-peg test-regex-all check-docs check-docs-strict data-check docker-build docker-push lint -.PHONY: check-cross-tools docker fuzz-websocket-fuzz jlsp jlsp-freebsd-amd64 \ +.PHONY: help chez static-supported-check chez-cross build binary binary-typed binary-typed-smoke binary-typed-uri-smoke binary-typed-json-smoke binary-cross native-cross pure-audit typecheck typed-rust typed-rust-focused-smoke-suite typed-rust-crate-metadata-smoke typed-rust-hashmap-smoke typed-rust-list-smoke typed-rust-map-smoke typed-rust-set-smoke typed-rust-mutable-list-smoke typed-rust-pair-smoke typed-rust-nullable-smoke typed-rust-string-ops-smoke typed-rust-jvm-helpers-smoke typed-rust-jvm-arrays-smoke typed-rust-jvm-json-smoke typed-rust-try-throw-smoke typed-rust-direct-throw-smoke typed-json-value-smoke typed-json-value-corpus-check typed-json-value-diff typed-json-value-diff-repro typed-json-value-bench typed-json-value-public-smoke typed-json-scan-corpus-check typed-bench typed-uri-pilot typed-uri-corpus-check typed-uri-diff typed-uri-diff-repro typed-uri-bench typed-uri-wrapper-smoke typed-uri-public-smoke typed-json-scan-diff typed-json-scan-bench typed-llvmir typed-llvmir-check typed-llvmir-leak-check typed-llvmir-leak-suite typed-llvmir-wasm-object-smoke typed-llvmir-wasm-runtime-smoke typed-llvmir-wasm-browser-smoke typed-llvmir-wasm-suite typed-llvmir-wasm-suite-release wasm-gc-release-gate typed-llvmir-smoke typed-llvmir-parity typed-llvmir-focused-parity-suite typed-llvmir-try-throw-parity typed-llvmir-bytes-parity typed-llvmir-list-parity typed-llvmir-mutable-list-parity typed-llvmir-set-parity typed-llvmir-map-parity typed-llvmir-jvm-arrays-parity typed-llvmir-pair-parity typed-llvmir-nullable-parity typed-llvmir-regex-parity typed-llvmir-unicode-string-parity typed-wrappers typed-build typed-wrapper-smoke typed-split-tree-smoke typed-test typed-clean test test-known-flaky test-reader test-core test-runtime test-try-debug test-stdlib test-ffi test-modules test-expanded test-contract test-ergo test-sqlite-robustness test-limits-primitives test-typed-core test-typed-parser test-typed-checker test-typed-rust test-typed-kotlin test-typed-llvmir test-typed-wrappers test-pure-audit test-features test-wrappers test-phase4a test-phase4b test-phase4c test-phase4d test-phase4e test-phase5 test-phase5e test-phase6 test-phase7 test-phase8 test-functional test-repl test-security test-security-profile test-native test-gaps native clean-native audit audit-native jpkg-audit vendor-jsqlite-security-check native-export-review-check tcb-drift-check import-policy-check source-balance restrict-closure-check security-audit clean security security-production security-profile security-hardware-smoke sbom reproducibility-report reproducibility-compare verify release-evidence fuzz fuzz-smoke fuzz-deep fuzz-reader-fuzz fuzz-json-fuzz fuzz-http2-fuzz fuzz-dns-fuzz fuzz-pregexp-fuzz fuzz-csv-fuzz fuzz-format-fuzz fuzz-uri-fuzz fuzz-base64-fuzz fuzz-hex-fuzz fuzz-router-fuzz fuzz-sandbox-fuzz test-rawstring test-regex test-rx test-peg test-regex-all check-docs check-docs-strict data-check podman podman-build podman-push lint +.PHONY: check-cross-tools fuzz-websocket-fuzz jlsp jlsp-freebsd-amd64 \ jlsp-install jlsp-linux-amd64 jlsp-portable jmcp-freebsd-amd64 \ jmcp-freebsd-arm64 jmcp-linux-amd64 jmcp-linux-arm64 \ jmcp-macos-amd64 test-all test-nrepl-auth test-worker test-phase2 \ @@ -512,10 +512,10 @@ help: @echo " fuzz-deep Long-running deep fuzz (nightly)" @echo " fuzz-<target> Individual fuzz targets (reader, json, http2, ...)" @echo "" - @echo "Docker:" - @echo " docker Alias for docker-build" - @echo " docker-build Build jerboa21/jerboa base image" - @echo " docker-push Push base image to Docker Hub" + @echo "Podman:" + @echo " podman Alias for podman-build" + @echo " podman-build Build jerboa21/jerboa base image" + @echo " podman-push Push base image to the container registry" static-supported-check: @if [ -n "$(STATIC_ENABLED)" ]; then \ @@ -955,7 +955,7 @@ release-evidence: support/check-release-path-leaks.sh dist/jerboa > "$(EVIDENCE_DIR)/path-leaks.txt" 2>&1 JERBOA_RELEASE_DIR="$(RELEASE_DIR)" JERBOA_SIGNING_EVIDENCE_DIR="$(EVIDENCE_DIR)/signing" support/sign-release-artifacts.sh evidence > "$(EVIDENCE_DIR)/signing-evidence.txt" 2>&1 $(MAKE) sbom > "$(EVIDENCE_DIR)/sbom.txt" 2>&1 - shasum -a 256 Dockerfile Makefile SECURITY.md README.md rust-toolchain.toml \ + shasum -a 256 Containerfile Makefile SECURITY.md README.md rust-toolchain.toml \ docs/release-security.md docs/release-artifacts.md \ docs/typed-final.md docs/typed-uri-pilot.md \ support/container-dependencies.lock support/container-inputs.sh \ @@ -3024,27 +3024,29 @@ clean: find lib -name "*.so" -delete 2>/dev/null || true find lib -name "*.wpo" -delete 2>/dev/null || true -# ── Docker base image (jerboa21/jerboa) ────────────────────────────────────── +# ── Podman base image (jerboa21/jerboa) ────────────────────────────────────── # Base image for building static musl binaries of Jerboa projects. # Includes: stock Chez, musl Chez, jerboa lib, musl-gcc, build deps. -DOCKER_IMAGE = jerboa21/jerboa +PODMAN ?= podman +PODMAN_PLATFORM ?= linux/amd64 +CONTAINER_IMAGE ?= docker.io/jerboa21/jerboa -docker: docker-build +podman: podman-build -docker-build: - @echo "=== Building $(DOCKER_IMAGE) base image ===" +podman-build: + @echo "=== Building $(CONTAINER_IMAGE) base image ===" @support/container-inputs.sh check @base=$$(support/container-inputs.sh field ubuntu-24.04 3); \ - docker build --platform linux/amd64 \ + $(PODMAN) build --platform $(PODMAN_PLATFORM) -f Containerfile \ --build-arg JERBOA_BASE_IMAGE="$$base" \ - -t $(DOCKER_IMAGE) . + -t $(CONTAINER_IMAGE) . @echo "" - @docker images $(DOCKER_IMAGE) --format "Image: {{.Repository}}:{{.Tag}} Size: {{.Size}}" + @$(PODMAN) images $(CONTAINER_IMAGE) --format "Image: {{.Repository}}:{{.Tag}} Size: {{.Size}}" -docker-push: docker-build - @echo "=== Pushing $(DOCKER_IMAGE) to Docker Hub ===" - docker push $(DOCKER_IMAGE) - @echo "Pushed $(DOCKER_IMAGE)" +podman-push: podman-build + @echo "=== Pushing $(CONTAINER_IMAGE) to the container registry ===" + $(PODMAN) push $(CONTAINER_IMAGE) + @echo "Pushed $(CONTAINER_IMAGE)" # ── Browser REPL WASM engine ──────────────────────────────────────────────── BROWSER_REPL_MANIFEST := browser-repl/Cargo.toml --- a/README.md +++ b/README.md @@ -242,7 +242,7 @@ make test-all # broad local test run On Linux, the release pipeline also uses: ```bash -make docker-build +make podman-build ``` For MCP tooling data and portable MCP binaries: --- a/data/anti-patterns.sexp +++ b/data/anti-patterns.sexp @@ -910,14 +910,14 @@ "Use SSH access to linux.cons.io for Linux builds and tests. Run the relevant make, jerbuild, or shell commands remotely over ssh linux.cons.io, and copy or sync artifacts as needed instead of relying on containers.") ("avoid" . - "Do not use Docker or Podman for Jerboa or jerboa-emacs Linux builds, cross-build verification, or CI-style smoke tests. Do not cite unavailable Docker/Podman as a blocker.") + "Use the repo's Podman build target for Jerboa or jerboa-emacs Linux builds, cross-build verification, or CI-style smoke tests. Do not cite unavailable legacy container tooling as a blocker.") ("id" . "no-containers-use-linux-cons") ("kinds" "workflow" "build" "test") ("pattern" . - "(?i)\\b(docker|podman)\\b.*\\b(linux|build|cross|jerboa|jerbuild)\\b") + "(?i)\\bpodman\\b.*\\b(linux|build|cross|jerboa|jerbuild)\\b") ("severity" . "high") - ("tags" "docker" "podman" "linux.cons.io" "cross-build" + ("tags" "podman" "linux.cons.io" "cross-build" "jerboa" "jerboa-emacs") ("title" . "Do not use containers for Linux builds") ("tools" "exec_command")) --- a/data/cookbooks.sexp +++ b/data/cookbooks.sexp @@ -2285,15 +2285,15 @@ "Build Rust static library with rustup when Homebrew rustc shadows it")) (("code" . - ";; PROBLEM: Docker `-v /path/to/file.a:/container/file.a:ro` creates a DIRECTORY\n;; at the host path if the file doesn't exist yet. This persists as a root-owned\n;; directory, blocking future builds even after the file is created.\n;;\n;; SYMPTOM: `file libjsh_coreutils.a` → \"directory\"\n;; `ls -la libjsh_coreutils.a` → shows \"drwxr-xr-x 2 root root\"\n;;\n;; DIAGNOSIS: The .a file was referenced in a Makefile Docker volume mount\n;; before it was built. Docker created a directory at that path.\n;;\n;; FIX: Remove the bogus directory (root-owned, needs Docker or sudo):\n;; docker run --rm -v /path/to/parent:/target alpine \\\n;; rm -rf /target/libjsh_coreutils.a\n;;\n;; Or fix ownership of all root-owned files in a tree:\n;; docker run --rm -v /path/to/target:/target alpine \\\n;; sh -c 'find /target -user root -exec chown 1000:1000 {} +'\n;;\n;; PREVENTION: Verify the source file exists before running Docker:\n;; test -f $(JSH_COREUTILS_LIB) || { echo \"Build rust-coreutils first\"; exit 1; }") ("id" . "docker-volume-mount-nonexistent-file") ("imports") + ";; PROBLEM: Podman `-v /path/to/file.a:/container/file.a:ro` creates a DIRECTORY\n;; at the host path if the file doesn't exist yet. This persists as a root-owned\n;; directory, blocking future builds even after the file is created.\n;;\n;; SYMPTOM: `file libjsh_coreutils.a` → \"directory\"\n;; `ls -la libjsh_coreutils.a` → shows \"drwxr-xr-x 2 root root\"\n;;\n;; DIAGNOSIS: The .a file was referenced in a Makefile Podman volume mount\n;; before it was built. Podman created a directory at that path.\n;;\n;; FIX: Remove the bogus directory (root-owned, needs Podman or sudo):\n;; podman run --rm -v /path/to/parent:/target alpine \\\n;; rm -rf /target/libjsh_coreutils.a\n;;\n;; Or fix ownership of all root-owned files in a tree:\n;; podman run --rm -v /path/to/target:/target alpine \\\n;; sh -c 'find /target -user root -exec chown 1000:1000 {} +'\n;;\n;; PREVENTION: Verify the source file exists before running Podman:\n;; test -f $(JSH_COREUTILS_LIB) || { echo \"Build rust-coreutils first\"; exit 1; }") ("id" . "podman-volume-mount-nonexistent-file") ("imports") ("notes" . - "This is a well-known Docker footgun. Always check that volume-mount source paths for files (not directories) actually exist before running docker. Root-owned artifacts left behind require Docker or sudo to clean up.") - ("tags" "docker" "volume" "mount" "directory" "file" + "This is a well-known Podman footgun. Always check that volume-mount source paths for files (not directories) actually exist before running podman. Root-owned artifacts left behind require Podman or sudo to clean up.") + ("tags" "podman" "volume" "mount" "directory" "file" "static-build" "gotcha") ("title" . - "Docker creates directories when volume-mounting nonexistent files")) + "Podman creates directories when volume-mounting nonexistent files")) (("code" . ";; The (jerboa prelude) shadows Chez's make-time with a datetime constructor.\n;; Capture the original BEFORE the prelude can shadow it, using a local import.\n\n(def chez:make-time\n (let () (import (only (chezscheme) make-time)) make-time))\n\n(def (thread-sleep! secs)\n \"Sleep for SECS seconds (real number). Works in standalone Jerboa prelude scripts.\"\n (let* ((diff (max 0 secs))\n (s (exact (floor diff)))\n (ns (exact (floor (* (- diff s) 1000000000)))))\n (sleep (chez:make-time 'time-duration ns s))))\n\n;; Usage:\n(thread-sleep! 0.5) ;; sleep 500ms\n(thread-sleep! 2) ;; sleep 2 seconds") ("deprecated" . #t) ("id" . "thread-sleep-prelude-script") @@ -2386,11 +2386,11 @@ "Background worker delivering results to jemacs UI thread via ui-queue-push!")) (("code" . - ";; Pattern: vendor/jerboa-ssl-static.sls\n;; Copy the upstream module's .sls to vendor/, then guard load-shared-object\n;; so the static binary skips it (symbols already registered via Sforeign_symbol).\n\n;; In vendor/jerboa-ssl-static.sls (library declaration matches original):\n;; (library (jerboa-ssl) ...)\n;; ...same body as upstream...\n;; BUT replace:\n;; (load-shared-object \"libssl.so\")\n;; (load-shared-object \"libcrypto.so\")\n;; (load-shared-object \"jerboa_ssl_shim.so\")\n;; WITH:\n\n(define load-libs\n (let ([static (getenv \"JEMACS_STATIC\")])\n (if (and static\n (not (string=? static \"\"))\n (not (string=? static \"0\")))\n (void) ;; static binary: symbols pre-registered, skip load\n (begin\n (load-shared-object \"libssl.so\")\n (load-shared-object \"libcrypto.so\")\n (load-shared-object \"jerboa_ssl_shim.so\")))))\n\n;; The static binary sets JEMACS_STATIC=1 in the build script.\n;; The override file lives in vendor/ which comes BEFORE the upstream\n;; lib dir in --libdirs, so it shadows the original.\n\n;; In Makefile, add vendor/ to LIBDIRS before the upstream path:\n;; LIBDIRS = vendor:$(CSSL):...\n;;\n;; In Docker container setup, copy the override into place:\n;; cp vendor/jerboa-ssl-static.sls /deps/jerboa-ssl/src/jerboa-ssl.sls") ("id" . "static-vendor-module-override") + ";; Pattern: vendor/jerboa-ssl-static.sls\n;; Copy the upstream module's .sls to vendor/, then guard load-shared-object\n;; so the static binary skips it (symbols already registered via Sforeign_symbol).\n\n;; In vendor/jerboa-ssl-static.sls (library declaration matches original):\n;; (library (jerboa-ssl) ...)\n;; ...same body as upstream...\n;; BUT replace:\n;; (load-shared-object \"libssl.so\")\n;; (load-shared-object \"libcrypto.so\")\n;; (load-shared-object \"jerboa_ssl_shim.so\")\n;; WITH:\n\n(define load-libs\n (let ([static (getenv \"JEMACS_STATIC\")])\n (if (and static\n (not (string=? static \"\"))\n (not (string=? static \"0\")))\n (void) ;; static binary: symbols pre-registered, skip load\n (begin\n (load-shared-object \"libssl.so\")\n (load-shared-object \"libcrypto.so\")\n (load-shared-object \"jerboa_ssl_shim.so\")))))\n\n;; The static binary sets JEMACS_STATIC=1 in the build script.\n;; The override file lives in vendor/ which comes BEFORE the upstream\n;; lib dir in --libdirs, so it shadows the original.\n\n;; In Makefile, add vendor/ to LIBDIRS before the upstream path:\n;; LIBDIRS = vendor:$(CSSL):...\n;;\n;; In Podman container setup, copy the override into place:\n;; cp vendor/jerboa-ssl-static.sls /deps/jerboa-ssl/src/jerboa-ssl.sls") ("id" . "static-vendor-module-override") ("imports" "(chezscheme)") ("notes" . - "Use this when a third-party library calls load-shared-object at module load time and you can't modify the upstream source. The override file is only compiled into the Docker container — development mode still uses the upstream. The JEMACS_STATIC check is a 3-way guard: (and static (not empty) (not \"0\")) so unsetting the var reverts to dynamic loading. Alpine's openssl-dev only ships shared .so files — if you need static libssl.a, you must build OpenSSL from source inside the container. See also: jerboa-load-shared-object-static for the simpler guard-only pattern.") + "Use this when a third-party library calls load-shared-object at module load time and you can't modify the upstream source. The override file is only compiled into the Podman container — development mode still uses the upstream. The JEMACS_STATIC check is a 3-way guard: (and static (not empty) (not \"0\")) so unsetting the var reverts to dynamic loading. Alpine's openssl-dev only ships shared .so files — if you need static libssl.a, you must build OpenSSL from source inside the container. See also: jerboa-load-shared-object-static for the simpler guard-only pattern.") ("tags" "static" "vendor" "override" "load-shared-object" "JEMACS_STATIC" "build") ("title" @@ -3510,7 +3510,7 @@ ("imports") ("notes" . - "The musl-target libjerboa_native.a is pre-built in the Docker image. If you add new Rust FFI functions (like jerboa_eventfd_* was added), the archive may be stale. Rebuild inside Docker:\n\n```bash\ndocker run --rm -v ~/mine/jerboa:/build/mine/jerboa -w /build/mine/jerboa/jerboa-native-rs \\\n jerboa21/jerboa cargo build --release --target x86_64-unknown-linux-musl --no-default-features\n```\n\nNote the `:ro` flag is removed for the rebuild run, then restored for the actual static build.\n\nTo check what's actually in the archive:\n```bash\nnm libjerboa_native.a | grep \"^[0-9a-f].*T jerboa_\" | awk '{print $3}' | sort\n```") + "The musl-target libjerboa_native.a is pre-built in the Podman image. If you add new Rust FFI functions (like jerboa_eventfd_* was added), the archive may be stale. Rebuild inside Podman:\n\n```bash\npodman run --rm -v ~/mine/jerboa:/build/mine/jerboa -w /build/mine/jerboa/jerboa-native-rs \\\n jerboa21/jerboa cargo build --release --target x86_64-unknown-linux-musl --no-default-features\n```\n\nNote the `:ro` flag is removed for the rebuild run, then restored for the actual static build.\n\nTo check what's actually in the archive:\n```bash\nnm libjerboa_native.a | grep \"^[0-9a-f].*T jerboa_\" | awk '{print $3}' | sort\n```") ("tags" "libjerboa_native" "Sforeign_symbol" "crypto" "static-binary" "FFI" "symbol-names") ("title" @@ -3564,11 +3564,11 @@ "Export jerboa-db datoms to DuckDB for OLAP queries")) (("code" . - ";; PROBLEM: Docker Chez Scheme csv10 rejects two token forms even with\n;; #!chezscheme mode prefix:\n;; #\\escape → \"invalid character name\" (use #\\esc instead)\n;; #!void → \"invalid syntax #!void\" (use (void) instead)\n;;\n;; SOLUTION: Text-preprocess the source string before handing it to\n;; (with-input-from-string src read) in jerbuild.\n\n(def (normalize-jerboa-reader-tokens src)\n ;; Replace #!void with (void) — exact token, word boundary via space/paren\n (let* ([s (re-replace-all (re \"#!void\") src \"(void)\")]\n ;; Replace #\\escape with #\\esc\n [s (re-replace-all (re \"#\\\\\\\\escape\") s \"#\\\\esc\")])\n s))\n\n;; Usage in jerbuild's read loop:\n(def (read-forms-from-string src)\n (let ([normalized (normalize-jerboa-reader-tokens src)])\n (with-input-from-string normalized\n (lambda ()\n (let loop ([forms '()])\n (let ([form (read)])\n (if (eof-object? form)\n (reverse forms)\n (loop (cons form forms)))))))))") ("id" . "jerbuild-jerboa-reader-char-void-normalize") + ";; PROBLEM: Podman Chez Scheme csv10 rejects two token forms even with\n;; #!chezscheme mode prefix:\n;; #\\escape → \"invalid character name\" (use #\\esc instead)\n;; #!void → \"invalid syntax #!void\" (use (void) instead)\n;;\n;; SOLUTION: Text-preprocess the source string before handing it to\n;; (with-input-from-string src read) in jerbuild.\n\n(def (normalize-jerboa-reader-tokens src)\n ;; Replace #!void with (void) — exact token, word boundary via space/paren\n (let* ([s (re-replace-all (re \"#!void\") src \"(void)\")]\n ;; Replace #\\escape with #\\esc\n [s (re-replace-all (re \"#\\\\\\\\escape\") s \"#\\\\esc\")])\n s))\n\n;; Usage in jerbuild's read loop:\n(def (read-forms-from-string src)\n (let ([normalized (normalize-jerboa-reader-tokens src)])\n (with-input-from-string normalized\n (lambda ()\n (let loop ([forms '()])\n (let ([form (read)])\n (if (eof-object? form)\n (reverse forms)\n (loop (cons form forms)))))))))") ("id" . "jerbuild-jerboa-reader-char-void-normalize") ("imports") ("notes" . - "This only affects jerbuild's .ss→.sls transpiler pipeline when targeting Chez csv10 (the Docker build). Interactive Chez sessions and newer Chez releases may accept #\\escape. The preprocess step must happen on the raw source string, BEFORE calling read — you cannot fix this at the AST level because the reader fails before producing an AST. Apply normalization once per source file, not per form.") + "This only affects jerbuild's .ss→.sls transpiler pipeline when targeting Chez csv10 (the Podman build). Interactive Chez sessions and newer Chez releases may accept #\\escape. The preprocess step must happen on the raw source string, BEFORE calling read — you cannot fix this at the AST level because the reader fails before producing an AST. Apply normalization once per source file, not per form.") ("tags" "jerbuild" "reader" "chez" "csv10" "char" "void" "preprocessing") ("title" @@ -6123,7 +6123,7 @@ ("imports" "(jerboa prelude)") ("notes" . - "rsync -a preserves permissions/symlinks and --exclude patterns keep generated build artifacts out of the workspace copy. cp -R fallback can fail if excluded directories contain files the current user can't read (e.g. stale .so files owned by root in Docker); install rsync to use the exclude path. Leading / in exclude patterns makes them anchor to the source root, preventing false matches in subdirectories. Trailing / on source-root/ means copy contents not the directory itself.") + "rsync -a preserves permissions/symlinks and --exclude patterns keep generated build artifacts out of the workspace copy. cp -R fallback can fail if excluded directories contain files the current user can't read (e.g. stale .so files owned by root in Podman); install rsync to use the exclude path. Leading / in exclude patterns makes them anchor to the source root, preventing false matches in subdirectories. Trailing / on source-root/ means copy contents not the directory itself.") ("tags" "rsync" "cp" "workspace" "copy" "exclude" "build-artifacts" "subprocess") ("title" @@ -6220,7 +6220,7 @@ "# Makefile\nJERBUILD ?= jerbuild\nJH := $(shell $(JERBUILD) --jerboa-home 2>/dev/null)\nVENDOR_DEP_URL ?= https://git.sr.ht/~lisp/jerboa-yubikey\nVENDOR_DEP_DIR := vendor/jerboa-yubikey\nVENDOR_DEP_LIB := $(VENDOR_DEP_DIR)/lib\nJEXEC := $(JERBUILD) exec --libdirs $(CURDIR)/$(VENDOR_DEP_LIB):$(CURDIR)/scheme:$(JH)/lib\n\nvendor-yubikey:\n\tsh support/ensure-vendor.sh jerboa-yubikey \"$(VENDOR_DEP_URL)\"\n\t@test -f \"$(VENDOR_DEP_LIB)/yubikey/auth.sls\" || \\\n\t { echo \"ERROR: missing $(VENDOR_DEP_LIB)/yubikey/auth.sls\" >&2; exit 1; }\n\nbinary: vendor-yubikey\n\t$(JERBUILD) build\n\n# .jerbuild\n(entry \"scheme/main.ss\")\n(output \"my-program\")\n(libdirs \"vendor/jerboa-yubikey/lib\" \"scheme\")\n(pre-build \"sh support/ensure-vendor.sh jerboa-yubikey https://git.sr.ht/~lisp/jerboa-yubikey\")\n\n# support/ensure-vendor.sh\n#!/bin/sh\nset -eu\nname=\"$1\"\nurl=\"$2\"\ncase \"$url\" in https://*|git://*|ssh://*|git@*:*) ;; *) echo \"absolute Git URL required\" >&2; exit 2;; esac\ndir=\"vendor/$name\"\nif [ -d \"$dir\" ] && { [ -f \"$dir/README.md\" ] || [ -f \"$dir/Makefile\" ]; }; then exit 0; fi\nrm -rf \"$dir\"\nmkdir -p vendor\ntmp=\"vendor/.$name.tmp.$$\"\ntrap 'rm -rf \"$tmp\"' EXIT INT TERM\ngit clone --depth 1 \"$url\" \"$tmp\"\nrm -rf \"$tmp/.git\"\nmv \"$tmp\" \"$dir\"") ("id" . "jerbuild-vendor-dependency-prebuild") ("imports") ("notes" . - "Put the vendored libdir before local source libdirs if the project previously carried a copied module tree; otherwise the stale local copy can shadow the canonical dependency. Use an absolute Git URL in the pre-build hook, not a developer-local path such as ~/mine/.... Exclude build artifacts from package and Docker contexts.") + "Put the vendored libdir before local source libdirs if the project previously carried a copied module tree; otherwise the stale local copy can shadow the canonical dependency. Use an absolute Git URL in the pre-build hook, not a developer-local path such as ~/mine/.... Exclude build artifacts from package and Podman contexts.") ("tags" "jerbuild" "vendor" "libdirs" "makefile" "dependency" "git-url") ("title" --- a/data/error-fixes.sexp +++ b/data/error-fixes.sexp @@ -2300,7 +2300,7 @@ "The file-wide MCP verifier can raise this reader/expander error for jerbuild.ss while the repository's native binary build compiles the same source successfully. Avoid random edits to unrelated defstruct forms; use the repo build as the authoritative check.") ("fix" . - "When this exact error appears from jerboa_verify on the full jerbuild.ss file, first validate with the real build path (`make binary` on non-Linux hosts or `make docker-build` on Linux) before editing source. If the build passes, treat it as a verifier limitation around file-wide expansion rather than a proven malformed defstruct.") + "When this exact error appears from jerboa_verify on the full jerbuild.ss file, first validate with the real build path (`make binary` on non-Linux hosts or `make podman-build` on Linux) before editing source. If the build passes, treat it as a verifier limitation around file-wide expansion rather than a proven malformed defstruct.") ("id" . "jerbuild-defstruct-verifier-cadr") ("pattern" . --- a/data/features.sexp +++ b/data/features.sexp @@ -24,7 +24,7 @@ "Audit Scheme files for unguarded load-shared-object calls that crash static binaries") ("use_case" . - "When preparing a Jerboa project for static binary compilation (musl or otherwise), before spending 30+ minutes on a Docker build that fails at runtime.") + "When preparing a Jerboa project for static binary compilation (musl or otherwise), before spending 30+ minutes on a Podman build that fails at runtime.") ("votes" . 1)) (("closed_reason" . @@ -334,7 +334,7 @@ "~2000 tokens per static build (eliminates 4-6 round-trips of build→crash→grep→nm→fix, each ~300-400 tokens)") ("example_scenario" . - "Building jerboa-edge static binary: the C main had `jerboa_sha`, `jerboa_hmac_sha`, `jerboa_argon`, `jerboa_pbkdf`, `jerboa_chacha` as registered names. The actual archive had `jerboa_sha256`, `jerboa_hmac_sha256`, `jerboa_argon2id_hash`, etc. The linker errored on all of them as undefined references (15+ symbols). Additionally `getsockname` and `getpeername` were used by (std net io) but not registered, causing runtime \"no entry\" crashes. Finding each missing symbol required: (1) Docker build → linker error or runtime crash → (2) grep stdlib source for foreign-procedure uses → (3) nm archive to verify actual name → (4) edit C main → repeat. A coverage check tool would have reported all gaps in one shot before the first build attempt.") + "Building jerboa-edge static binary: the C main had `jerboa_sha`, `jerboa_hmac_sha`, `jerboa_argon`, `jerboa_pbkdf`, `jerboa_chacha` as registered names. The actual archive had `jerboa_sha256`, `jerboa_hmac_sha256`, `jerboa_argon2id_hash`, etc. The linker errored on all of them as undefined references (15+ symbols). Additionally `getsockname` and `getpeername` were used by (std net io) but not registered, causing runtime \"no entry\" crashes. Finding each missing symbol required: (1) Podman build → linker error or runtime crash → (2) grep stdlib source for foreign-procedure uses → (3) nm archive to verify actual name → (4) edit C main → repeat. A coverage check tool would have reported all gaps in one shot before the first build attempt.") ("id" . "static-binary-sforeign-symbol-coverage-check") ("impact" . "high") ("implemented_in" . "mcp/server.ss") ("implemented_tool" . "jerboa_static_symbol_audit") @@ -349,7 +349,7 @@ "Check that C main Sforeign_symbol registrations cover all foreign-procedure symbols in a WPO binary") ("use_case" . - "When writing or updating the C main for a static Jerboa binary, before spending 30 minutes on a Docker build that then crashes at runtime with \"no entry for getsockname\".") + "When writing or updating the C main for a static Jerboa binary, before spending 30 minutes on a Podman build that then crashes at runtime with \"no entry for getsockname\".") ("votes" . 0)) (("closed_reason" . @@ -381,13 +381,13 @@ "Token check reports csv10-incompatible #\\escape and #!void reader forms with replacements.") ("description" . - "When validating .ss files destined for jerbuild transpilation, jerboa_verify (and jerboa_check_syntax) should detect token forms that are valid in newer Chez but rejected by csv10 (the Docker/static build toolchain): specifically #\\escape (use #\\esc) and #!void (use (void)). These cause silent build failures — the reader error surfaces only inside Docker, far from the source edit. The tool should report the file, line, offending token, and the correct replacement.") + "When validating .ss files destined for jerbuild transpilation, jerboa_verify (and jerboa_check_syntax) should detect token forms that are valid in newer Chez but rejected by csv10 (the Podman/static build toolchain): specifically #\\escape (use #\\esc) and #!void (use (void)). These cause silent build failures — the reader error surfaces only inside Podman, far from the source edit. The tool should report the file, line, offending token, and the correct replacement.") ("estimated_token_reduction" . - "~400 tokens per occurrence (eliminates full Docker build cycle + grep search to locate the offending token)") + "~400 tokens per occurrence (eliminates full Podman build cycle + grep search to locate the offending token)") ("example_scenario" . - "A .ss file uses #\\escape as a character literal. Local jerboa_verify passes. The Docker build (Chez csv10) fails with \"invalid character name: escape\" deep in the build log. Finding the source location requires searching all .ss files for #\\escape manually. A jerboa_verify warning would have caught it immediately at edit time.") + "A .ss file uses #\\escape as a character literal. Local jerboa_verify passes. The Podman build (Chez csv10) fails with \"invalid character name: escape\" deep in the build log. Finding the source location requires searching all .ss files for #\\escape manually. A jerboa_verify warning would have caught it immediately at edit time.") ("id" . "jerbuild-reader-token-validator") ("impact" . "medium") ("implemented_in" . "mcp/server.ss") ("implemented_tool" . "jerboa_jerbuild_token_check") @@ -398,7 +398,7 @@ "jerboa_verify should flag Chez csv10-incompatible reader tokens (#\\escape, #!void)") ("use_case" . - "When editing .ss files that will be transpiled by jerbuild for static/Docker builds using an older Chez csv10 toolchain. The incompatibility is invisible during local development with a newer Chez and only surfaces in Docker.") + "When editing .ss files that will be transpiled by jerbuild for static/Podman builds using an older Chez csv10 toolchain. The incompatibility is invisible during local development with a newer Chez and only surfaces in Podman.") ("votes" . 0)) (("closed_reason" . @@ -532,7 +532,7 @@ "jerboa_boot_library_audit now accepts roots/entry_paths plus external_libs, resolves imports through project/Jerboa libdirs, follows transitive std/jerboa imports, and reports missing/extra external libraries.") ("description" . - "When building a static jerboa binary via make-boot-file + compile-program, every transitive (std ...) and (jerboa ...) library import of every included module must be explicitly listed in the binary's `external-libs` list. If even one is missing, the build succeeds but the binary crashes at runtime with `Exception: library (std X Y) not found`. There is no compile-time check for this — each missing library surfaces as a separate runtime failure, requiring a full Docker rebuild cycle (~5 minutes) to discover. A tool that takes a set of root .ss/.sls files (or a project's existing external-libs list) and computes the actual transitive closure of stdlib imports would catch all gaps in one shot. Implementation: parse the import forms in each .ss/.sls under a given libdir set, follow the graph until fixed point, return the diff against the existing external-libs list.") + "When building a static jerboa binary via make-boot-file + compile-program, every transitive (std ...) and (jerboa ...) library import of every included module must be explicitly listed in the binary's `external-libs` list. If even one is missing, the build succeeds but the binary crashes at runtime with `Exception: library (std X Y) not found`. There is no compile-time check for this — each missing library surfaces as a separate runtime failure, requiring a full Podman rebuild cycle (~5 minutes) to discover. A tool that takes a set of root .ss/.sls files (or a project's existing external-libs list) and computes the actual transitive closure of stdlib imports would catch all gaps in one shot. Implementation: parse the import forms in each .ss/.sls under a given libdir set, follow the graph until fixed point, return the diff against the existing external-libs list.") ("estimated_token_reduction" . "~2000 tokens per binary integration of new vendored library (eliminates 3-4 full build/crash/grep/fix cycles, each ~500-700 tokens)") --- a/docs/browser-repl-plan.md +++ b/docs/browser-repl-plan.md @@ -734,7 +734,7 @@ works fully when allowed by the REPL CSP, and non-REPL pages retain 9. Run the site's existing `make verify` and `make release-evidence` gates. 10. On macOS, run the canonical native `make binary` pre-commit gate for each repository containing Jerboa source changes. Do not substitute the Linux - Docker gate on macOS. + Podman gate on macOS. 11. Deploy through the existing site playbook. Extend deployment evidence to check `/repl/` plus the content-hashed WASM route, including CSP, MIME, digest, TLS, and a browser smoke result. --- a/docs/bundling-chez.md +++ b/docs/bundling-chez.md @@ -17,8 +17,8 @@ part of the normal build. This doc records how that works and what's left. | `make chez` builds it | **Done** — installs to `./.chez/`, no `sudo`, no system Chez | | Wired into the build | **Done** — `build:`/`binary:` depend on `chez`; `SCHEME` defaults to `.chez/bin/scheme` | | Cross-compilation | **Done** — `make chez-cross` for Linux/FreeBSD/macOS-x86 targets | -| Docker | **Done** — image builds the same `vendor/ChezScheme` (glibc + a `--static` musl variant) | -| `--static` musl | **Done** — `support/musl-chez-build*.sh`, Docker musl stage | +| Podman | **Done** — image builds the same `vendor/ChezScheme` (glibc + a `--static` musl variant) | +| `--static` musl | **Done** — `support/musl-chez-build*.sh`, Podman musl stage | | Native `STATIC=1` | **Done for ELF/BSD** — `make ... STATIC=1` uses `.chez-static`, passes Chez `--static`, and links supported native binaries statically on Linux/FreeBSD/OpenBSD/NetBSD; macOS rejects the knob explicitly because Mach-O static system binaries are not a supported release target | | Licensing / attribution | **Done** — `LICENSE-CHEZ` + README + `--version`; all bundled deps permissive; lz4 reduced to BSD `lib/` + LICENSE (zero GPL) | | Distribution story | **Done** — `jerboa-portable`, `release-artifact(s)`, signing, SBOM, and release evidence targets exist | @@ -60,12 +60,12 @@ targets include `ta6le`/`tarm64le` (Linux), `ta6fb` (FreeBSD), and `ta6osx` (macOS x86_64). This resolved the original "cross-arch" open question, though each target still needs its cross-CC plumbed (`CROSS_CC=…`). -### Docker +### Podman -`Dockerfile` copies `vendor/ChezScheme` into the build context and builds it +`Containerfile` copies `vendor/ChezScheme` into the build context and builds it twice: a glibc Chez at `/usr/local` (`--threads --enable-harden --disable-x11`) and a `--static CC=musl-gcc` variant for fully static binaries. Native builds -and Docker share one Chez source. +and Podman share one Chez source. ## What's already in place (C embedding) @@ -119,7 +119,7 @@ dirs; supports multiple independent instances. 2. **Generalize `--static` (done for supported native static targets).** Static, hermetic Chez is wired for Linux/musl (`musl-chez-build*.sh`, - Docker musl, `jerboa-linux-*`) and the FreeBSD release path uses the system + Podman musl, `jerboa-linux-*`) and the FreeBSD release path uses the system static toolchain. Native `make ... STATIC=1` now installs Chez under `.chez-static`, passes `--static` to the vendored Chez configure step, and propagates the static link mode to `binary`, `jerbuild`, and `jmcp` on --- a/docs/chez-hardening.md +++ b/docs/chez-hardening.md @@ -22,7 +22,7 @@ In scope: - `vendor/ChezScheme/s/x86_64.ss` and `s/arm64.ss` — the JIT back-ends that emit native function prologues at runtime. - The Jerboa build wiring that drives Chez's `./configure` - (`Makefile`, `Dockerfile`, cross-build paths). + (`Makefile`, `Containerfile`, cross-build paths). Out of scope: - Jerboa's C shim and link line. Already hardened via @@ -71,7 +71,7 @@ entry points: |------------------------------------|:-------------------------:| | `Makefile` `$(CHEZ_INSTALL_FLAGS)` | ✓ | | `Makefile` `chez-cross` target | ✓ | -| `Dockerfile` (musl pipeline) | ✓ | +| `Containerfile` (musl pipeline) | ✓ | | `support/musl-chez-build*.sh` | ✓ | Net effect: newly built `libkernel.a` uses the Chez fork's hardening @@ -139,7 +139,7 @@ append `--enable-harden`. CET is x86_64-Linux-only; the configure case statement gates it automatically per `flagsmuni`, so this is safe for all targets including `tarm64le`, `ta6osx`, `ta6fb`. -**`Dockerfile`** (~lines 71, 84, 89): the three `./configure` +**`Containerfile`** (~lines 71, 84, 89): the three `./configure` invocations in the Chez build stages all need `--enable-harden`. The musl-static stage (line 89) is the highest-value one — that's the production binary. @@ -476,7 +476,7 @@ regressed (e.g., someone added a third `./configure` call without Recommended sequence to land: -1. **Phase 1** (done) — `--enable-harden` is wired into native, cross, Docker, +1. **Phase 1** (done) — `--enable-harden` is wired into native, cross, Podman, and musl helper build paths. 2. **Phase 2.1–2.4** (done) — extra compiler-probed CFLAGS and static `-fPIE` are folded into the vendored Chez configure path. --- a/docs/cross-compile.md +++ b/docs/cross-compile.md @@ -248,11 +248,11 @@ binary. ## Validation -Cross-built binaries can be smoke-tested with Docker (or any Linux +Cross-built binaries can be smoke-tested with Podman (or any Linux runtime):