diff --git a/docs/PROGRESS.md b/docs/PROGRESS.md index 11b1e6f..ebd68ed 100644 --- a/docs/PROGRESS.md +++ b/docs/PROGRESS.md @@ -115,14 +115,57 @@ Current assessment: - no source changes were needed in `~/repos/bdwgc` yet, but the earlier FreeBSD warning keeps it on the watch list - the project can now move on to Phase 1.2 with a known-good local Guile fallback +## 2026-04-01 — Phase 1.2 started: native GNU Hello build validated on FreeBSD + +Completed work: + +- added a reusable native build harness: + - `tests/native-build/run-gnu-hello.sh` +- used the current Guix package definition in `~/repos/guix/gnu/packages/base.scm` as the source of truth for: + - GNU Hello version `2.12.3` + - expected Guix nix-base32 source hash `183a6rxnhixiyykd7qis0y9g9cfqhpkk872a245y3zl28can0pqd` +- verified the downloaded tarball against the translated SHA256: + - `0d5f60154382fee10b114a1c34e785d8b1f492073ae2d3a6f7b147687b366aa0` +- successfully executed the standard native build lifecycle on `FreeBSD 15.0-STABLE` amd64: + - fetch + - hash verification + - extract + - configure + - build + - staged install + - runtime execution +- confirmed the staged binary runs and prints: + - `Hello, world!` +- captured build metadata including: + - compiler and make versions + - host triplet + - configure command + - staged output path + - runtime shared-library dependencies +- wrote the results to `docs/reports/phase1-native-gnu-hello.md` + +Important findings: + +- GNU Hello built successfully with FreeBSD base `make`, not just `gmake` +- that contrasts with the earlier local Guile build, which did require GNU `gmake` +- even this minimal GNU package links against FreeBSD-userland-provided libraries such as `libiconv` and `libintl`, which is useful data for later Guix package modeling +- this step is still a native shell-driven build exercise, not yet a real Guix package build + +Current assessment: + +- Phase 1.2 now has a concrete native autotools success case on FreeBSD +- the host can perform the basic fetch/verify/configure/build/install/run cycle needed for later `gnu-build-system` adaptation work +- Guix-specific build orchestration is still missing, but the environmental baseline is stronger now + Recent commits: - `e380e88` — `Add FreeBSD Guile verification harness` - `cd721b1` — `Update progress after Guile verification` - `27916cb` — `Diagnose Guile subprocess crash on FreeBSD` +- `02f7a7f` — `Validate local Guile fix on FreeBSD` Next recommended step: -1. begin Phase 1.2 by creating a minimal native FreeBSD build environment exercise (for example, GNU Hello or an even smaller autotools package) -2. use the local fixed Guile build when subprocess helpers are required -3. keep `bdwgc` in reserve if later FreeBSD-specific GC/thread issues appear +1. extend Phase 1.2 with at least one additional representative GNU/autotools package build on FreeBSD, or +2. prototype a tiny Scheme-based `gnu-build-system`-like phase runner using the known-good local Guile path, starting from the GNU Hello flow +3. continue keeping `~/repos/bdwgc` in reserve if later FreeBSD-specific GC/thread issues appear diff --git a/docs/reports/phase1-native-gnu-hello.md b/docs/reports/phase1-native-gnu-hello.md new file mode 100644 index 0000000..b0b46d2 --- /dev/null +++ b/docs/reports/phase1-native-gnu-hello.md @@ -0,0 +1,133 @@ +# Phase 1.2 started: native FreeBSD GNU Hello build exercise + +Date: 2026-04-01 + +## Summary + +This step begins Phase 1.2 from `docs/PLAN.md` by validating a minimal native GNU autotools build on FreeBSD. + +A reusable harness was added: + +- `tests/native-build/run-gnu-hello.sh` + +The harness downloads GNU Hello, verifies the source hash against the current Guix package definition, configures it, builds it, installs it into a staging directory, and runs the resulting binary. + +## Source and integrity verification + +The exercise uses the same GNU Hello release currently referenced by the Guix source tree at `~/repos/guix/gnu/packages/base.scm`: + +- package: `hello` +- version: `2.12.3` +- Guix nix-base32 hash: `183a6rxnhixiyykd7qis0y9g9cfqhpkk872a245y3zl28can0pqd` + +The harness converts the Guix nix-base32 hash to hexadecimal using `(guix base32)` and verifies the downloaded tarball with `sha256(1)`. + +Verified SHA256: + +```text +0d5f60154382fee10b114a1c34e785d8b1f492073ae2d3a6f7b147687b366aa0 +``` + +## Verification command + +```sh +METADATA_OUT=/tmp/gnu-hello-metadata.txt ./tests/native-build/run-gnu-hello.sh +``` + +## Result + +The native FreeBSD build succeeds. + +Observed outcome: + +- source fetch: success +- source hash verification: success +- extract: success +- configure: success +- build: success +- staged install: success +- runtime execution: success + +Observed program output: + +```text +Hello, world! +``` + +## Environment used + +From the captured metadata: + +- host: `FreeBSD 15.0-STABLE amd64` +- compiler: `cc` (`FreeBSD clang version 19.1.7`) +- make tool: `make` (FreeBSD base make) +- host triplet: `x86_64-unknown-freebsd15.0` +- configure command: `CC=cc .../configure --prefix=/usr/local` + +## Notable findings + +### 1. A simple GNU autotools package builds with FreeBSD base `make` + +GNU Hello built successfully using FreeBSD's native `/usr/bin/make`. + +This is a useful contrast with the earlier local Guile build work, where GNU `gmake` was required. So for Phase 1.2, the immediate result is: + +- some standard GNU autotools packages can build on FreeBSD with native base tooling +- but more complex packages still may require GNU-specific build tools + +### 2. Runtime dependencies reflect FreeBSD userland packaging choices + +The staged `hello` binary is dynamically linked and pulls in: + +- `libiconv.so.2` +- `libintl.so.8` +- `libc.so.7` +- `libthr.so.3` +- `libsys.so.7` + +This is relevant for later Guix porting work because even a minimal GNU package on FreeBSD picks up non-Linux runtime linkage patterns that will need to be modeled correctly. + +### 3. Guile was only needed for hash translation, not for the build itself + +The build harness uses Guile plus `(guix base32)` only to translate the Guix package hash into hexadecimal for source verification. + +The actual package build is performed entirely with native FreeBSD/GNU userland tools: + +- `fetch` +- `sha256` +- `bsdtar` +- `cc` +- `make` + +## What this step demonstrates + +This step demonstrates that the current FreeBSD host can already perform the basic lifecycle expected of a future adapted `gnu-build-system` flow: + +1. fetch source +2. verify source integrity +3. unpack source +4. run `configure` +5. compile +6. install into a staging directory +7. execute the resulting binary +8. collect basic input/output metadata + +## Remaining gaps relative to the full Phase 1.2 goal + +This is a native build exercise, not yet a real Guix package build. + +Still outstanding: + +- building the package through Guix abstractions rather than a shell harness +- recording Guix-style dependency graphs and derivation-like metadata +- Linux-vs-FreeBSD output/process comparison from the same package build +- trying at least one more representative GNU package beyond Hello + +## Recommendation for the next step + +Continue Phase 1.2 by either: + +1. creating a second native build exercise for another small GNU autotools package, or +2. starting a very small FreeBSD-specific prototype of `gnu-build-system`-like phase execution in Scheme using the now-validated local Guile path + +The current GNU Hello harness provides a good baseline for either direction. diff --git a/tests/native-build/run-gnu-hello.sh b/tests/native-build/run-gnu-hello.sh new file mode 100755 index 0000000..dd6bcf8 --- /dev/null +++ b/tests/native-build/run-gnu-hello.sh @@ -0,0 +1,199 @@ +#!/bin/sh +set -eu + +guix_source_dir=${GUIX_SOURCE_DIR:-"$HOME/repos/guix"} +hello_version=${HELLO_VERSION:-2.12.3} +expected_nix_base32=${HELLO_NIX_BASE32:-183a6rxnhixiyykd7qis0y9g9cfqhpkk872a245y3zl28can0pqd} +source_url=${HELLO_SOURCE_URL:-"https://ftp.gnu.org/gnu/hello/hello-$hello_version.tar.gz"} +prefix=${PREFIX:-/usr/local} +cc_bin=${CC_BIN:-cc} +make_bin=${MAKE_BIN:-make} + +if [ ! -d "$guix_source_dir/guix" ]; then + echo "Guix source tree not found at $guix_source_dir" >&2 + exit 1 +fi + +if [ -n "${GUILE_BIN:-}" ]; then + guile_bin=$GUILE_BIN +elif command -v guile3 >/dev/null 2>&1; then + guile_bin=$(command -v guile3) +elif command -v guile-3.0 >/dev/null 2>&1; then + guile_bin=$(command -v guile-3.0) +else + echo "Unable to find GUILE_BIN, guile3, or guile-3.0 in PATH" >&2 + exit 1 +fi + +if [ ! -x "$guile_bin" ]; then + echo "Guile binary is not executable: $guile_bin" >&2 + exit 1 +fi + +if ! command -v fetch >/dev/null 2>&1; then + echo "fetch not found in PATH" >&2 + exit 1 +fi +if ! command -v sha256 >/dev/null 2>&1; then + echo "sha256 not found in PATH" >&2 + exit 1 +fi +if ! command -v bsdtar >/dev/null 2>&1; then + echo "bsdtar not found in PATH" >&2 + exit 1 +fi +if ! command -v "$cc_bin" >/dev/null 2>&1; then + echo "C compiler not found: $cc_bin" >&2 + exit 1 +fi +if ! command -v "$make_bin" >/dev/null 2>&1; then + echo "make tool not found: $make_bin" >&2 + exit 1 +fi + +jobs=${JOBS:-$(sysctl -n hw.ncpu 2>/dev/null || echo 1)} +guile_prefix=$(CDPATH= cd -- "$(dirname "$guile_bin")/.." && pwd) +guile_lib_dir=$guile_prefix/lib +if [ -e "$guile_lib_dir/libguile-3.0.so.1" ]; then + if [ -n "${LD_LIBRARY_PATH:-}" ]; then + export LD_LIBRARY_PATH="$guile_lib_dir:$LD_LIBRARY_PATH" + else + export LD_LIBRARY_PATH="$guile_lib_dir" + fi +fi + +cleanup=0 +if [ -n "${WORKDIR:-}" ]; then + workdir=$WORKDIR + mkdir -p "$workdir" +else + workdir=$(mktemp -d /tmp/fruix-gnu-hello.XXXXXX) + cleanup=1 +fi + +if [ "${KEEP_WORKDIR:-0}" -eq 1 ]; then + cleanup=0 +fi + +cleanup_workdir() { + if [ "$cleanup" -eq 1 ]; then + rm -rf "$workdir" + fi +} +trap cleanup_workdir EXIT INT TERM + +expected_sha256_hex=$(GUILE_AUTO_COMPILE=0 \ + GUILE_LOAD_PATH="$guix_source_dir${GUILE_LOAD_PATH:+:$GUILE_LOAD_PATH}" \ + "$guile_bin" -c "(use-modules (guix base32) (rnrs bytevectors) (ice-9 format)) (for-each (lambda (b) (format #t \"~2,'0x\" b)) (bytevector->u8-list (nix-base32-string->bytevector (cadr (command-line))))) (newline)" \ + "$expected_nix_base32") + +src_tarball=$workdir/hello-$hello_version.tar.gz +src_dir=$workdir/hello-$hello_version +build_dir=$workdir/build +stage_dir=$workdir/stage +metadata_file=$workdir/gnu-hello-build-metadata.txt +configure_log=$workdir/configure.log +build_log=$workdir/build.log +install_log=$workdir/install.log + +printf 'Using Guile: %s\n' "$guile_bin" +printf 'Using LD_LIBRARY_PATH: %s\n' "${LD_LIBRARY_PATH:-}" +printf 'Working directory: %s\n' "$workdir" +printf 'Fetching: %s\n' "$source_url" +fetch -o "$src_tarball" "$source_url" + +actual_sha256_hex=$(sha256 -q "$src_tarball") +if [ "$actual_sha256_hex" != "$expected_sha256_hex" ]; then + echo "sha256 mismatch for $src_tarball" >&2 + echo "expected: $expected_sha256_hex" >&2 + echo "actual: $actual_sha256_hex" >&2 + exit 1 +fi + +bsdtar -xf "$src_tarball" -C "$workdir" +mkdir -p "$build_dir" "$stage_dir" + +host_triplet=$(sh "$src_dir/build-aux/config.guess") +configure_cmd="CC=$cc_bin $src_dir/configure --prefix=$prefix" + +( + cd "$build_dir" + env CC="$cc_bin" "$src_dir/configure" --prefix="$prefix" +) >"$configure_log" 2>&1 + +( + cd "$build_dir" + env CC="$cc_bin" "$make_bin" -j"$jobs" +) >"$build_log" 2>&1 + +( + cd "$build_dir" + env CC="$cc_bin" "$make_bin" DESTDIR="$stage_dir" install +) >"$install_log" 2>&1 + +installed_binary=$stage_dir$prefix/bin/hello +if [ ! -x "$installed_binary" ]; then + echo "installed hello binary not found: $installed_binary" >&2 + exit 1 +fi + +hello_output=$(env LC_ALL=C "$installed_binary") +if [ "$hello_output" != "Hello, world!" ]; then + echo "unexpected hello output: $hello_output" >&2 + exit 1 +fi + +binary_file=$(file "$installed_binary") +runtime_deps=$(ldd "$installed_binary") +cc_version=$($cc_bin --version | sed -n '1p') +make_version=$($make_bin -V MAKE_VERSION 2>/dev/null || $make_bin --version 2>/dev/null | sed -n '1p' || echo unknown) +uname_string=$(uname -a) + +cat >"$metadata_file" <