# Phase 13.2: built the first native FreeBSD world and kernel artifacts from `/usr/src` Date: 2026-04-03 ## Goal After Phase 13.1 introduced native Fruix package/materialization support for FreeBSD base artifacts, the next step was to exercise that path for real: - build a kernel from `/usr/src` - build and stage a minimal runtime-oriented world from `/usr/src` - place both outputs under `/frx/store` - document the exact split of this first native base target ## Implementation ### 1. Fixed two important builder issues found during the first real run #### `MAKEOBJDIRPREFIX` had to move to the environment The first real `buildworld` attempt failed with: ```text MAKEOBJDIRPREFIX can only be set in environment or src-env.conf(5) ``` The native build path originally passed `MAKEOBJDIRPREFIX=...` as a make command-line variable. That was corrected so the generated build command now uses: - `env MAKEOBJDIRPREFIX=... make ...` instead. #### The initial `/usr/src` tree hash was accidentally unstable The first source-tree hashing attempt hashed the raw `mtree -c` output. That was subtly wrong because `mtree` includes header comments such as: - date - user - machine - tree path banner As a result, successive hash computations differed even when `/usr/src` had not changed. This was corrected by stripping the leading `# ...` comment lines before hashing the `mtree` content. After that fix: - native world and native kernel reported the same `source-tree-sha256` - both reused the same native build root - output identity stopped drifting on each run ## First concrete native outputs A native Fruix system definition using: - `freebsd-native-kernel` - `freebsd-native-world` - host-staged `freebsd-bootloader` - `shepherd-pid1` was built successfully. Resulting store outputs: - kernel: - `/frx/store/93f35ddcb9a03f63f83c9e8ae29788685d339789da664f881822b4a1914f5ff6-freebsd-native-kernel-15.0-STABLE` - world: - `/frx/store/3f6f7f8c06ed8dad4cae21a1e8ac8ba4823bdb7cf54328c9bbcccaeb858beb77-freebsd-native-world-15.0-STABLE` Native build metadata records for both outputs show: - `source-root=/usr/src` - the same `source-tree-sha256` - `kernconf=GENERIC` - the same shared `build-root` Shared build root: - `/var/tmp/fruix-freebsd-native-build-c59b1b8128b305d9bad9cf3d654771c941c4e8b6a2732f6bc959df96d1d32f58` Key log files recorded in the output metadata: - `buildworld.log` - `buildkernel-GENERIC.log` - `install-freebsd-native-world.log` - `install-freebsd-native-kernel.log` ## First native world split The first `freebsd-native-world` output is intentionally runtime-oriented. Validation confirmed that it contains the core pieces needed by the existing Fruix guest model, including: - `/bin/sh` - `/sbin/init` - `/etc/rc` - `/usr/sbin/sshd` - `/sbin/dhclient` - `/usr/bin/cap_mkdb` - `/usr/sbin/pwd_mkdb` - `/usr/share/locale/C.UTF-8/LC_CTYPE` The first prune list is also active. Validation confirmed the world output does **not** contain: - `/usr/share/man` - `/usr/tests` This keeps the first native world output closer to the current boot/runtime target instead of a fully unpruned base install tree. ## Store-boundary result The generated closure metadata now shows the intended transitional boundary clearly: - `host_base_store_count=1` - `host_base_stores=` bootloader only - `native_base_store_count=2` - `native_base_stores=` native kernel + native world That means Fruix now has a mixed but explicit Phase-13 system boundary: - bootloader still comes from the old host-staged path - kernel and core runtime world now come from native `/usr/src`-built store outputs ## Validation ### Direct build through `fruix system build` A real native-base system build succeeded and produced: - native kernel store output - native world store output - a system closure referencing those outputs ### Dedicated Phase 13.2 harness Added: - `tests/system/phase13-native-base-pid1-operating-system.scm.in` - `tests/system/run-phase13-native-base-build.sh` Passing run: - `PASS phase13-native-base-build` - workdir: `/tmp/phase13-2-build-1775173551` Key metadata from that run: ```text kernel_store=/frx/store/93f35ddcb9a03f63f83c9e8ae29788685d339789da664f881822b4a1914f5ff6-freebsd-native-kernel-15.0-STABLE world_store=/frx/store/3f6f7f8c06ed8dad4cae21a1e8ac8ba4823bdb7cf54328c9bbcccaeb858beb77-freebsd-native-world-15.0-STABLE host_base_store_count=1 native_base_store_count=2 world_source_tree_sha256=72a451e2ea47c4c4777035f797dc35f8d905eaabb2a717bc1fd71019f3021f72 kernel_source_tree_sha256=72a451e2ea47c4c4777035f797dc35f8d905eaabb2a717bc1fd71019f3021f72 world_build_root=/var/tmp/fruix-freebsd-native-build-c59b1b8128b305d9bad9cf3d654771c941c4e8b6a2732f6bc959df96d1d32f58 kernel_build_root=/var/tmp/fruix-freebsd-native-build-c59b1b8128b305d9bad9cf3d654771c941c4e8b6a2732f6bc959df96d1d32f58 ``` The harness also verified: - closure rebuild path reproducibility - existence of required kernel/world runtime files - absence of the pruned world paths - presence of native build metadata and logs - presence of `native-base-stores` in closure store-layout metadata ## Assessment Phase 13.2 is complete. Fruix now does more than describe native FreeBSD base artifacts: it actually builds them from `/usr/src`, stores them under `/frx/store`, and records enough metadata to inspect how they were produced. This is the first point where Fruix can honestly say that part of the FreeBSD base is no longer just a curated copy of the builder host. ## Next recommended step Proceed to Phase 13.3: - wire the operating-system/image path to boot using these native kernel/world outputs - validate locally with QEMU/UEFI - validate on the approved XCP-ng VM/VDI path