#!/usr/bin/env bash # build-soul-from-dist.sh — build a deployable soul from the SAME input CI compiles. # # THE PROBLEM THIS CLOSES: until now, deploys were built by build-soul.sh, which # compiles a scratch amalgam and never touches dist/soul.c. CI compiles dist/soul.c. # Two lineages. On 2026-08-09 the committed input fell 2,761 bytes behind the sources # while three binaries built the other way were installed on the operator machine — # so "what runs" and "what the repo says builds" were different artifacts again, # which is the whole of #133 and #111 wearing new clothes. # # This builds from dist/soul.c with CI's own flags, after asserting that dist/soul.c # actually matches the .el sources, and writes a provenance sidecar so a deployer can # refuse anything of unknown origin. # # -rdynamic and -DHAVE_CURL are copied from .gitea/workflows/ci.yaml deliberately. # The CI comment explains -rdynamic: without it the runtime cannot resolve its HTTP # handler by name via dlsym and the binary serves nothing on every route. # # usage: build-soul-from-dist.sh set -u OUT="${1:?usage: build-soul-from-dist.sh }" ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" RUNTIME="$ROOT/vendor/el-runtime/v1.0.0-20260501" cd "$ROOT" || exit 2 echo "[build-from-dist] GATE: does dist/soul.c match the sources?" if ! ./tools/soulc-stamp.sh --check; then echo "[build-from-dist] REFUSING — the build input is stale. Regenerate and stamp first." >&2 exit 9 fi [ -f "$RUNTIME/el_runtime.c" ] || { echo "pinned runtime missing at $RUNTIME" >&2; exit 2; } echo "[build-from-dist] compiling dist/soul.c with CI's flags" cc -O2 -DHAVE_CURL -rdynamic \ -I"$RUNTIME" \ dist/soul.c \ "$RUNTIME/el_runtime.c" \ -lcurl -lpthread -lm \ -o "$OUT" || { echo "[build-from-dist] COMPILE FAILED" >&2; exit 3; } # Provenance sidecar: what a deployer checks before installing anything. SRC_SHA="$(shasum -a 256 dist/soul.c | awk '{print $1}')" STAMP_SHA="$(shasum -a 256 dist/soul.c.stamp | awk '{print $1}')" COMMIT="$(git rev-parse HEAD 2>/dev/null || echo unknown)" DIRTY="clean"; [ -n "$(git status --porcelain -- '*.el' dist/soul.c 2>/dev/null)" ] && DIRTY="DIRTY" cat > "$OUT.provenance" < $OUT ($(wc -c < "$OUT" | tr -d ' ') bytes)" echo "[build-from-dist] provenance -> $OUT.provenance (commit ${COMMIT:0:8}, worktree $DIRTY)"