Validate real FreeBSD package builds

This commit is contained in:
2026-04-01 16:34:42 +02:00
parent c3a2d45a02
commit 2e838fb2a5
3 changed files with 312 additions and 0 deletions

View File

@@ -1723,3 +1723,34 @@ Next recommended step:
- Fruix at the product boundary
- `/frx` as the canonical store root
- stable upstream-derived internal names unless there is strong architectural value in renaming them
## 2026-04-01 — Phase 6.1 completed: real package build validated into `/frx/store`
Completed work:
- added a runnable real-package harness:
- `tests/guix/run-phase6-real-package-build.sh`
- wrote the Phase 6.1 report:
- `docs/reports/phase6-real-package-build-freebsd.md`
- ran the real-package harness successfully and captured metadata under:
- `/tmp/phase6-real-package-metadata.txt`
Important findings:
- the checkout can now build a real package definition derived from Guix's `hello` package through:
- `./pre-inst-env fruix build -f ...`
- the FreeBSD-aware daemon
- `/frx/store`
- this moves the project beyond the deliberately minimal Phase 5 custom derivation path and into a real package-definition flow
- the current successful path still uses a prefetched local GNU Hello tarball as the package source because the built-in downloader path remains a separate unresolved FreeBSD/root-daemon issue
- observed metadata confirmed:
- `drv_path=/frx/store/...-hello-2.12.3.drv`
- `out_path=/frx/store/...-hello-2.12.3`
- `source_store_path=/frx/store/...-hello-2.12.3.tar.gz`
- `runtime_output=Hello, world!`
- a daemon-side references query confirmed that the built output preserved the declared source store item as a direct reference
Current assessment:
- Phase 6.1 is now satisfied on the current FreeBSD prototype track
- the next step is to move the already validated jail/build-user model into this live package-build path rather than keeping it prototype-only

View File

@@ -0,0 +1,65 @@
# Phase 6.1: Real FreeBSD-backed package build into `/frx/store`
Date: 2026-04-01
## Summary
This step moves beyond the Phase 5 minimal custom derivation path and validates a real package definition derived from Guix's `hello` package through the live Fruix/Guix checkout, daemon, and `/frx/store` path on FreeBSD.
Added file:
- `tests/guix/run-phase6-real-package-build.sh`
## Validation command
Run command:
```sh
METADATA_OUT=/tmp/phase6-real-package-metadata.txt \
./tests/guix/run-phase6-real-package-build.sh
```
## What the harness does
The harness:
1. reuses the patched Phase 5 checkout/runtime setup
2. fetches GNU Hello `2.12.3` and verifies the expected SHA256
3. starts the patched daemon on a temporary Unix socket
4. generates a package file that inherits from Guix's real `hello` package definition
5. replaces the source with a prefetched local tarball store item to avoid the still-unresolved built-in downloader/root path on FreeBSD
6. lowers that package through a tiny FreeBSD host build system and invokes it through:
- `./pre-inst-env fruix build -f ...`
7. validates the built result in `/frx/store`
8. queries the daemon for direct references of the output path
## Observed results
Observed metadata included:
- `drv_path=/frx/store/...-hello-2.12.3.drv`
- `out_path=/frx/store/...-hello-2.12.3`
- `source_store_path=/frx/store/...-hello-2.12.3.tar.gz`
- `runtime_output=Hello, world!`
- `frontend_invocation=./pre-inst-env fruix build -f ...`
The direct references query included both:
- the built output path itself
- the source tarball store item recorded by the build output metadata
## Important findings
- this is the first validated `fruix build`-style package build on the current FreeBSD track that lands a real package output in `/frx/store`
- the package definition was not invented from scratch; it inherits from the real Guix `hello` package and only swaps in a FreeBSD-specific build-system path plus a prefetched source item
- the live daemon/store path is now strong enough to materialize and execute a genuine package output rather than only the earlier minimal derivation-backed probes
- the built-in downloader path is still not ready for this FreeBSD/root daemon flow, so Phase 6.1 currently uses a prefetched local tarball to isolate the package-build boundary from that separate runtime issue
## Conclusion
Phase 6.1 is satisfied on the current FreeBSD prototype track:
- a real package definition derived from Guix's `hello` package builds successfully through the Fruix/Guix checkout and daemon path
- the output lands in `/frx/store`
- the package runs successfully from the store
- the output preserves a declared source reference that can be queried through the daemon

