Add linux-tui/linux-qt static build targets using jerboa21/jerboa

ober

985d4ef8c2fbc442fff8edd188a7adb89297ed65

diff --git a/Dockerfile.qt b/Dockerfile.qt
new file mode 100644
index 0000000..db9da7c
--- /dev/null
+++ b/Dockerfile.qt
@@ -0,0 +1,292 @@
+# Dockerfile.qt — Build jemacs-qt static binary using jerboa21/jerboa + Qt6
+#
+# Multi-stage build:
+#   Stage 1 (Alpine):          Build Qt6 static, QScintilla, tree-sitter, libvterm (musl)
+#   Stage 1.5 (Alpine+shim):   Compile libqt_shim.a with musl-compatible g++
+#   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
+#   chmod +x jemacs-qt
+
+# ── Stage 1: Build Qt6 + QScintilla + tree-sitter + libvterm on Alpine ───────
+FROM alpine:3.21 AS qt-alpine
+
+ARG QT6_VERSION=6.8.3
+ARG QSCI_VERSION=2.14.1
+ARG TS_VERSION=0.24.7
+
+# ── Phase 1: Alpine build deps ──────────────────────────────────────────
+RUN apk add --no-cache \
+    cmake samurai perl python3 linux-headers patchelf \
+    libxcb-dev xcb-util-dev xcb-util-image-dev \
+    xcb-util-keysyms-dev xcb-util-renderutil-dev \
+    xcb-util-wm-dev xcb-util-cursor-dev \
+    libx11-dev libxkbcommon-dev \
+    fontconfig-dev freetype-dev harfbuzz-dev \
+    libpng-dev zlib-dev \
+    pcre2-dev \
+    at-spi2-core-dev libdrm-dev \
+    zlib-static libxcb-static \
+    fontconfig-static freetype-static harfbuzz-static \
+    libpng-static bzip2-static expat-static brotli-static \
+    libx11-static graphite2-static libxkbcommon-static \
+    ncurses-dev ncurses-static \
+    util-linux-dev util-linux-static \
+    libvterm-dev libvterm-static \
+    gcc g++ binutils make git curl wget
+
+# Build static libXau (no Alpine -static package available)
+RUN apk add --no-cache libxau-dev && \
+    cd /tmp && \
+    wget -q https://xorg.freedesktop.org/releases/individual/lib/libXau-1.0.12.tar.xz && \
+    tar xf libXau-1.0.12.tar.xz && \
+    cd libXau-1.0.12 && \
+    ./configure --prefix=/usr --enable-static --disable-shared && \
+    make -j$(nproc) && make install && \
+    cd / && rm -rf /tmp/libXau-1.0.12*
+
+# Build static libxcb-util (no Alpine -static package; needed by xcb-image)
+RUN cd /tmp && \
+    wget -q https://xcb.freedesktop.org/dist/xcb-util-0.4.1.tar.xz && \
+    tar xf xcb-util-0.4.1.tar.xz && \
+    cd xcb-util-0.4.1 && \
+    ./configure --prefix=/usr --enable-static --disable-shared && \
+    make -j$(nproc) && make install && \
+    cd / && rm -rf /tmp/xcb-util-0.4.1*
+
+# ── Phase 2: Build Qt6 qtbase static ────────────────────────────────────
+RUN wget -q https://download.qt.io/official_releases/qt/6.8/${QT6_VERSION}/submodules/qtbase-everywhere-src-${QT6_VERSION}.tar.xz && \
+    tar xf qtbase-everywhere-src-${QT6_VERSION}.tar.xz && \
+    rm qtbase-everywhere-src-${QT6_VERSION}.tar.xz && \
+    cmake -S qtbase-everywhere-src-${QT6_VERSION} -B qt6-build -G Ninja \
+      -DCMAKE_BUILD_TYPE=Release \
+      -DCMAKE_INSTALL_PREFIX=/opt/qt6-static \
+      -DBUILD_SHARED_LIBS=OFF \
+      -DQT_BUILD_EXAMPLES=OFF \
+      -DQT_BUILD_TESTS=OFF \
+      -DQT_BUILD_BENCHMARKS=OFF \
+      -DFEATURE_xcb=ON \
+      -DFEATURE_sql=OFF \
+      -DFEATURE_network=OFF \
+      -DFEATURE_testlib=OFF \
+      -DFEATURE_printsupport=ON \
+      -DFEATURE_dbus=OFF \
+      -DFEATURE_opengl=OFF \
+      -DFEATURE_vulkan=OFF \
+      -DFEATURE_glib=OFF \
+      -DFEATURE_icu=OFF && \
+    cmake --build qt6-build --parallel && \
+    cmake --install qt6-build && \
+    rm -rf qtbase-everywhere-src-${QT6_VERSION} qt6-build
+
+# ── Phase 3: Build QScintilla static ────────────────────────────────────
+RUN wget -q https://www.riverbankcomputing.com/static/Downloads/QScintilla/${QSCI_VERSION}/QScintilla_src-${QSCI_VERSION}.tar.gz && \
+    tar xf QScintilla_src-${QSCI_VERSION}.tar.gz && \
+    rm QScintilla_src-${QSCI_VERSION}.tar.gz && \
+    cd QScintilla_src-${QSCI_VERSION}/src && \
+    /opt/qt6-static/bin/qmake CONFIG+=staticlib && \
+    make -j$(nproc) && \
+    make install && \
+    cd / && rm -rf QScintilla_src-${QSCI_VERSION}
+
+# ── Phase 4: Generate pkg-config files with full transitive deps ─────────
+RUN mkdir -p /opt/qt6-static/lib/pkgconfig && \
+    prl_libs() { \
+      grep '^QMAKE_PRL_LIBS ' "$1" | \
+        sed 's/^QMAKE_PRL_LIBS *= *//' | \
+        tr ' ' '\n' | grep '^-l' | \
+        grep -v '^-lQt6' | tr '\n' ' '; \
+    } && \
+    CORE_PRIVATE=$(prl_libs /opt/qt6-static/lib/libQt6Core.prl) && \
+    GUI_PRL=$(prl_libs /opt/qt6-static/lib/libQt6Gui.prl) && \
+    XCB_PRL=$(prl_libs /opt/qt6-static/plugins/platforms/libqxcb.prl) && \
+    TRANSITIVE="-lgraphite2 -lbz2 -lbrotlidec -lbrotlicommon -lexpat -lXau -lXdmcp" && \
+    GUI_PRIVATE="$GUI_PRL $TRANSITIVE" && \
+    XCB_TRANSITIVE="-lxcb-util -lxcb -lXau -lXdmcp" && \
+    XCB_PRIVATE="$XCB_PRL $TRANSITIVE $XCB_TRANSITIVE" && \
+    printf '%s\n' \
+      'prefix=/opt/qt6-static' \
+      'includedir=${prefix}/include' \
+      'libdir=${prefix}/lib' \
+      '' \
+      'Name: Qt6Core' "Description: Qt6 Core" "Version: ${QT6_VERSION}" \
+      'Cflags: -I${includedir} -I${includedir}/QtCore' \
+      "Libs: -L\${libdir} -lQt6Core" \
+      "Libs.private: $CORE_PRIVATE" \
+      > /opt/qt6-static/lib/pkgconfig/Qt6Core.pc && \
+    printf '%s\n' \
+      'prefix=/opt/qt6-static' \
+      'includedir=${prefix}/include' \
+      'libdir=${prefix}/lib' \
+      '' \
+      'Name: Qt6Gui' "Description: Qt6 Gui" "Version: ${QT6_VERSION}" \
+      'Requires: Qt6Core' \
+      'Cflags: -I${includedir} -I${includedir}/QtGui' \
+      "Libs: -L\${libdir} -lQt6Gui" \
+      "Libs.private: $GUI_PRIVATE" \
+      > /opt/qt6-static/lib/pkgconfig/Qt6Gui.pc && \
+    printf '%s\n' \
+      'prefix=/opt/qt6-static' \
+      'includedir=${prefix}/include' \
+      'libdir=${prefix}/lib' \
+      '' \
+      'Name: Qt6Widgets' "Description: Qt6 Widgets" "Version: ${QT6_VERSION}" \
+      'Requires: Qt6Gui' \
+      'Cflags: -I${includedir} -I${includedir}/QtWidgets -I${includedir}/QtGui -I${includedir}/QtCore' \
+      "Libs: -L\${libdir} -lQt6Widgets" \
+      > /opt/qt6-static/lib/pkgconfig/Qt6Widgets.pc && \
+    printf '%s\n' \
+      'prefix=/opt/qt6-static' \
+      'includedir=${prefix}/include' \
+      'libdir=${prefix}/lib' \
+      '' \
+      'Name: Qt6PrintSupport' "Description: Qt6 PrintSupport" "Version: ${QT6_VERSION}" \
+      'Requires: Qt6Widgets' \
+      'Cflags: -I${includedir} -I${includedir}/QtPrintSupport' \
+      "Libs: -L\${libdir} -lQt6PrintSupport" \
+      > /opt/qt6-static/lib/pkgconfig/Qt6PrintSupport.pc && \
+    printf '%s\n' \
+      'prefix=/opt/qt6-static' \
+      'includedir=${prefix}/include' \
+      'libdir=${prefix}/lib' \
+      'plugindir=${prefix}/plugins' \
+      '' \
+      'Name: Qt6XcbPlugin' "Description: Qt6 XCB platform plugin" "Version: ${QT6_VERSION}" \
+      'Requires: Qt6Gui' \
+      "Libs: -L\${libdir} -L\${plugindir}/platforms -lqxcb -lQt6XcbQpa" \
+      "Libs.private: $XCB_PRIVATE" \
+      > /opt/qt6-static/lib/pkgconfig/Qt6XcbPlugin.pc && \
+    printf '%s\n' \
+      'prefix=/opt/qt6-static' \
+      'includedir=${prefix}/include' \
+      'libdir=${prefix}/lib' \
+      '' \
+      'Name: QScintilla' "Description: QScintilla for Qt6" "Version: ${QSCI_VERSION}" \
+      'Requires: Qt6Widgets Qt6PrintSupport' \
+      'Cflags: -I${includedir} -I${includedir}/Qsci' \
+      "Libs: -L\${libdir} -lqscintilla2_qt6" \
+      > /opt/qt6-static/lib/pkgconfig/QScintilla.pc && \
+    echo "Generated .pc files:" && ls /opt/qt6-static/lib/pkgconfig/
+
+# ── Phase 5: Build tree-sitter + grammars (static) ──────────────────────
+RUN git clone --depth 1 --branch v${TS_VERSION} \
+      https://github.com/tree-sitter/tree-sitter /tmp/tree-sitter && \
+    cd /tmp/tree-sitter && \
+    cc -c -O2 -Ilib/include lib/src/lib.c -o lib/src/lib.o && \
+    mkdir -p /opt/tree-sitter-lib && \
+    ar rcs /opt/tree-sitter-lib/libtree-sitter.a lib/src/lib.o && \
+    mkdir -p /opt/tree-sitter-include/tree_sitter && \
+    cp lib/include/tree_sitter/api.h /opt/tree-sitter-include/tree_sitter/ && \
+    rm -rf /tmp/tree-sitter
+
+RUN mkdir -p /opt/tree-sitter-grammars && \
+    build_grammar() { \
+      name=$1; repo=$2; tag=$3; subdir=${4:-.}; \
+      git clone --depth 1 --branch "$tag" \
+        "https://github.com/$repo" /tmp/ts-$name && \
+      cd /tmp/ts-$name/$subdir && \
+      SRC_DIR=src && \
+      gcc -c -O2 -I/opt/tree-sitter-include -I$SRC_DIR \
+        $SRC_DIR/parser.c -o parser.o && \
+      if [ -f $SRC_DIR/scanner.c ]; then \
+        gcc -c -O2 -I/opt/tree-sitter-include -I$SRC_DIR \
+          $SRC_DIR/scanner.c -o scanner.o && \
+        ar rcs /opt/tree-sitter-grammars/libtree-sitter-$name.a parser.o scanner.o; \
+      else \
+        ar rcs /opt/tree-sitter-grammars/libtree-sitter-$name.a parser.o; \
+      fi && \
+      cd / && rm -rf /tmp/ts-$name; \
+    } && \
+    build_grammar c          tree-sitter/tree-sitter-c          v0.23.5 && \
+    build_grammar cpp        tree-sitter/tree-sitter-cpp        v0.23.4 && \
+    build_grammar python     tree-sitter/tree-sitter-python     v0.23.6 && \
+    build_grammar javascript tree-sitter/tree-sitter-javascript v0.23.1 && \
+    build_grammar rust       tree-sitter/tree-sitter-rust       v0.23.3 && \
+    build_grammar go         tree-sitter/tree-sitter-go         v0.23.4 && \
+    build_grammar bash       tree-sitter/tree-sitter-bash       v0.23.3 && \
+    build_grammar json       tree-sitter/tree-sitter-json       v0.24.8 && \
+    build_grammar ruby       tree-sitter/tree-sitter-ruby       v0.23.1 && \
+    build_grammar java       tree-sitter/tree-sitter-java       v0.23.5 && \
+    build_grammar css        tree-sitter/tree-sitter-css        v0.23.2 && \
+    build_grammar html       tree-sitter/tree-sitter-html       v0.23.2 && \
+    build_grammar lua        tree-sitter-grammars/tree-sitter-lua v0.3.0 && \
+    build_grammar scheme     6cdh/tree-sitter-scheme            main && \
+    echo "Grammars built:" && ls /opt/tree-sitter-grammars/
+
+# ── Stage 1.5: Compile libqt_shim.a with musl-compatible Alpine g++ ──────────
+# Separate stage so Qt6 cache is preserved when qt_shim.cpp changes
+FROM qt-alpine AS qt-shim-alpine
+
+COPY vendor/qt_shim.cpp vendor/qt_shim.h /tmp/qt-shim-src/
+
+RUN mkdir -p /tmp/qt-shim-out && \
+    QT_CFLAGS="-I/opt/qt6-static/include \
+      -I/opt/qt6-static/include/QtCore \
+      -I/opt/qt6-static/include/QtGui \
+      -I/opt/qt6-static/include/QtWidgets" && \
+    QSCI_FLAGS="-DQT_SCINTILLA_AVAILABLE \
+      -I/opt/qt6-static/include \
+      -I/opt/qt6-static/include/Qsci" && \
+    g++ -c -fPIC -std=c++17 -DJEMACS_CHEZ_SMP \
+      $QT_CFLAGS $QSCI_FLAGS \
+      /tmp/qt-shim-src/qt_shim.cpp \
+      -o /tmp/qt-shim-out/qt_shim_static.o && \
+    ar rcs /tmp/qt-shim-out/libqt_shim.a \
+      /tmp/qt-shim-out/qt_shim_static.o && \
+    printf '#include <QtPlugin>\nQ_IMPORT_PLUGIN(QXcbIntegrationPlugin)\n' \
+      > /tmp/qt-shim-out/qt_static_plugins.cpp && \
+    g++ -c -fPIC -std=c++17 $QT_CFLAGS \
+      /tmp/qt-shim-out/qt_static_plugins.cpp \
+      -o /tmp/qt-shim-out/qt_static_plugins.o && \
+    echo "libqt_shim.a built successfully" && \
+    ls -lh /tmp/qt-shim-out/
+
+# ── Stage 2: jerboa21/jerboa + Qt artifacts → build jemacs-qt ────────────────
+FROM jerboa21/jerboa AS builder
+
+# Install Ubuntu build deps needed for jemacs-qt compilation
+RUN apt-get update && apt-get install -y --no-install-recommends \
+    g++ \
+    libncurses-dev \
+    uuid-dev \
+    libssl-dev \
+    pkg-config \
+    && rm -rf /var/lib/apt/lists/*
+
+# Copy Qt6 static libs and tools from Alpine stage
+COPY --from=qt-alpine /opt/qt6-static /opt/qt6-static
+
+# Copy tree-sitter from Alpine stage
+COPY --from=qt-alpine /opt/tree-sitter-lib /opt/tree-sitter-lib
+COPY --from=qt-alpine /opt/tree-sitter-include /opt/tree-sitter-include
+COPY --from=qt-alpine /opt/tree-sitter-grammars /opt/tree-sitter-grammars
+
+# Copy Alpine-compiled libvterm.a (Ubuntu doesn't ship a static version)
+COPY --from=qt-alpine /usr/lib/libvterm.a /usr/local/lib/
+COPY --from=qt-alpine /usr/include/vterm.h /usr/local/include/
+
+# Copy pre-compiled Qt shim (Alpine-musl g++, so ABI-compatible with musl final link)
+COPY --from=qt-shim-alpine /tmp/qt-shim-out/ /opt/qt-shim/
+
+# Create /opt/chez symlink → /build/chez-musl (musl Chez Scheme)
+RUN ln -s /build/chez-musl /opt/chez
+
+# Copy source and run the in-container build
+COPY . /build/mine/jerboa-emacs
+WORKDIR /build/mine/jerboa-emacs
+
+RUN make linux-qt-local
+
+# Verify
+RUN ./jemacs-qt --version && \
+    file jemacs-qt && \
+    echo "--- Binary info ---" && \
+    ls -lh jemacs-qt
+
+# ── Final stage: extract binary ───────────────────────────────────────────────
+FROM ubuntu:24.04
+COPY --from=builder /build/mine/jerboa-emacs/jemacs-qt /out/jemacs-qt
+CMD ["cat", "/out/jemacs-qt"]
diff --git a/Dockerfile.tui b/Dockerfile.tui
new file mode 100644
index 0000000..98b336b
--- /dev/null
+++ b/Dockerfile.tui
@@ -0,0 +1,29 @@
+# Dockerfile.tui — Build jemacs (TUI) static binary using jerboa21/jerboa
+#
+# 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
+#   chmod +x jemacs
+
+FROM jerboa21/jerboa AS builder
+
+# ── Copy jerboa-emacs source ────────────────────────────────────────────────
+COPY . /build/mine/jerboa-emacs
+
+# ── Build jemacs-musl ────────────────────────────────────────────────────────
+WORKDIR /build/mine/jerboa-emacs
+RUN make linux-tui-local
+
+# ── Verify ───────────────────────────────────────────────────────────────────
+RUN ./jemacs --version && \
+    file jemacs && \
+    echo "--- Binary info ---" && \
+    ls -lh jemacs
+
+# ── Output ───────────────────────────────────────────────────────────────────
+FROM ubuntu:24.04
+COPY --from=builder /build/mine/jerboa-emacs/jemacs /out/jemacs
+CMD ["cat", "/out/jemacs"]
diff --git a/Makefile b/Makefile
index 5aa927b..6a430b6 100644
--- a/Makefile
+++ b/Makefile
@@ -55,6 +55,8 @@ endif
         test-pty test-emacs test-functional test-term-hang \
         docker-deps static-qt static-tui clean-docker check-root \
         build-jemacs-qt-static build-jemacs-tui-static binary macos \
+        linux-tui linux-tui-local \
+        linux-qt linux-qt-local \
         stress-run stress-run-static stress-test stress-burn stress-burn-static \
         test-behavioral
 
@@ -684,7 +686,7 @@ build-jemacs-tui-static: check-root
 	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 liblexilla.a && \
+	make -C /deps/sci-vendor/lexilla/src && \
 	JEMACS_STATIC=1 \
 	CHEZ_DIR=$(CHEZ_MUSL_DIR) \
 	JERBOA_DIR=/deps/jerboa/lib \
@@ -733,6 +735,242 @@ linux-static-tui-docker:
 	           cd /src && make build-jemacs-tui-static'"
 
 # =============================================================================
+# Static TUI via jerboa21/jerboa Docker image (like jerboa-gitsafe)
+# =============================================================================
+
+JERBOA_IMAGE ?= jerboa21/jerboa
+MUSL_CHEZ_DIR = $(shell ls -d /build/chez-musl/lib/csv*/ta6le 2>/dev/null | head -1)
+MUSL_SCHEME = /usr/local/bin/scheme
+
+# 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
+	@chmod +x jemacs
+	@echo ""
+	@ls -lh jemacs
+	@file jemacs
+
+# In-container build target (called inside jerboa21/jerboa)
+# All deps are pre-installed in the image at /build/mine/ and /build/sci-vendor/
+linux-tui-local:
+	@echo "=== Building jemacs static TUI (in-container) ==="
+	rm -f src/.jerbuild-hashes
+	find lib -name '*.so' -o -name '*.wpo' | xargs rm -f 2>/dev/null; true
+	find src/jerboa-emacs -name '*.ss' | sed 's|src/|lib/|; s|\.ss$$|.sls|' | xargs rm -f 2>/dev/null; true
+	find /build/mine/jerboa/lib -name '*.so' -delete 2>/dev/null; true
+	find /build/mine/jerboa/lib -name '*.wpo' -delete 2>/dev/null; true
+	find /build/mine/chez-scintilla -name '*.so' -delete 2>/dev/null; true
+	find /build/mine/chez-pcre2 -name '*.so' -delete 2>/dev/null; true
+	find /build/mine/jerboa-shell -name '*.wpo' -delete 2>/dev/null; true
+	find vendor/gherkin-runtime -name '*.so' -delete 2>/dev/null; true
+	find vendor/gherkin-runtime -name '*.wpo' -delete 2>/dev/null; true
+	find vendor/jerboa-shell -name '*.so' -delete 2>/dev/null; true
+	find vendor/jerboa-shell -name '*.wpo' -delete 2>/dev/null; true
+	@echo "Recompiling jerboa core + prelude..."
+	echo '(import (chezscheme)) (compile-imported-libraries #t) (import (jerboa core)) (import (jerboa prelude))' \
+	  | $(MUSL_SCHEME) --libdirs /build/mine/jerboa/lib -q
+	rm -f /build/mine/jerboa/lib/jerboa/*.wpo
+	$(MUSL_SCHEME) --libdirs /build/mine/jerboa/lib --script /build/mine/jerboa/jerbuild.ss src/ lib/
+	cp vendor/chez-pcre2-ffi-static.ss /build/mine/chez-pcre2/chez-pcre2/ffi.ss
+	$(MUSL_SCHEME) --libdirs /build/mine/chez-pcre2 \
+	  --compile-imported-libraries --script vendor/chez-pcre2-compile-libs.ss
+	rm -f /build/mine/chez-pcre2/chez-pcre2/*.wpo
+	cp vendor/chez-scintilla-ffi-static.sls /build/mine/chez-scintilla/src/chez-scintilla/ffi.sls
+	JEMACS_STATIC=1 $(MUSL_SCHEME) --libdirs /build/mine/chez-scintilla/src \
+	  --compile-imported-libraries --script vendor/chez-scintilla-compile-libs.ss
+	rm -f /build/mine/chez-scintilla/src/chez-scintilla/*.wpo
+	cp vendor/jerboa-net-tcp-static.sls /build/mine/jerboa/lib/std/net/tcp.sls
+	cp vendor/jerboa-net-tcp-raw-static.sls /build/mine/jerboa/lib/std/net/tcp-raw.sls
+	cp vendor/jerboa-net-uri.sls /build/mine/jerboa/lib/std/net/uri.sls
+	cp vendor/jerboa-net-tls-rustls-static.sls /build/mine/jerboa/lib/std/net/tls-rustls.sls
+	rm -f /build/mine/jerboa/lib/std/net/*.wpo /build/mine/jerboa/lib/std/net/*.so
+	cp vendor/jerboa-crypto-native-static.sls /build/mine/jerboa/lib/std/crypto/native.sls
+	rm -f /build/mine/jerboa/lib/std/crypto/*.wpo /build/mine/jerboa/lib/std/crypto/*.so
+	mkdir -p /build/mine/jerboa/lib/std/security
+	cp vendor/jerboa-security-capsicum-static.sls /build/mine/jerboa/lib/std/security/capsicum.sls
+	rm -f /build/mine/jerboa/lib/std/security/*.wpo /build/mine/jerboa/lib/std/security/*.so
+	cp vendor/jerboa-os-landlock-static.sls /build/mine/jerboa/lib/std/os/landlock.sls
+	rm -f /build/mine/jerboa/lib/std/os/landlock.wpo /build/mine/jerboa/lib/std/os/landlock.so
+	JEMACS_STATIC=1 $(MUSL_SCHEME) --libdirs /build/mine/jerboa/lib \
+	  --compile-imported-libraries --script vendor/jerboa-compile-tcp.ss
+	JEMACS_STATIC=1 $(MUSL_SCHEME) --libdirs /build/mine/jerboa/lib \
+	  --compile-imported-libraries --script vendor/jerboa-compile-tcp-raw.ss
+	$(MUSL_SCHEME) --libdirs /build/mine/jerboa/lib \
+	  --compile-imported-libraries --script vendor/jerboa-compile-uri.ss
+	rm -f /build/mine/jerboa/lib/std/net/*.wpo
+	cp vendor/jerboa-repl-static.sls /build/mine/jerboa/lib/std/repl.sls
+	rm -f /build/mine/jerboa/lib/std/repl.wpo /build/mine/jerboa/lib/std/repl.so
+	cd /build/mine/jerboa/lib && $(MUSL_SCHEME) --libdirs /build/mine/jerboa/lib \
+	  --compile-imported-libraries --script $(CURDIR)/vendor/jerboa-compile-repl.ss
+	rm -f /build/mine/jerboa/lib/std/repl.wpo
+	rm -f lib/jerboa/*.wpo lib/jerboa/*.so
+	JEMACS_STATIC=1 $(MUSL_SCHEME) --libdirs lib \
+	  --compile-imported-libraries --script vendor/jerboa-compile-repl-socket.ss
+	rm -f lib/jerboa/*.wpo
+	find /build/mine/jerboa-shell -name '*.wpo' -delete 2>/dev/null; true
+	JEMACS_STATIC=1 \
+	CHEZ_DIR=$(MUSL_CHEZ_DIR) \
+	JERBOA_DIR=/build/mine/jerboa/lib \
+	JSH_DIR=vendor/jerboa-shell/src \
+	GHERKIN_DIR=vendor/gherkin-runtime \
+	CHEZ_PCRE2_DIR=/build/mine/chez-pcre2 \
+	CHEZ_SCINTILLA_DIR=/build/mine/chez-scintilla/src \
+	SCI_VENDOR_DIR=/build/sci-vendor \
+	$(MUSL_SCHEME) \
+	  --libdirs lib:/build/mine/jerboa/lib:vendor/jerboa-shell/src:vendor/gherkin-runtime:/build/mine/chez-pcre2:/build/mine/chez-scintilla/src \
+	  --script build-binary.ss
+	@echo ""
+	@echo "=== jemacs static TUI binary built ==="
+	@ls -lh jemacs
+	@file jemacs
+
+# =============================================================================
+# Static Qt binary via jerboa21/jerboa Docker 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
+	@chmod +x jemacs-qt
+	@echo ""
+	@ls -lh jemacs-qt
+	@file jemacs-qt
+
+# In-container build target (called inside Dockerfile.qt → jerboa21/jerboa stage)
+# 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).
+# /opt/chez → /build/chez-musl symlink provides musl Chez Scheme.
+linux-qt-local:
+	@echo "=== Building jemacs-qt static (in-container) ==="
+	rm -f src/.jerbuild-hashes
+	find lib -name '*.so' -o -name '*.wpo' | xargs rm -f 2>/dev/null; true
+	find src/jerboa-emacs -name '*.ss' | sed 's|src/|lib/|; s|\.ss$$|.sls|' | xargs rm -f 2>/dev/null; true
+	find /build/mine/jerboa/lib -name '*.so' -delete 2>/dev/null; true
+	find /build/mine/jerboa/lib -name '*.wpo' -delete 2>/dev/null; true
+	find /build/mine/chez-scintilla -name '*.so' -delete 2>/dev/null; true
+	find /build/mine/chez-pcre2 -name '*.so' -delete 2>/dev/null; true
+	find /build/mine/jerboa-shell -name '*.wpo' -delete 2>/dev/null; true
+	find vendor/gherkin-runtime -name '*.so' -delete 2>/dev/null; true
+	find vendor/gherkin-runtime -name '*.wpo' -delete 2>/dev/null; true
+	find vendor/jerboa-shell -name '*.so' -delete 2>/dev/null; true
+	find vendor/jerboa-shell -name '*.wpo' -delete 2>/dev/null; true
+	find vendor/chez-ssl -name '*.so' -delete 2>/dev/null; true
+	find vendor/chez-ssl -name '*.wpo' -delete 2>/dev/null; true
+	find vendor/chez-https -name '*.so' -delete 2>/dev/null; true
+	find vendor/chez-https -name '*.wpo' -delete 2>/dev/null; true
+	find vendor/jerboa-aws -name '*.so' -delete 2>/dev/null; true
+	find vendor/jerboa-aws -name '*.wpo' -delete 2>/dev/null; true
+	@echo "Recompiling jerboa core + prelude..."
+	echo '(import (chezscheme)) (compile-imported-libraries #t) (import (jerboa core)) (import (jerboa prelude))' \
+	  | $(MUSL_SCHEME) --libdirs /build/mine/jerboa/lib -q
+	rm -f /build/mine/jerboa/lib/jerboa/*.wpo
+	$(MUSL_SCHEME) --libdirs /build/mine/jerboa/lib --script /build/mine/jerboa/jerbuild.ss src/ lib/
+	# Set up writable chez-qt copy from vendor (compile Scheme library)
+	mkdir -p /tmp/jemacs-build/chez-qt
+	cp -a vendor/chez-qt/. /tmp/jemacs-build/chez-qt/
+	find /tmp/jemacs-build/chez-qt -name '*.so' -delete 2>/dev/null; true
+	find /tmp/jemacs-build/chez-qt -name '*.wpo' -delete 2>/dev/null; true
+	JEMACS_STATIC=1 $(MUSL_SCHEME) --libdirs /tmp/jemacs-build/chez-qt \
+	  --compile-imported-libraries --script /tmp/jemacs-build/chez-qt/compile-libs.ss
+	rm -f /tmp/jemacs-build/chez-qt/chez-qt/*.wpo
+	cp vendor/chez-pcre2-ffi-static.ss /build/mine/chez-pcre2/chez-pcre2/ffi.ss
+	$(MUSL_SCHEME) --libdirs /build/mine/chez-pcre2 \
+	  --compile-imported-libraries --script vendor/chez-pcre2-compile-libs.ss
+	rm -f /build/mine/chez-pcre2/chez-pcre2/*.wpo
+	cp vendor/chez-scintilla-ffi-static.sls /build/mine/chez-scintilla/src/chez-scintilla/ffi.sls
+	JEMACS_STATIC=1 $(MUSL_SCHEME) --libdirs /build/mine/chez-scintilla/src \
+	  --compile-imported-libraries --script vendor/chez-scintilla-compile-libs.ss
+	rm -f /build/mine/chez-scintilla/src/chez-scintilla/*.wpo
+	cp vendor/jerboa-net-tcp-static.sls /build/mine/jerboa/lib/std/net/tcp.sls
+	cp vendor/jerboa-net-tcp-raw-static.sls /build/mine/jerboa/lib/std/net/tcp-raw.sls
+	cp vendor/jerboa-net-uri.sls /build/mine/jerboa/lib/std/net/uri.sls
+	cp vendor/jerboa-net-tls-rustls-static.sls /build/mine/jerboa/lib/std/net/tls-rustls.sls
+	rm -f /build/mine/jerboa/lib/std/net/*.wpo /build/mine/jerboa/lib/std/net/*.so
+	cp vendor/jerboa-crypto-native-static.sls /build/mine/jerboa/lib/std/crypto/native.sls
+	rm -f /build/mine/jerboa/lib/std/crypto/*.wpo /build/mine/jerboa/lib/std/crypto/*.so
+	mkdir -p /build/mine/jerboa/lib/std/security
+	cp vendor/jerboa-security-capsicum-static.sls /build/mine/jerboa/lib/std/security/capsicum.sls
+	rm -f /build/mine/jerboa/lib/std/security/*.wpo /build/mine/jerboa/lib/std/security/*.so
+	cp vendor/jerboa-os-landlock-static.sls /build/mine/jerboa/lib/std/os/landlock.sls
+	rm -f /build/mine/jerboa/lib/std/os/landlock.wpo /build/mine/jerboa/lib/std/os/landlock.so
+	JEMACS_STATIC=1 $(MUSL_SCHEME) --libdirs /build/mine/jerboa/lib \
+	  --compile-imported-libraries --script vendor/jerboa-compile-tcp.ss
+	JEMACS_STATIC=1 $(MUSL_SCHEME) --libdirs /build/mine/jerboa/lib \
+	  --compile-imported-libraries --script vendor/jerboa-compile-tcp-raw.ss
+	$(MUSL_SCHEME) --libdirs /build/mine/jerboa/lib \
+	  --compile-imported-libraries --script vendor/jerboa-compile-uri.ss
+	rm -f /build/mine/jerboa/lib/std/net/*.wpo
+	cp vendor/jerboa-repl-static.sls /build/mine/jerboa/lib/std/repl.sls
+	rm -f /build/mine/jerboa/lib/std/repl.wpo /build/mine/jerboa/lib/std/repl.so
+	cd /build/mine/jerboa/lib && $(MUSL_SCHEME) --libdirs /build/mine/jerboa/lib \
+	  --compile-imported-libraries --script $(CURDIR)/vendor/jerboa-compile-repl.ss
+	rm -f /build/mine/jerboa/lib/std/repl.wpo
+	rm -f lib/jerboa/*.wpo lib/jerboa/*.so
+	JEMACS_STATIC=1 $(MUSL_SCHEME) --libdirs lib \
+	  --compile-imported-libraries --script vendor/jerboa-compile-repl-socket.ss
+	rm -f lib/jerboa/*.wpo
+	# Compile SSL/HTTPS/AWS
+	cp vendor/chez-ssl-static.sls vendor/chez-ssl/src/chez-ssl.sls
+	cp vendor/jerboa-aws-crypto-native.sls vendor/jerboa-aws/jerboa-aws/crypto.sls
+	find vendor/chez-ssl -name '*.so' -delete; find vendor/chez-ssl -name '*.wpo' -delete
+	find vendor/chez-https -name '*.so' -delete; find vendor/chez-https -name '*.wpo' -delete
+	find vendor/jerboa-aws -name '*.so' -delete; find vendor/jerboa-aws -name '*.wpo' -delete
+	JEMACS_STATIC=1 $(MUSL_SCHEME) \
+	  --libdirs vendor/chez-ssl/src:/build/mine/jerboa/lib \
+	  --compile-imported-libraries -q --script vendor/chez-ssl-compile-libs.ss
+	find vendor/chez-ssl -name '*.wpo' -delete
+	JEMACS_STATIC=1 $(MUSL_SCHEME) \
+	  --libdirs vendor/chez-https/src:vendor/chez-ssl/src \
+	  --compile-imported-libraries -q --script vendor/chez-https-compile-libs.ss
+	find vendor/chez-https -name '*.wpo' -delete
+	JEMACS_STATIC=1 $(MUSL_SCHEME) \
+	  --libdirs vendor/jerboa-aws:vendor/chez-https/src:vendor/chez-ssl/src:/build/mine/jerboa/lib \
+	  --compile-imported-libraries -q --script vendor/jerboa-aws-compile-libs.ss
+	find vendor/jerboa-aws -name '*.wpo' -delete
+	# Build tree-sitter C shim objects
+	mkdir -p /tmp/jemacs-build
+	gcc -c -O2 -I/opt/tree-sitter-include -o /tmp/jemacs-build/treesitter_shim.o \
+	    support/treesitter_shim.c -Wall
+	gcc -c -O2 -o /tmp/jemacs-build/treesitter_queries.o \
+	    support/treesitter_queries.c -Wall
+	# Run the main Qt build script
+	JEMACS_STATIC=1 \
+	CHEZ_DIR=$(MUSL_CHEZ_DIR) \
+	JERBOA_DIR=/build/mine/jerboa/lib \
+	JSH_DIR=vendor/jerboa-shell/src \
+	GHERKIN_DIR=vendor/gherkin-runtime \
+	CHEZ_PCRE2_DIR=/build/mine/chez-pcre2 \
+	CHEZ_SCINTILLA_DIR=/build/mine/chez-scintilla/src \
+	CHEZ_QT_DIR=/tmp/jemacs-build/chez-qt \
+	CHEZ_QT_SHIM_DIR=/opt/qt-shim \
+	JSH_COREUTILS_LIB=vendor/libjsh_coreutils_stub.a \
+	JAWS_DIR=vendor/jerboa-aws \
+	CHEZ_SSL_DIR=vendor/chez-ssl \
+	CHEZ_HTTPS_DIR=vendor/chez-https/src \
+	TREE_SITTER_INCLUDE=/opt/tree-sitter-include \
+	TREE_SITTER_LIB=/opt/tree-sitter-lib \
+	TREE_SITTER_GRAMMARS=/opt/tree-sitter-grammars \
+	TREE_SITTER_SHIM_OBJ=/tmp/jemacs-build/treesitter_shim.o \
+	TREE_SITTER_QUERIES_OBJ=/tmp/jemacs-build/treesitter_queries.o \
+	PKG_CONFIG_PATH=/opt/qt6-static/lib/pkgconfig \
+	$(MUSL_SCHEME) \
+	  --libdirs lib:/build/mine/jerboa/lib:vendor/jerboa-shell/src:vendor/gherkin-runtime:/build/mine/chez-pcre2:/build/mine/chez-scintilla/src:/tmp/jemacs-build/chez-qt:vendor/jerboa-aws:vendor/chez-ssl/src:vendor/chez-https/src \
+	  --script build-binary-qt.ss
+	@echo ""
+	@echo "=== jemacs-qt static binary built ==="
+	@ls -lh jemacs-qt
+	@file jemacs-qt
+
+# =============================================================================
 # Stress testing targets
 # =============================================================================
 
diff --git a/build-binary.ss b/build-binary.ss
index d169592..f1de191 100644
--- a/build-binary.ss
+++ b/build-binary.ss
@@ -439,7 +439,7 @@
          (include-dir chez-dir)
          (gen-cmd
            (format
-             "{ { cat ~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; 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 -path '*/qt/*' -prune -o -name '*.sls' -print -o -name '*.ss' -print | xargs cat 2>/dev/null; } | \
 sed 's/;;.*//' | grep -oE '(foreign-procedure|foreign-entry\\?) \"[^\"]*\"' | sed 's/.* \"//;s/\"//'; \
 { cat ~a; } | sed 's/;;.*//' | grep -o 'define-optional-ffi [^ ]* \"[^\"]*\"' | sed 's/.*define-optional-ffi [^ ]* \"//;s/\"//'; \
 find ~a -name '*.sls' -o -name '*.ss' | \
@@ -451,7 +451,9 @@ 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/tui_ffi_syms.txt && \
+grep -v '^__error$' | grep -v '^ts_shim_' | grep -v '^ts_parser_' | grep -v '^ts_tree_' | grep -v '^ts_node_' | \
+grep -v '^ts_query_' | grep -v '^ts_language_' | grep -v '^tree_sitter_' | \
+grep -v '^qt_' | grep -v '^QRcode_' | grep -v '^chez_tcp_' | grep -v '^chez_ssl_' | grep -v '^chez_qt_' | grep -v '^chez_conn_' > /tmp/tui_ffi_syms.txt && \
 awk '\
 BEGIN{ print \"/* Auto-generated — do not edit */\"; \
        print \"#include \\\"scheme.h\\\"\"; print \"\"; } \
@@ -581,12 +583,12 @@ tui_static_symbols.o \
 ~a \
 -L~a -lkernel -llz4 -lz \
 -Wl,--whole-archive ~a ~a ~a -Wl,--no-whole-archive \
-~a ~a \
+~a ~a ~a \
 -lm -ldl -lpthread -luuid -lstdc++ 2>&1"
                       jsh-coreutils-lib
                       chez-dir
                       sci-a lex-a tbx-a
