Validate FreeBSD derivation generation
This commit is contained in:
@@ -1615,3 +1615,34 @@ Current assessment:
|
||||
- Phase 5.1 is now satisfied on the current FreeBSD prototype track
|
||||
- the key boundary has shifted from “the checkout still crashes immediately” to “the checkout runs, and can now be used as the basis for real derivation/store experiments”
|
||||
- the next step is to prove that a real derivation can be emitted against `/frx/store` from the now-runnable checkout
|
||||
|
||||
## 2026-04-01 — Phase 5.2 completed: real derivation generation validated against `/frx/store`
|
||||
|
||||
Completed work:
|
||||
|
||||
- added a runnable derivation-generation harness:
|
||||
- `tests/guix/run-phase5-derivation-generation.sh`
|
||||
- wrote the Phase 5.2 report:
|
||||
- `docs/reports/phase5-derivation-generation-freebsd.md`
|
||||
- ran the derivation-generation harness successfully and captured metadata under:
|
||||
- `/tmp/phase5-derivation-metadata.txt`
|
||||
|
||||
Important findings:
|
||||
|
||||
- the now-runnable checkout can successfully use a real daemon/store connection on FreeBSD to lower a package through:
|
||||
- `package->bag`
|
||||
- `bag->derivation`
|
||||
- the emitted derivation is a real `/frx/store` derivation path rather than an ad hoc placeholder or shell metadata artifact
|
||||
- the validation used a deliberately minimal custom package with a custom low-level build system so that this subphase isolates the real lowering/store boundary without being dominated by still-unresolved upstream bootstrap assumptions for full native FreeBSD package graphs
|
||||
- observed metadata confirmed:
|
||||
- `bag_name=phase5-freebsd-lowering-0`
|
||||
- `bag_host_inputs=("source")`
|
||||
- `drv_path=/frx/store/...-phase5-freebsd-lowering-0.drv`
|
||||
- `out_path=/frx/store/...-phase5-freebsd-lowering-0`
|
||||
- this means the key architectural step is now real and no longer hypothetical:
|
||||
- a package object in the checkout can be lowered to a real derivation targeting `/frx/store` on FreeBSD
|
||||
|
||||
Current assessment:
|
||||
|
||||
- Phase 5.2 is now satisfied on the current FreeBSD prototype track
|
||||
- the next step is no longer “can we emit a derivation at all?” but “can the same daemon/store path accept and execute a derivation-backed build request successfully?”
|
||||
|
||||
90
docs/reports/phase5-derivation-generation-freebsd.md
Normal file
90
docs/reports/phase5-derivation-generation-freebsd.md
Normal file
@@ -0,0 +1,90 @@
|
||||
# Phase 5.2: Real derivation generation validated on FreeBSD against `/frx/store`
|
||||
|
||||
Date: 2026-04-01
|
||||
|
||||
## Summary
|
||||
|
||||
This step validates that the now-runnable checkout can perform real package lowering and emit a real derivation targeting `/frx/store` on FreeBSD.
|
||||
|
||||
Added file:
|
||||
|
||||
- `tests/guix/run-phase5-derivation-generation.sh`
|
||||
|
||||
## Approach
|
||||
|
||||
Rather than jumping immediately to a full upstream package such as GNU Hello, this step uses a deliberately minimal custom package defined inside the harness. The goal is to validate the real Guix lowering layers first, while avoiding unrelated bootstrap baggage that is still not fully adapted to FreeBSD.
|
||||
|
||||
The custom package still exercises the layers that matter for this subphase:
|
||||
|
||||
- `package->bag`
|
||||
- `bag->derivation`
|
||||
- real store connection through the daemon socket
|
||||
- derivation emission into `/frx/store`
|
||||
- source lowering as a real store item
|
||||
|
||||
## Why a custom low-level package was used
|
||||
|
||||
Attempting to lower a representative upstream package now gets past the earlier `leave-on-EPIPE` command-path failure, but still runs into deeper platform/bootstrap issues on this FreeBSD path, such as missing bootstrap binaries for the native system string.
|
||||
|
||||
That means the meaningful next proof point was:
|
||||
|
||||
> can the real checkout lower a package and emit a real derivation at all on FreeBSD?
|
||||
|
||||
The answer is now yes.
|
||||
|
||||
## Validation command
|
||||
|
||||
Run command:
|
||||
|
||||
```sh
|
||||
METADATA_OUT=/tmp/phase5-derivation-metadata.txt \
|
||||
./tests/guix/run-phase5-derivation-generation.sh
|
||||
```
|
||||
|
||||
## What the harness does
|
||||
|
||||
The harness:
|
||||
|
||||
1. reuses the patched checkout/runtime setup from Phase 5.1
|
||||
2. builds the patched `guix-daemon` for FreeBSD
|
||||
3. starts that daemon on a temporary Unix socket
|
||||
4. runs the checkout through the user-facing frontend boundary:
|
||||
- `./pre-inst-env fruix repl -- ...`
|
||||
5. defines a minimal custom FreeBSD test package with a custom low-level build system
|
||||
6. lowers that package through:
|
||||
- `package->bag`
|
||||
- `bag->derivation`
|
||||
7. records the resulting derivation path and output path
|
||||
|
||||
## Observed results
|
||||
|
||||
Observed metadata included:
|
||||
|
||||
- `bag_name=phase5-freebsd-lowering-0`
|
||||
- `bag_host_inputs=("source")`
|
||||
- `drv_path=/frx/store/...-phase5-freebsd-lowering-0.drv`
|
||||
- `out_path=/frx/store/...-phase5-freebsd-lowering-0`
|
||||
|
||||
This demonstrates that:
|
||||
|
||||
- the checkout can now talk to a real daemon socket on FreeBSD
|
||||
- a real package object can be lowered to a bag
|
||||
- that bag can be lowered to a real derivation
|
||||
- the derivation is registered under `/frx/store`
|
||||
- the output path is also a normal `/frx/store` path
|
||||
|
||||
## Important findings
|
||||
|
||||
- the FreeBSD daemon path does not need to be fully feature-complete before derivation generation becomes useful; a narrow but real lowering path already works
|
||||
- the custom package approach avoided conflating Phase 5.2 with the still-unresolved upstream bootstrap-package assumptions for native FreeBSD package graphs
|
||||
- the result is materially beyond the earlier builder-phase and profile prototypes because the derivation is now emitted by the real checkout and store machinery rather than by an ad hoc stand-in
|
||||
|
||||
## Conclusion
|
||||
|
||||
Phase 5.2 is satisfied on the current FreeBSD prototype track:
|
||||
|
||||
- a real derivation is now emitted by the checkout on FreeBSD
|
||||
- it targets `/frx/store`
|
||||
- it comes from a real `package->bag` and `bag->derivation` path rather than from a shell-only approximation
|
||||
|
||||
The next step is to go one layer deeper and submit an actual derivation-backed build request through the same FreeBSD-aware daemon/store path.
|
||||
203
tests/guix/run-phase5-derivation-generation.sh
Executable file
203
tests/guix/run-phase5-derivation-generation.sh
Executable file
@@ -0,0 +1,203 @@
|
||||
#!/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-phase5-derivation.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/phase5-derivation-metadata.txt
|
||||
daemon_socket=$workdir/guix-daemon.sock
|
||||
daemon_log=$workdir/guix-daemon.log
|
||||
scheme_log=$workdir/phase5-derivation.log
|
||||
scheme_template=$workdir/phase5-derivation.scm.in
|
||||
scheme_file=$workdir/phase5-derivation.scm
|
||||
source_file=$workdir/phase5-source.txt
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
printf 'phase5-derivation-source\n' > "$source_file"
|
||||
|
||||
cat >"$scheme_template" <<'EOF'
|
||||
(use-modules (guix store)
|
||||
(guix monads)
|
||||
(guix gexp)
|
||||
(guix packages)
|
||||
(guix build-system)
|
||||
(guix derivations)
|
||||
(ice-9 match)
|
||||
(srfi srfi-1))
|
||||
|
||||
(define source-file "__SOURCE_FILE__")
|
||||
(call-with-output-file source-file
|
||||
(lambda (port)
|
||||
(display "phase5-derivation-source\n" port)))
|
||||
|
||||
(define source-item
|
||||
(local-file source-file "__SOURCE_NAME__"))
|
||||
|
||||
(define* (phase5-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 phase5-build)
|
||||
(arguments `(#:source ,source))))
|
||||
|
||||
(define* (phase5-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 "phase5-builder.sh"
|
||||
"#!/bin/sh\nset -eu\n/bin/mkdir -p \"$out\"\n/bin/cp \"$1\" \"$out/payload.txt\"\nprintf '%s\\n' \"$1\" > \"$out/source-path.txt\"\n"
|
||||
(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"))
|
||||
#:inputs `(,@(if (derivation? source*)
|
||||
`((,source*))
|
||||
'())
|
||||
(,shell) (,builder))
|
||||
#:sources `(,shell ,builder)
|
||||
#:system system
|
||||
#:outputs outputs)
|
||||
store))))
|
||||
|
||||
(define phase5-build-system
|
||||
(build-system
|
||||
(name 'phase5-freebsd)
|
||||
(description "Phase 5 FreeBSD lowering test build system")
|
||||
(lower phase5-lower)))
|
||||
|
||||
(define phase5-package
|
||||
(package
|
||||
(name "phase5-freebsd-lowering")
|
||||
(version "0")
|
||||
(source source-item)
|
||||
(build-system phase5-build-system)
|
||||
(synopsis "Phase 5 lowering test package")
|
||||
(description "Minimal package used to validate lowering on FreeBSD.")
|
||||
(home-page "https://example.invalid/fruix")
|
||||
(license #f)))
|
||||
|
||||
(run-with-store (open-connection)
|
||||
(mlet* %store-monad ((bag -> (package->bag phase5-package (%current-system) #f))
|
||||
(drv (bag->derivation bag phase5-package)))
|
||||
(return (begin
|
||||
(format #t "bag-name=~a~%" (bag-name bag))
|
||||
(format #t "bag-host-inputs=~s~%" (map car (bag-host-inputs bag)))
|
||||
(format #t "drv-path=~a~%" (derivation-file-name drv))
|
||||
(format #t "out-path=~a~%" (derivation->output-path drv))))))
|
||||
EOF
|
||||
sed \
|
||||
-e "s|__SOURCE_FILE__|$source_file|g" \
|
||||
-e "s|__SOURCE_NAME__|$(basename "$source_file")|g" \
|
||||
"$scheme_template" > "$scheme_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 repl -- "$scheme_file" >"$scheme_log" 2>&1
|
||||
|
||||
bag_name=$(sed -n 's/^bag-name=//p' "$scheme_log")
|
||||
bag_inputs=$(sed -n 's/^bag-host-inputs=//p' "$scheme_log")
|
||||
drv_path=$(sed -n 's/^drv-path=//p' "$scheme_log")
|
||||
out_path=$(sed -n 's/^out-path=//p' "$scheme_log")
|
||||
|
||||
[ -n "$bag_name" ] || { echo "missing bag-name in $scheme_log" >&2; exit 1; }
|
||||
[ -n "$drv_path" ] || { echo "missing drv-path in $scheme_log" >&2; exit 1; }
|
||||
[ -n "$out_path" ] || { echo "missing out-path in $scheme_log" >&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/*) : ;;
|
||||
*) echo "unexpected output path: $out_path" >&2; exit 1 ;;
|
||||
esac
|
||||
printf '%s' "$bag_inputs" | grep -q 'source' || {
|
||||
echo "expected source input in bag-host-inputs: $bag_inputs" >&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
|
||||
scheme_log=$scheme_log
|
||||
source_file=$source_file
|
||||
scheme_file=$scheme_file
|
||||
bag_name=$bag_name
|
||||
bag_host_inputs=$bag_inputs
|
||||
drv_path=$drv_path
|
||||
out_path=$out_path
|
||||
EOF
|
||||
|
||||
if [ -n "$metadata_target" ]; then
|
||||
mkdir -p "$(dirname "$metadata_target")"
|
||||
cp "$metadata_file" "$metadata_target"
|
||||
fi
|
||||
|
||||
printf 'PASS phase5-derivation-generation\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"
|
||||
Reference in New Issue
Block a user