# Phase 1.2 follow-up: Scheme-driven GNU Hello build with Guix builder phases on FreeBSD Date: 2026-04-01 ## Summary This step extends the earlier native GNU Hello shell harness by validating a tiny Scheme-driven prototype that uses Guix's actual builder-side GNU build machinery on FreeBSD. Added files: - `tests/native-build/gnu-hello-guix-phase-runner.scm` - `tests/native-build/run-gnu-hello-guix-phase-runner.sh` The prototype does not yet build a real Guix package or derivation, but it does execute a subset of Guix's builder-side `%standard-phases` from `(guix build gnu-build-system)` against GNU Hello on FreeBSD. ## Why this step matters The previous Phase 1.2 step showed that FreeBSD can perform a shell-driven native autotools build of GNU Hello. This step moves closer to actual Guix execution by validating that FreeBSD can run Guix's Scheme-side builder logic when using a fixed local Guile build. That is important because the earlier packaged FreeBSD `guile3` binary still crashes in subprocess helpers such as `system*`, `spawn`, and `open-pipe*`. A Scheme-driven build harness therefore needs the locally fixed Guile path validated in Phase 1.1. ## Harness design The shell wrapper: - requires a fixed local Guile build - automatically prepends the matching sibling `lib` directory to `LD_LIBRARY_PATH` - exposes the Guix source tree through `GUILE_LOAD_PATH` - creates and cleans up a temporary work directory unless `KEEP_WORKDIR=1` The Scheme runner: 1. fetches GNU Hello `2.12.3` 2. translates the Guix nix-base32 hash to hexadecimal using `(guix base32)` 3. verifies the downloaded tarball with `sha256(1)` 4. invokes `gnu-build` from `(guix build gnu-build-system)` 5. runs this phase subset from `%standard-phases`: - `set-SOURCE-DATE-EPOCH` - `unpack` - `configure` - `build` - `check` - `install` 6. executes the installed `hello` binary 7. records metadata including test results and runtime dependencies Unlike the earlier shell harness, this prototype installs directly into a store-like output directory under the temporary work tree, which is closer to actual Guix build behavior. ## Source identity As in the previous step, this uses the GNU Hello source currently referenced by `~/repos/guix/gnu/packages/base.scm`: - version: `2.12.3` - Guix nix-base32: `183a6rxnhixiyykd7qis0y9g9cfqhpkk872a245y3zl28can0pqd` - verified SHA256: `0d5f60154382fee10b114a1c34e785d8b1f492073ae2d3a6f7b147687b366aa0` ## Verification command ```sh METADATA_OUT=/tmp/gnu-hello-guix-metadata.txt \ ./tests/native-build/run-gnu-hello-guix-phase-runner.sh ``` The wrapper used the previously validated local fixed Guile build: ```text /tmp/guile-freebsd-validate-install/bin/guile ``` ## Result The Scheme-driven build succeeded on `FreeBSD 15.0-STABLE` amd64. Observed outcomes: - source fetch: success - source hash verification: success - Guix builder phase execution: success - `configure`: success - `build`: success - `check`: success - `install`: success - runtime execution: success Observed program output: ```text Hello, world! ``` Observed test summary: ```text # TOTAL: 7 # PASS: 7 # SKIP: 0 # XFAIL: 0 # FAIL: 0 # XPASS: 0 # ERROR: 0 ``` ## Notable findings ### 1. Guix builder-side GNU phases can run on FreeBSD This is the first repository step that successfully exercised actual Guix builder-side GNU build logic on FreeBSD rather than only a shell approximation. The harness successfully called `gnu-build` from `(guix build gnu-build-system)` with a selected subset of `%standard-phases`. ### 2. The local fixed Guile build remains necessary for Scheme-driven build orchestration This harness depends on subprocess helpers such as `open-pipe*` and `invoke`, so it must not use the packaged FreeBSD `guile3` binary. Using the fixed local Guile build from earlier Phase 1.1 validation was sufficient. ### 3. Store-like installation changes the resulting runtime linkage profile The installed binary ended up in a store-like output directory: ```text /tmp/.../0000000000000000-hello-2.12.3/bin/hello ``` Observed runtime dependencies were: - `libc.so.7` - `libsys.so.7` This differs from the earlier `/usr/local`-prefixed native shell harness, where the staged binary also pulled in `libiconv.so.2`, `libintl.so.8`, and `libthr.so.3`. This is an important data point: a more Guix-like output layout and build path can produce materially different runtime linkage on FreeBSD. ### 4. The test suite passes in this mode too Unlike the previous shell harness, this prototype also ran GNU Hello's `make check` phase successfully. That gives a stronger signal that the Guix builder-side phase sequence is usable on FreeBSD for at least a minimal GNU autotools package. ## What this step demonstrates This step demonstrates that FreeBSD can support a small but real fragment of Guix build orchestration in Scheme, provided that Guile itself is built from a fixed revision containing the upstream subprocess crash fix. In practical terms, the host now has validated evidence for all of the following: 1. native shell-driven GNU Hello build works 2. local fixed Guile can safely drive subprocess-heavy Scheme code on FreeBSD 3. Guix builder-side GNU phases can build, test, install, and run GNU Hello on FreeBSD ## Remaining limitations This is still not a full Guix package build: - no derivation was created - no store daemon was involved - no build isolation/jail integration was used - no dependency graph resolution was performed by Guix package machinery - only a subset of `%standard-phases` was exercised ## Recommended next step Continue Phase 1.2 by broadening coverage in one of two ways: 1. run the same Scheme-driven phase-runner approach against another small GNU/autotools package, or 2. start documenting the exact Linux-vs-FreeBSD gaps that remain between this prototype and a real `gnu-build-system` build driven by Guix package definitions Either direction would build directly on the harnesses now present in `tests/native-build/`.