-                      pcre2-libs ncurses-libs)))
+                      pcre2-libs ncurses-libs vterm-libs)))
     (printf "  ~a~n" cmd)
     (unless (= 0 (system cmd))
       (display "Error: Static link failed\n")
diff --git a/jemacs-main.c b/jemacs-main.c
index d35aefa..37db53a 100644
--- a/jemacs-main.c
+++ b/jemacs-main.c
@@ -85,9 +85,10 @@ int main(int argc, char *argv[]) {
     Sbuild_heap(NULL, NULL);
 
 #ifdef JEMACS_STATIC_BUILD
-    /* Static builds: register FFI symbols compiled into the binary.
-     * In musl static builds dlopen(NULL) is a stub, so foreign-procedure
-     * can't find symbols by name at runtime. We pre-register them here. */
+    /* Static builds: tell Scheme not to call load-shared-object, and
+     * register FFI symbols compiled into the binary so foreign-procedure
+     * can find them (dlopen(NULL) is a stub in musl static builds). */
+    setenv("JEMACS_STATIC", "1", 1);
     extern void register_static_foreign_symbols(void);
     register_static_foreign_symbols();
 #endif
diff --git a/jemacs-ssh-agent-stub.c b/jemacs-ssh-agent-stub.c
new file mode 100644
index 0000000..5994d23
--- /dev/null
+++ b/jemacs-ssh-agent-stub.c
@@ -0,0 +1,3 @@
+/* Stub — jemacs doesn't use ssh-agent */
+void chez_ssh_agent_stop(void) {}
+int chez_ssh_agent_is_running(void) { return 0; }
diff --git a/jemacs-tls-stubs.c b/jemacs-tls-stubs.c
new file mode 100644
index 0000000..12b48e1
--- /dev/null
+++ b/jemacs-tls-stubs.c
@@ -0,0 +1,17 @@
+/* Stub — jemacs TUI doesn't use rustls TLS */
+#include <stddef.h>
+#include <stdint.h>
+uint64_t jerboa_tls_server_new(const char *c, const char *k) { return 0; }
+uint64_t jerboa_tls_server_new_mtls(const char *c, const char *k, const char *ca) { return 0; }
+void jerboa_tls_server_free(uint64_t s) {}
+uint64_t jerboa_tls_accept(uint64_t s, int fd) { return 0; }
+uint64_t jerboa_tls_connect(const char *h, int p) { return 0; }
+uint64_t jerboa_tls_connect_pinned(const char *h, int p, const uint8_t *fp, size_t fplen) { return 0; }
+uint64_t jerboa_tls_connect_mtls(const char *h, int p, const char *c, const char *k, const char *ca) { return 0; }
+int jerboa_tls_read(uint64_t s, uint8_t *buf, uint64_t len) { return -1; }
+int jerboa_tls_write(uint64_t s, const uint8_t *buf, uint64_t len) { return -1; }
+int jerboa_tls_flush(uint64_t s) { return -1; }
+void jerboa_tls_close(uint64_t s) {}
+int jerboa_tls_set_nonblock(uint64_t s, int nb) { return -1; }
+int jerboa_tls_get_fd(uint64_t s) { return -1; }
+size_t jerboa_last_error(uint8_t *buf, size_t len) { return 0; }
diff --git a/lib/jerboa-emacs/async.sls b/lib/jerboa-emacs/async.sls
index 81c2d6f..361978c 100644
--- a/lib/jerboa-emacs/async.sls
+++ b/lib/jerboa-emacs/async.sls
@@ -552,8 +552,8 @@
        (let ([v (hashtable-ref
                   cache
                   key
-                  '#{miss dtdkom0leeg8kp0f535kz6s40-1})])
-         (if (eq? v '#{miss dtdkom0leeg8kp0f535kz6s40-2})
+                  '#{miss jdswg0innsj0c7bc23vlvqgfo-1})])
+         (if (eq? v '#{miss jdswg0innsj0c7bc23vlvqgfo-2})
              (if (null? default) #f (car default))
              v)))
   (def (weak-cache-set! cache key value)
diff --git a/lib/jerboa-emacs/qt/window.sls b/lib/jerboa-emacs/qt/window.sls
index 8b04afc..5c9e9fd 100644
--- a/lib/jerboa-emacs/qt/window.sls
+++ b/lib/jerboa-emacs/qt/window.sls
@@ -399,36 +399,6 @@
                                             (+ i 1)
                                             (cons 500 acc))))))))
                             (qt-edit-window-editor new-win))]