View File

@@ -0,0 +1,216 @@
#!/bin/sh
set -eu
repo_root=$(CDPATH= cd -- "$(dirname "$0")/../.." && pwd)
metadata_target=${METADATA_OUT:-}
cleanup=0
if [ -n "${WORKDIR:-}" ]; then
workdir=$WORKDIR
mkdir -p "$workdir"
else
workdir=$(mktemp -d /tmp/fruix-phase6-real-package.XXXXXX)
cleanup=1
fi
if [ "${KEEP_WORKDIR:-0}" -eq 1 ]; then
cleanup=0
fi
setup_metadata=$workdir/setup-metadata.txt
setup_env=$workdir/setup-env.sh
metadata_file=$workdir/phase6-real-package-metadata.txt
daemon_socket=$workdir/guix-daemon.sock
daemon_log=$workdir/guix-daemon.log
fetch_tarball=$workdir/hello-2.12.3.tar.gz
build_stdout=$workdir/fruix-build.out
build_stderr=$workdir/fruix-build.err
references_log=$workdir/references.log
package_template=$workdir/phase6-hello.scm.in
package_file=$workdir/phase6-hello.scm
daemon_pid=
cleanup_workdir() {
if [ -n "$daemon_pid" ]; then
sudo kill "$daemon_pid" >/dev/null 2>&1 || true
wait "$daemon_pid" 2>/dev/null || true
fi
rm -f "$daemon_socket"
if [ "$cleanup" -eq 1 ]; then
rm -rf "$workdir"
fi
}
trap cleanup_workdir EXIT INT TERM
fetch -o "$fetch_tarball" https://ftp.gnu.org/gnu/hello/hello-2.12.3.tar.gz >/dev/null
[ "$(sha256 -q "$fetch_tarball")" = '0d5f60154382fee10b114a1c34e785d8b1f492073ae2d3a6f7b147687b366aa0' ] || {
echo "unexpected hello tarball hash" >&2
exit 1
}
WORKDIR=$workdir/setup KEEP_WORKDIR=1 \
METADATA_OUT=$setup_metadata ENV_OUT=$setup_env \
"$repo_root/tests/guix/setup-phase5-checkout.sh" >"$workdir/setup.log" 2>&1
# shellcheck disable=SC1090
. "$setup_env"
cd "$PHASE5_BUILDDIR"
export LD_LIBRARY_PATH GUILE_LOAD_PATH GUILE_LOAD_COMPILED_PATH GUILE_EXTENSIONS_PATH
export GUILE_AUTO_COMPILE=0
cat >"$package_template" <<'EOF'
(use-modules (gnu packages base)
(guix packages)
(guix build-system)
(guix store)
(guix monads)
(guix gexp)
(guix derivations))
(define source-file "__SOURCE_FILE__")
(define source-item
(local-file source-file "hello-2.12.3.tar.gz"))
(define* (phase6-lower name #:key source inputs native-inputs outputs system target #:allow-other-keys)
(bag
(name name)
(system system)
(target target)
(host-inputs `(,@(if source `(("source" ,source)) '()) ,@inputs))
(build-inputs native-inputs)
(outputs outputs)
(build phase6-build)
(arguments `(#:source ,source #:package-name ,name))))
(define* (phase6-build name inputs #:key source (outputs '("out")) (system (%current-system)) #:allow-other-keys)
(mlet* %store-monad ((shell (interned-file "/bin/sh" "sh" #:recursive? #t))
(source* (lower-object source system))
(builder (text-file "phase6-hello-builder.sh"
"#!/bin/sh
set -eu
export PATH=/bin:/usr/bin:/usr/local/bin
src_tar=\"$1\"
/bin/mkdir -p \"$TMPDIR/phase6-build\"
cd \"$TMPDIR/phase6-build\"
/usr/bin/tar -xf \"$src_tar\"
cd hello-2.12.3
export CC=/usr/bin/cc
export CONFIG_SHELL=/bin/sh
export CPPFLAGS='-I/usr/local/include'
export LDFLAGS='-L/usr/local/lib -Wl,-rpath,/usr/local/lib'
./configure --prefix=\"$out\"
/usr/local/bin/gmake -j1
/usr/local/bin/gmake -j1 check
/usr/local/bin/gmake -j1 install
/bin/mkdir -p \"$out/share/fruix-phase6\"
printf '%s\\n' \"$src_tar\" > \"$out/share/fruix-phase6/source-store-path.txt\"
"
(list (if (derivation? source*)
(derivation->output-path source*)
source*)))))
(lambda (store)
(values (derivation store name shell
(list "-e" builder
(if (derivation? source*)
(derivation->output-path source*)
source*))
#:env-vars '(("HOME" . "/homeless")
("PATH" . "/bin:/usr/bin:/usr/local/bin"))
#:inputs `(,@(if (derivation? source*) `((,source*)) '())
(,shell) (,builder))
#:sources `(,shell ,builder)
#:system system
#:outputs outputs)
store))))
(define phase6-build-system
(build-system
(name 'phase6-freebsd-host-gnu)
(description "Phase 6 FreeBSD host GNU build system")
(lower phase6-lower)))
(package/inherit hello
(source source-item)
(build-system phase6-build-system)
(supported-systems (list (%current-system))))
EOF
sed "s|__SOURCE_FILE__|$fetch_tarball|g" "$package_template" > "$package_file"
sudo env GUIX_DAEMON_SOCKET=unix://$daemon_socket \
"$PHASE5_GUIX_DAEMON" --disable-chroot --listen "$daemon_socket" --no-substitutes \
>"$daemon_log" 2>&1 &
daemon_pid=$!
for _ in 1 2 3 4 5 6 7 8 9 10; do
[ -S "$daemon_socket" ] && break
sleep 1
done
[ -S "$daemon_socket" ] || {
echo "daemon socket was not created: $daemon_socket" >&2
exit 1
}
GUIX_DAEMON_SOCKET=unix://$daemon_socket \
./pre-inst-env fruix build -f "$package_file" >"$build_stdout" 2>"$build_stderr"
out_path=$(awk 'NF { last = $0 } END { print last }' "$build_stdout")
drv_path=$(sed -n 's/^successfully built //p' "$build_stderr" | tail -n 1)
source_store_path=$(tr -d '\n' < "$out_path/share/fruix-phase6/source-store-path.txt")
runtime_output=$("$out_path/bin/hello")
GUIX_DAEMON_SOCKET=unix://$daemon_socket \
./pre-inst-env fruix gc --references "$out_path" >"$references_log" 2>"$workdir/fruix-gc.err"
[ -n "$drv_path" ] || { echo "missing derivation path in $build_stderr" >&2; exit 1; }
case "$drv_path" in
/frx/store/*.drv) : ;;
*) echo "unexpected derivation path: $drv_path" >&2; exit 1 ;;
esac
case "$out_path" in
/frx/store/*-hello-2.12.3) : ;;
*) echo "unexpected output path: $out_path" >&2; exit 1 ;;
esac
case "$source_store_path" in
/frx/store/*-hello-2.12.3.tar.gz) : ;;
*) echo "unexpected source store path: $source_store_path" >&2; exit 1 ;;
esac
[ "$runtime_output" = 'Hello, world!' ] || {
echo "unexpected runtime output: $runtime_output" >&2
exit 1
}
grep -Fx "$source_store_path" "$references_log" >/dev/null || {
echo "source store path was not preserved as a reference" >&2
exit 1
}
cat >"$metadata_file" <<EOF
workdir=$workdir
setup_metadata=$setup_metadata
setup_env=$setup_env
phase5_builddir=$PHASE5_BUILDDIR
daemon_socket=$daemon_socket
daemon_log=$daemon_log
fetch_tarball=$fetch_tarball
package_file=$package_file
build_stdout=$build_stdout
build_stderr=$build_stderr
references_log=$references_log
drv_path=$drv_path
out_path=$out_path
source_store_path=$source_store_path
runtime_output=$runtime_output
frontend_invocation=./pre-inst-env fruix build -f $package_file
EOF
if [ -n "$metadata_target" ]; then
mkdir -p "$(dirname "$metadata_target")"
cp "$metadata_file" "$metadata_target"
fi
printf 'PASS phase6-real-package-build\n'
printf 'Work directory: %s\n' "$workdir"
printf 'Metadata file: %s\n' "$metadata_file"
if [ -n "$metadata_target" ]; then
printf 'Copied metadata to: %s\n' "$metadata_target"
fi
printf '%s\n' '--- metadata ---'
cat "$metadata_file"