Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
c49871d
feat: add haskell-language-server 2.14.0.0
0chroma Jun 2, 2026
5d656de
Update glibc to 2.43
bryan-minimal Jun 11, 2026
30cef78
Update binutils to 2.46.1
bryan-minimal Jun 11, 2026
4cf505f
gcc: -Wno-error=discarded-qualifiers for the glibc-2.43 C23 rebuild
bryan-minimal Jun 11, 2026
cdafc7b
Merge remote-tracking branch 'origin/main' into update-base-soup-2026…
bryan-minimal Jun 16, 2026
37409af
make stack: fleet-wide -Wno-error=discarded-qualifiers for the glibc-…
bryan-minimal Jun 16, 2026
40e3d4a
make stack: correct comment — fleet lever is durable, gcc-16 only ret…
bryan-minimal Jun 16, 2026
09ca7fd
libxcrypt: -Wno-error=discarded-qualifiers for glibc 2.43 C23 const F…
bryan-minimal Jun 17, 2026
38d0c01
elfutils: --disable-werror for glibc 2.43 C23 const FTBFS
bryan-minimal Jun 17, 2026
0585928
elfutils: correct fix — -Wno-error=discarded-qualifiers in CFLAGS (--…
bryan-minimal Jun 17, 2026
bd5bffd
strace: -Wno-error=discarded-qualifiers for glibc 2.43 C23 const FTBFS
bryan-minimal Jun 17, 2026
e966a17
or-tools: switch SCIP TPI tny->omp to dodge tinycthread/glibc-2.43 th…
bryan-minimal Jun 17, 2026
690a6cf
unzip: migrate EOL Info-ZIP -> libarchive bsdunzip (+ new libarchive …
bryan-minimal Jun 17, 2026
9669f16
libarchive: mark build.sh executable (CI: build scripts are executable)
bryan-minimal Jun 17, 2026
5b5e025
unzip: wrapper script execing bsdunzip (symlink escaped package output)
bryan-minimal Jun 17, 2026
229b1ba
virtio-linux: pin KBUILD_BUILD_* for reproducible kernel image
bryan-minimal Jun 17, 2026
9a4219d
unzip: apply Debian backported CVE patches (keep Info-ZIP, drop bsdun…
bryan-minimal Jun 17, 2026
9028fbe
unzip: actually wire the Debian patch series (prior commit missed the…
bryan-minimal Jun 17, 2026
1e0a786
feat(microvm-rootfs): add git to runtime deps
norrietaylor Jun 17, 2026
c1eae6b
refactor(microvm-rootfs): drop socat and the standalone bring-up init
norrietaylor Jun 17, 2026
78a5137
Update binutils-arm-none-eabi to 2.46.1
gominimal-pkgmgr-mgr[bot] Jun 17, 2026
258b817
agent-browser: make Rust CLI + pnpm tree reproducible
bryan-minimal Jun 17, 2026
f4d2669
nspr: pin build timestamp for reproducible library
bryan-minimal Jun 17, 2026
4e3d141
Merge branch 'main' into feat/microvm-rootfs-add-git
norrietaylor Jun 17, 2026
c86e47e
nspr: drop SOURCE_DATE_EPOCH=0 export (sandbox sets it)
bryan-minimal Jun 17, 2026
7c18e0b
docs(AGENTS): fix reproducibility guidance — sandbox sets SOURCE_DATE…
bryan-minimal Jun 17, 2026
c125b46
Merge commit 'refs/pull/214/head' of https://github.com/gominimal/pkg…
Jun 17, 2026
1dcc5f4
Merge commit 'refs/pull/238/head' of https://github.com/gominimal/pkg…
Jun 17, 2026
f79055c
Merge commit 'refs/pull/260/head' of https://github.com/gominimal/pkg…
Jun 17, 2026
62095e5
Merge commit 'refs/pull/261/head' of https://github.com/gominimal/pkg…
Jun 17, 2026
03a1c19
Merge commit 'refs/pull/262/head' of https://github.com/gominimal/pkg…
Jun 17, 2026
b3d0dc7
Merge commit 'refs/pull/263/head' of https://github.com/gominimal/pkg…
Jun 17, 2026
588782c
Merge commit 'refs/pull/264/head' of https://github.com/gominimal/pkg…
Jun 17, 2026
75d9816
Merge commit 'refs/pull/265/head' of https://github.com/gominimal/pkg…
Jun 17, 2026
3eb1dce
Merge commit 'refs/pull/266/head' of https://github.com/gominimal/pkg…
Jun 17, 2026
881e7ce
haskell-language-server: add reproducibility flags to build.sh
Jun 17, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 12 additions & 8 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -638,23 +638,27 @@ cp target/release/my-tool $OUTPUT_DIR/usr/bin/
### Reproducibility (required)

Two builds of the same source must produce **byte-identical** output — the build cache is
content-addressed and can't trust non-reproducible artifacts. The sandbox does **not** pin
the clock or inject flags for you; determinism is `build.sh`'s responsibility. Apply the
recipe for your build system on top of the pattern above. Background and the full taxonomy
of non-determinism: <https://reproducible-builds.org/>.
content-addressed and can't trust non-reproducible artifacts. The build sandbox already
exports `SOURCE_DATE_EPOCH=0` and `PYTHONHASHSEED=0` for you, so **do not set those
yourself** — `minimal-check` rejects it. Compiler/linker determinism flags are otherwise
`build.sh`'s responsibility. Apply **only the bullet that matches your build system** —
these are per-stack recipes, not a checklist to run all of. Background and the full
taxonomy of non-determinism: <https://reproducible-builds.org/>.

- **C / C++:** `CFLAGS="… -ffile-prefix-map=$(pwd)=/builddir -gno-record-gcc-switches"`,
`CXXFLAGS="$CFLAGS"`, `LDFLAGS="-Wl,--build-id=none"`, `export ARFLAGS=Drc`
(autotools: also pass `--enable-deterministic-archives` to `./configure`).
(autotools: also pass `--enable-deterministic-archives` to `./configure`; post-install,
drop libtool archives with `find "$OUTPUT_DIR" -name '*.la' -delete`).
- **Go:** every `go build`/`go install`: `-trimpath -ldflags "-buildid="`
(add `-buildvcs=false` if the source tree contains a `.git` directory).
- **Rust:** `RUSTFLAGS="-C linker=gcc --remap-path-prefix=$(pwd)=/builddir --remap-path-prefix=$HOME/.cargo=/cargo"`;
if the binary still differs in `.text`/`.rodata`, also add `-C codegen-units=1` and
`export CONST_RANDOM_SEED=0`.
- **Linux kernel:** `export KBUILD_BUILD_TIMESTAMP=@0 KBUILD_BUILD_USER=builder KBUILD_BUILD_HOST=minimal`.
- **Embedded timestamps** (configure scripts, generated docs, `__DATE__`/`__TIME__`):
`export SOURCE_DATE_EPOCH=0` (and `PYTHONHASHSEED=0` for Python-based build steps).
- **Post-install:** drop libtool archives — `find "$OUTPUT_DIR" -name '*.la' -delete`.
- **A build that bakes in its own wall-clock time** despite `SOURCE_DATE_EPOCH` (version
strings, generated headers): pin that specific stamp rather than re-exporting
`SOURCE_DATE_EPOCH`. For example `nspr` overrides the make variables its version header
is generated from (`SH_DATE` from `$SOURCE_DATE_EPOCH`, `SH_NOW=` to omit the build time).

**Verify:** build the package twice and compare the two `$OUTPUT_DIR` trees — they must be
byte-for-byte identical. When they differ, the diff points at the cause (a timestamp, a
Expand Down
7 changes: 6 additions & 1 deletion packages/agent-browser/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ set -e

export CC=gcc
export LD=gcc
export RUSTFLAGS="-C linker=gcc"
export RUSTFLAGS="-C linker=gcc --remap-path-prefix=$(pwd)=/builddir --remap-path-prefix=$HOME/.cargo=/cargo -C codegen-units=1"
export CONST_RANDOM_SEED=0 # pin ahash/const-random compile-time seed

# Install JS deps (skip postinstall which downloads pre-built binary).
# Use the hoisted node-linker so node_modules is a flat, self-contained
Expand Down Expand Up @@ -34,6 +35,10 @@ cp cli/target/release/agent-browser bin/agent-browser-${PLATFORM}
install -d $OUTPUT_DIR/usr/bin
install -d $OUTPUT_DIR/usr/libexec/agent-browser

# pnpm bakes wall-clock timestamps into its node_modules state files
# (.modules.yaml `prunedAt`, .pnpm-workspace-state-v1.json `lastValidatedTimestamp`)
# — non-deterministic and not needed at runtime. Drop them before packaging.
rm -f node_modules/.modules.yaml node_modules/.pnpm-workspace-state-v1.json
cp -R dist bin node_modules package.json $OUTPUT_DIR/usr/libexec/agent-browser/

cat > $OUTPUT_DIR/usr/bin/agent-browser << EOF
Expand Down
4 changes: 2 additions & 2 deletions packages/binutils-arm-none-eabi/build.ncl
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ let gcc = import "../gcc/build.ncl" in
let glibc = import "../glibc/build.ncl" in
let zlib = import "../zlib/build.ncl" in

let version = "2.43.1" in
let version = "2.46.1" in
{
name = "binutils-arm-none-eabi",
build_deps = [
{ file = "build.sh" } | Local,
{
url = "https://mirrors.kernel.org/gnu/binutils/binutils-%{version}.tar.xz",
sha256 = "13f74202a3c4c51118b797a39ea4200d3f6cfbe224da6d1d95bb938480132dfd"
sha256 = "e127a709cba24c76de8936cb7083dd768f28cd37eb010492e2f19b71eb1294e4"
} | Source,
base-bootstrap,
make,
Expand Down
8 changes: 7 additions & 1 deletion packages/elfutils/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,13 @@ case $(uname -m) in
aarch64) MARCH="-march=armv8-a" ;;
*) MARCH="" ;;
esac
export CFLAGS="$MARCH -O2 -pipe -gno-record-gcc-switches -Wl,--build-id=none -ffile-prefix-map=$(pwd)=/builddir"
# -Wno-error=discarded-qualifiers: glibc 2.43's ISO C23 const-preserving
# bsearch/strchr-family return const for const args; elfutils assigns those to
# plain pointers (libcpu/riscv_disasm.c known_csrs bsearch) under its default-on
# -Werror. elfutils' configure has no --disable-werror in this version, but
# automake emits `$(AM_CFLAGS) $(CFLAGS)`, so a CFLAGS flag lands after
# elfutils' AM_CFLAGS -Werror and wins. Same glibc-2.43 C23 FTBFS class as #238.
export CFLAGS="$MARCH -O2 -pipe -gno-record-gcc-switches -Wl,--build-id=none -ffile-prefix-map=$(pwd)=/builddir -Wno-error=discarded-qualifiers"
export LDFLAGS="-Wl,--build-id=none"
export ARFLAGS=Drc
export CXXFLAGS="${CFLAGS}"
Expand Down
28 changes: 28 additions & 0 deletions packages/gcc/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,34 @@ export LDFLAGS="-Wl,--build-id=none"
export CXXFLAGS="${CFLAGS}"
export ARFLAGS=Drc

# glibc 2.43 implements ISO C23 const-preserving string macros: strchr,
# strrchr, strstr, memchr, etc. now return a `const char *` when given a
# `const char *`. gcc-15.2.0 predates this, so its libgomp source
# (libgomp/affinity-fmt.c: `char *q = strchr (p + 1, '}');`) assigns the
# result to a plain `char *` and trips -Werror=discarded-qualifiers, failing
# the build. The pointer is never written through (only used for `q - p`), so
# this is a source-pedantry mismatch, not a runtime bug.
#
# Downgrade ONLY that one warning (everything else stays -Werror), for gcc's
# own build only — the produced compiler is unaffected. CFLAGS_FOR_TARGET is
# the documented knob for target libraries like libgomp (BOOT_CFLAGS/CFLAGS
# don't reach them); see https://gcc.gnu.org/install/build.html. CFLAGS keeps
# it for gcc proper defensively.
#
# This is the interim escape hatch; gcc-16.1.0 fixes this upstream (it builds
# cleanly against glibc 2.43 — LFS pairs them with no workaround), so the
# clean follow-up is to bump gcc to 16. Refs:
# - glibc 2.43 C23 const-preserving macros:
# https://lists.gnu.org/archive/html/info-gnu/2026-01/msg00005.html
# - upstream gcc libgomp fix ("Fix GCC build after glibc@cd748a6"):
# https://www.mail-archive.com/gcc-patches@gcc.gnu.org/msg389139.html
# - LFS GCC-16.1.0 (builds against glibc 2.43, no const workaround):
# https://www.linuxfromscratch.org/lfs/view/development/chapter08/gcc.html
export CFLAGS="${CFLAGS} -Wno-error=discarded-qualifiers"
export CXXFLAGS="${CFLAGS}"
export CFLAGS_FOR_TARGET="${CFLAGS}"
export CXXFLAGS_FOR_TARGET="${CXXFLAGS}"

../configure \
--prefix=/usr \
--libdir=/usr/lib \
Expand Down
4 changes: 2 additions & 2 deletions packages/glibc/build.ncl
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,15 @@ let all_outputs = {
}
in

let version = "2.42" in
let version = "2.43" in
{
name = "glibc",
build_deps = [
{ file = "build.sh" } | Local,
{
# Downloadable from: https://ftp.gnu.org/gnu/glibc/
url = "gs://minimal-staging-archives/glibc-%{version}.tar.xz",
sha256 = "d1775e32e4628e64ef930f435b67bb63af7599acb6be2b335b9f19f16509f17f"
sha256 = "d9c86c6b5dbddb43a3e08270c5844fc5177d19442cf5b8df4be7c07cd5fa3831"
} | Source,
# base
bash,
Expand Down
64 changes: 64 additions & 0 deletions packages/haskell-language-server/build.ncl
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
let { Attrs, BuildSpec, Local, Needs, OutputBin, OutputLib, Source, Test, .. } = import "minimal.ncl" in

let base = import "../base/build.ncl" in
let cabal = import "../cabal/build.ncl" in
let ghc = import "../ghc/build.ncl" in
let glibc = import "../glibc/build.ncl" in

let version = "2.14.0.0" in

{
name = "haskell-language-server",

build_deps = [
{ file = "build.sh" } | Local,
{
url = "https://github.com/haskell/haskell-language-server/archive/refs/tags/%{version}.tar.gz",
sha256 = "02fdd2ea8048cddce0872f78fcc4ba15558f751333c97d24b9abadac8ee27dcb",
extract = true,
strip_prefix = "haskell-language-server-%{version}",
} | Source,
base,
ghc,
cabal,
],

runtime_deps = [glibc],

needs =
{
dns = {},
internet = {},
} | Needs,

cmd = "./build.sh",

build_args = {
include version,
},

outputs = {
hls = { glob = "usr/bin/haskell-language-server" } | OutputBin,
libs = { glob = "usr/lib/*.so*" } | OutputLib,
},

attrs =
{
upstream_version = version,
source_provenance = {
category = 'GithubRepo,
owner = "haskell",
repo = "haskell-language-server",
},
build_cost_multiple = 4,
} | Attrs,

tests = {
version_check =
{
class = 'Standalone,
test_deps = [],
cmds = [["haskell-language-server", "--version"]],
} | Test,
},
} | BuildSpec
41 changes: 41 additions & 0 deletions packages/haskell-language-server/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#!/bin/bash
set -euo pipefail

# The source tarball is already extracted with strip_prefix, so we're in the source root

# Build HLS for the GHC version available in the sandbox
export GHC="$(command -v ghc)"
export CABAL="$(command -v cabal)"

# Update cabal package index
cabal update

# Reproducibility: strip embedded build paths from GHC-produced object files and
# suppress the linker's random build-id. These are the Haskell analogues of
# -ffile-prefix-map and -Wl,--build-id=none for C (see AGENTS.md §Reproducibility).
# -optc flags reach the C compiler GHC invokes for C stubs / Cmm; -optl reaches ld.
GHC_REPRO_OPTS="-optc-ffile-prefix-map=$(pwd)=/builddir -optl-Wl,--build-id=none"

# Build HLS with the available GHC version
cabal build \
--ghc-options="-j$(nproc) $GHC_REPRO_OPTS" \
exe:haskell-language-server

# Install to OUTPUT_DIR
mkdir -p "$OUTPUT_DIR"/usr/bin
mkdir -p "$OUTPUT_DIR"/usr/lib

# Find and copy the built binary from cabal's build directory
HLS_BIN=$(cabal list-bin exe:haskell-language-server)
cp "$HLS_BIN" "$OUTPUT_DIR"/usr/bin/

# Strip the linker build-id from the installed binary (cabal may re-link without
# our -optl flag for the final exe depending on version; belt-and-suspenders).
strip --remove-section=.note.gnu.build-id "$OUTPUT_DIR"/usr/bin/haskell-language-server 2>/dev/null || true

# Copy all shared Haskell libraries the binary depends on
for lib in $(ldd "$HLS_BIN" | grep '\.so' | awk '{print $3}'); do
if [ -n "$lib" ] && [ -f "$lib" ]; then
cp "$lib" "$OUTPUT_DIR"/usr/lib/
fi
done
9 changes: 8 additions & 1 deletion packages/libxcrypt/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,14 @@ case $(uname -m) in
aarch64) MARCH="-march=armv8-a" ;;
*) MARCH="" ;;
esac
export CFLAGS="$MARCH -O2 -pipe -gno-record-gcc-switches -ffile-prefix-map=$(pwd)=/builddir"
# -Wno-error=discarded-qualifiers: glibc 2.43's ISO C23 const-preserving
# strchr/strstr/memchr return `const char *` for a `const char *` arg, which
# libxcrypt's crypt-{gost,sm3}-yescrypt.c assign to a plain `char *` — tripping
# libxcrypt's own configure-enabled -Werror. This package has a hand-written
# build.sh (not the make stack), so the stacks/make/stack.ncl fleet lever can't
# reach it; we downgrade only that one warning here, landing after libxcrypt's
# -Werror on the compile line so the later flag wins. Same class as #238.
export CFLAGS="$MARCH -O2 -pipe -gno-record-gcc-switches -ffile-prefix-map=$(pwd)=/builddir -Wno-error=discarded-qualifiers"
export LDFLAGS="-Wl,--build-id=none"
export CXXFLAGS="${CFLAGS}"

Expand Down
18 changes: 10 additions & 8 deletions packages/microvm-rootfs/build.ncl
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
let { BuildSpec, Local, OutputData, .. } = import "minimal.ncl" in
let base = import "../base/build.ncl" in
let e2fsprogs = import "../e2fsprogs/build.ncl" in
let socat = import "../socat/build.ncl" in
let git = import "../git/build.ncl" in
{
name = "microvm-rootfs",

# A read-only ext4 guest rootfs for a libkrun microVM. build.sh snapshots the
# runtime userland (base + socat), drops in a small bring-up init, prunes
# build-only bulk, and packs an ext4 image to load as a virtio-blk block
# device. e2fsprogs is build-only — it provides mke2fs to pack the image — and
# its files are removed from the tree before packing, so the runtime image
# ships only the runtime closure.
# A read-only ext4 guest userland for a libkrun microVM. build.sh snapshots
# the runtime closure (base + git), prunes build-only bulk, and packs an ext4
# image loaded as a virtio-blk block device (/dev/vda). The guest minimald
# ships as the initramfs pid-1, mounts this image, and chroots into it — there
# is no standalone init in the image itself. e2fsprogs is build-only (mke2fs to
# pack the image) and its files are removed before packing, so the image ships
# only the runtime closure. git is in the closure because the in-guest minimald
# session bring-up inits a minimal context that shells out to git.
runtime_deps = [
base,
socat,
git,
],
build_deps = [
{ file = "build.sh" } | Local,
Expand Down
60 changes: 14 additions & 46 deletions packages/microvm-rootfs/build.sh
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
#!/bin/bash
# Assemble a libkrun microVM guest rootfs as a read-only ext4 image.
# Assemble a libkrun microVM guest userland as a read-only ext4 image.
#
# The build sandbox hardlinks this package's runtime closure (base + socat +
# their libs) and its build-only deps (e2fsprogs, for mke2fs) into the sandbox
# root at standard paths. We snapshot the userland into a staging tree, drop the
# build-only e2fsprogs files, add a small bring-up init, prune bulk, and pack an
# ext4 image with mke2fs. The image is loaded as a virtio-blk block device (e.g.
# root=/dev/vda); a block root has no overlaid init, so the kernel runs the init
# below directly. devtmpfs auto-mounts /dev, giving the init /dev/vsock.
# The build sandbox hardlinks this package's runtime closure (base + git + their
# libs) and its build-only deps (e2fsprogs, for mke2fs) into the sandbox root at
# standard paths. We snapshot the userland into a staging tree, drop the
# build-only e2fsprogs files, prune bulk, and pack an ext4 image with mke2fs. The
# image is loaded as a virtio-blk block device (/dev/vda); the guest minimald
# ships as the initramfs pid-1, mounts this image, and chroots into it, so the
# image itself carries no standalone init.
set -euo pipefail

STAGE="$(pwd)/stage"
Expand All @@ -24,26 +24,26 @@ done
# e2fsprogs is a build-only dependency: it provides mke2fs to pack the image
# below (invoked from the build sandbox PATH, not from $STAGE), but the guest
# never needs it at runtime. Drop its staged files so the runtime image carries
# only the runtime closure. Done before the init is created, so nothing we ship
# is at risk. The symlink guard skips a usr-merged /usr/sbin.
# only the runtime closure. The symlink guard skips a usr-merged /usr/sbin.
if [ -d "$STAGE/usr/sbin" ] && [ ! -L "$STAGE/usr/sbin" ]; then
rm -rf "$STAGE/usr/sbin"
fi
rm -f "$STAGE"/usr/bin/chattr "$STAGE"/usr/bin/lsattr "$STAGE"/usr/bin/uuidgen \
"$STAGE"/usr/bin/compile_et "$STAGE"/usr/bin/mk_cmds
# Note: `libss.so*` (not `libss*.so*`) — the latter also matches openssl's
# libssl.so, which socat needs at runtime.
# libssl.so, which the git runtime closure (curl, openssl) needs at runtime.
rm -f "$STAGE"/usr/lib/libext2fs.so* "$STAGE"/usr/lib/libe2p.so* "$STAGE"/usr/lib/libss.so*

mkdir -p "$STAGE/bin" "$STAGE/sbin" "$STAGE/etc/microvm"
mkdir -p "$STAGE/bin" "$STAGE/sbin"

# Kernel mountpoints. devtmpfs auto-mounts on /dev at boot (CONFIG_DEVTMPFS_MOUNT)
# — without the directory it fails with "devtmpfs: error mounting -2" and the
# guest has no /dev/vsock node. /proc and /sys are conventional mountpoints.
mkdir -p "$STAGE/dev" "$STAGE/proc" "$STAGE/sys" "$STAGE/run" "$STAGE/tmp"
chmod 1777 "$STAGE/tmp"

# Guarantee /bin/sh for the init script's shebang.
# Guarantee /bin/sh: the in-guest minimald chroots in and runs /bin/bash, but a
# /bin/sh is conventional for any script the session shells out to.
if [ ! -e "$STAGE/bin/sh" ]; then
if [ -e "$STAGE/bin/bash" ]; then
ln -sf bash "$STAGE/bin/sh"
Expand All @@ -52,41 +52,9 @@ if [ ! -e "$STAGE/bin/sh" ]; then
fi
fi

# Bring-up init: signal readiness by connecting out to the host (vsock CID 2)
# port 7350 and writing "READY\n", then serve an echo on vsock port 2222 for
# host<->guest connectivity checks. Retry the marker briefly in case the vsock
# device is not live the instant init starts.
cat > "$STAGE/sbin/microvm-init" <<'INIT'
#!/bin/sh
i=0
while [ "$i" -lt 50 ]; do
printf 'READY\n' | socat -t2 - VSOCK-CONNECT:2:7350 && break
i=$((i + 1))
sleep 0.1
done
# Fail loudly if the READY handshake never succeeded, rather than starting the
# listener anyway and turning a boot failure into a downstream timeout.
[ "$i" -lt 50 ] || {
echo "microvm-init: failed to publish READY on vsock 7350" >&2
exit 1
}
exec socat VSOCK-LISTEN:2222,fork EXEC:cat
INIT
chmod +x "$STAGE/sbin/microvm-init"

# Machine-readable record of the bring-up contract.
cat > "$STAGE/etc/microvm/manifest" <<'MANIFEST'
# microvm guest rootfs contract
# format=ext4-block-image
# init=/sbin/microvm-init
# vsock_port_ready=7350 guest CONNECTs out (host listen=false); writes "READY\n" once
# vsock_port_echo=2222 guest LISTENs (host listen=true); echoes per connection
# net=none
MANIFEST

# Prune build-time-only bulk the guest never needs: headers, static libs,
# docs/man, and especially glibc's locale archive (the bulk of the closure).
# The bring-up workload is sh + socat; the C locale fallback is sufficient.
# The C locale fallback is sufficient for the guest workload.
# `|| true` is scoped to `find` only — a failure in `cd` or `rm -rf` must still
# fail the build (set -euo pipefail), while `find`'s noncritical errors are ok.
( cd "$STAGE" && \
Expand Down
Loading