-                         [(split-leaf? (qt-frame-root fr))
-                          (qt-splitter-set-orientation!
-                            root-spl
-                            orientation)
-                          (let* ([new-win (qt-make-new-window!
-                                            root-spl
-                                            new-buf)]
-                                 [new-leaf (make-split-leaf new-win)]
-                                 [new-node (make-split-node
-                                             orientation
-                                             root-spl
-                                             (list cur-leaf new-leaf))])
-                            (qt-frame-root-set! fr new-node)
-                            (qt-frame-windows-set!
-                              fr
-                              (split-tree-flatten (qt-frame-root fr)))
-                            (let ([new-idx (list-index
-                                             (lambda (w) (eq? w new-win))
-                                             (qt-frame-windows fr))])
-                              (qt-frame-current-idx-set!
-                                fr
-                                (or new-idx 0)))
-                            (qt-window-process-events!)
-                            (with-catch
-                              (lambda (_e) (void))
-                              (lambda ()
-                                (qt-splitter-set-sizes!
-                                  root-spl
-                                  (list 500 500))))
-                            (qt-edit-window-editor new-win))]
                          [else
                           (let* ([parent-spl (if parent
                                                  (split-node-splitter
diff --git a/vendor/jerboa-net-tls-rustls-static.sls b/vendor/jerboa-net-tls-rustls-static.sls
new file mode 100644
index 0000000..be5a8cd
--- /dev/null
+++ b/vendor/jerboa-net-tls-rustls-static.sls
@@ -0,0 +1,57 @@
+#!chezscheme
+;;; (std net tls-rustls) — static stub for jemacs TUI build
+;;;
+;;; The TUI binary does not use TLS. This stub exports the correct interface
+;;; but raises an error if any function is actually called at runtime.
+;;; It avoids foreign-procedure so the static binary does not need the
+;;; Rust rustls library (libjerboa_native).
+
+(library (std net tls-rustls)
+  (export
+    rustls-server-ctx-new
+    rustls-server-ctx-new-mtls
+    rustls-server-ctx-free
+    rustls-accept
+    rustls-connect
+    rustls-connect-pinned
+    rustls-connect-mtls
+    rustls-read
+    rustls-write
+    rustls-flush
+    rustls-close
+    rustls-set-nonblock
+    rustls-get-fd)
+
+  (import (chezscheme))
+
+  (define (tls-not-available who . args)
+    (error who "TLS not available in static jemacs build"))
+
+  (define (rustls-server-ctx-new cert-path key-path)
+    (tls-not-available 'rustls-server-ctx-new))
+  (define (rustls-server-ctx-new-mtls cert-path key-path client-ca-path)
+    (tls-not-available 'rustls-server-ctx-new-mtls))
+  (define (rustls-server-ctx-free handle)
+    (tls-not-available 'rustls-server-ctx-free))
+  (define (rustls-accept server-ctx tcp-fd)
+    (tls-not-available 'rustls-accept))
+  (define (rustls-connect host port)
+    (tls-not-available 'rustls-connect))
+  (define (rustls-connect-pinned host port pin-sha256)
+    (tls-not-available 'rustls-connect-pinned))
+  (define (rustls-connect-mtls host port cert-path key-path ca-cert-path)
+    (tls-not-available 'rustls-connect-mtls))
+  (define (rustls-read handle buf max-len)
+    (tls-not-available 'rustls-read))
+  (define (rustls-write handle buf len)
+    (tls-not-available 'rustls-write))
+  (define (rustls-flush handle)
+    (tls-not-available 'rustls-flush))
+  (define (rustls-close handle)
+    (tls-not-available 'rustls-close))
+  (define (rustls-set-nonblock handle nonblock?)
+    (tls-not-available 'rustls-set-nonblock))
+  (define (rustls-get-fd handle)
+    (tls-not-available 'rustls-get-fd))
+
+  ) ;; end library