Make FreeBSD base version declarative

This commit is contained in:
2026-04-03 09:53:44 +02:00
parent 3b95ced578
commit 72f89c51b5
7 changed files with 725 additions and 106 deletions

View File

@@ -3447,3 +3447,94 @@ Next recommended step:
1. begin Phase 15 by making the FreeBSD base version a declarative Fruix input
2. demonstrate side-by-side native base versions in `/frx/store`
3. validate rebuild/redeploy/rollback across those base versions
## 2026-04-03 — Phase 15.1: made the FreeBSD base a declarative Fruix input
Completed work:
- wrote the Phase 15.1 report:
- `docs/reports/phase15-declarative-base-freebsd.md`
- added a new declarative base record in `modules/fruix/packages/freebsd.scm`:
- `freebsd-base`
- `freebsd-base?`
- `%default-freebsd-base`
- the declarative base now records at least:
- `name`
- `version-label`
- `release`
- `branch`
- `source-root`
- `target`
- `target-arch`
- `kernconf`
- `make-flags`
- native FreeBSD package constructors are now parameterized by a declared base:
- `freebsd-native-kernel-for`
- `freebsd-native-world-for`
- `freebsd-native-runtime-for`
- `freebsd-native-bootloader-for`
- `freebsd-native-headers-for`
- `freebsd-native-system-packages-for`
- `freebsd-native-development-profile-packages-for`
- existing exported native package variables remain available as the `%default-freebsd-base` instances:
- `freebsd-native-kernel`
- `freebsd-native-world`
- `freebsd-native-runtime`
- `freebsd-native-bootloader`
- `freebsd-native-headers`
- added a new operating-system field in `modules/fruix/system/freebsd.scm`:
- `#:freebsd-base`
- exported accessor: `operating-system-freebsd-base`
- the declared base is now recorded in system/image metadata through:
- `operating-system-closure-spec`
- `operating-system-image-spec`
- `metadata/freebsd-base.scm`
- `metadata/store-layout.scm`
- native build manifests and `.freebsd-native-build-info.scm` now record:
- `declared-base`
- `scripts/fruix.scm` now emits declared base metadata for `build` and `image`:
- `freebsd_base_name`
- `freebsd_base_version_label`
- `freebsd_base_release`
- `freebsd_base_branch`
- `freebsd_base_source_root`
- `freebsd_base_target`
- `freebsd_base_target_arch`
- `freebsd_base_kernconf`
- `freebsd_base_file`
New validation files:
- `tests/system/phase15-declarative-base-pid1-operating-system.scm.in`
- `tests/system/run-phase15-declarative-base-build.sh`
Validation:
- declarative-base build harness passes:
- `tests/system/run-phase15-declarative-base-build.sh`
- workdir: `/tmp/phase15-1-build-1775202535`
- result: `PASS phase15-declarative-base-build`
- confirmed:
- `kernel_store=/frx/store/8fcef04c7e507e86ea5e92f251fe3c6ac1aa3bcf4809fa77ddd8b92854bfcde0-freebsd-native-kernel-15.0-STABLE-declarative`
- `bootloader_store=/frx/store/7a0ba431e487dc35a8f6318108da16a37c8426c43e77e7a7f91404ba1d980eef-freebsd-native-bootloader-15.0-STABLE-declarative`
- `runtime_store=/frx/store/17c24ad20ddcb136c39352b68e758deae0b480258ba0128a5546f696a7eba0a6-freebsd-native-runtime-15.0-STABLE-declarative`
- `native_base_store_count=3`
- `host_base_store_count=0`
- `freebsd_base_name=stable-default`
- `freebsd_base_version_label=15.0-STABLE-declarative`
- `freebsd_base_release=15.0-STABLE`
- `freebsd_base_branch=stable/15`
- `freebsd_base_source_root=/usr/src`
- `freebsd_base_kernconf=GENERIC`
- `declarative_base_input=ok`
- the harness also confirmed:
- `metadata/freebsd-base.scm` exists
- `parameters.scm` records the declared base
- `metadata/store-layout.scm` records the declared base
- native build info files record the declared base version/branch
Current assessment:
- Phase 15.1 is complete
- Fruix now models the FreeBSD base as an explicit declarative system input instead of leaving it implicit in the builder host alone
- the next step is to use that new declaration to prove side-by-side base versions and rollback-friendly rebuild/redeploy behavior

View File

@@ -0,0 +1,141 @@
# Phase 15.1: make the FreeBSD base version a declarative Fruix input
Date: 2026-04-03
## Goal
Phase 15.1 made the FreeBSD base an explicit declarative part of the Fruix system model instead of leaving it as an implicit property of whatever `/usr/src` happened to be present on the builder host.
## Implementation
### New declarative base record
Added in `modules/fruix/packages/freebsd.scm`:
- `freebsd-base`
- `freebsd-base?`
- accessors for:
- `name`
- `version-label`
- `release`
- `branch`
- `source-root`
- `target`
- `target-arch`
- `kernconf`
- `make-flags`
- `%default-freebsd-base`
This gives Fruix an explicit model for the base input used by native FreeBSD artifacts.
### Native package constructors now accept a declared base
Added package constructors:
- `freebsd-native-kernel-for`
- `freebsd-native-world-for`
- `freebsd-native-runtime-for`
- `freebsd-native-bootloader-for`
- `freebsd-native-headers-for`
- `freebsd-native-system-packages-for`
- `freebsd-native-development-profile-packages-for`
The existing exported package variables remain as the `%default-freebsd-base` instances:
- `freebsd-native-kernel`
- `freebsd-native-world`
- `freebsd-native-runtime`
- `freebsd-native-bootloader`
- `freebsd-native-headers`
That preserves the validated Phase 14 path while making alternative declared bases possible.
### Operating-system model now records the declared base
Added to `modules/fruix/system/freebsd.scm`:
- `operating-system-freebsd-base`
- new `#:freebsd-base` field on `operating-system`
The declared base is now recorded in:
- `operating-system-closure-spec`
- `operating-system-image-spec`
- `metadata/freebsd-base.scm`
- `metadata/store-layout.scm`
### CLI metadata now exposes the declared base
`scripts/fruix.scm` now emits, for `fruix system build` and `image`:
- `freebsd_base_name`
- `freebsd_base_version_label`
- `freebsd_base_release`
- `freebsd_base_branch`
- `freebsd_base_source_root`
- `freebsd_base_target`
- `freebsd_base_target_arch`
- `freebsd_base_kernconf`
- `freebsd_base_file`
### Native build metadata now records the declared base
Native build manifests and `.freebsd-native-build-info.scm` now carry a `declared-base` block so the native artifacts themselves record the declarative base choice.
## New files
Added:
- `tests/system/phase15-declarative-base-pid1-operating-system.scm.in`
- `tests/system/run-phase15-declarative-base-build.sh`
## Validation
Passing run:
- `PASS phase15-declarative-base-build`
- workdir: `/tmp/phase15-1-build-1775202535`
The harness used an explicit declared base:
```scheme
(freebsd-base
#:name "stable-default"
#:version-label "15.0-STABLE-declarative"
#:release "15.0-STABLE"
#:branch "stable/15"
#:source-root "/usr/src"
#:target "amd64"
#:target-arch "amd64"
#:kernconf "GENERIC")
```
Confirmed:
```text
kernel_store=/frx/store/8fcef04c7e507e86ea5e92f251fe3c6ac1aa3bcf4809fa77ddd8b92854bfcde0-freebsd-native-kernel-15.0-STABLE-declarative
bootloader_store=/frx/store/7a0ba431e487dc35a8f6318108da16a37c8426c43e77e7a7f91404ba1d980eef-freebsd-native-bootloader-15.0-STABLE-declarative
runtime_store=/frx/store/17c24ad20ddcb136c39352b68e758deae0b480258ba0128a5546f696a7eba0a6-freebsd-native-runtime-15.0-STABLE-declarative
native_base_store_count=3
host_base_store_count=0
freebsd_base_name=stable-default
freebsd_base_version_label=15.0-STABLE-declarative
freebsd_base_release=15.0-STABLE
freebsd_base_branch=stable/15
freebsd_base_source_root=/usr/src
freebsd_base_kernconf=GENERIC
declarative_base_input=ok
```
The harness also confirmed:
- `metadata/freebsd-base.scm` exists
- `parameters.scm` records the declared base
- `metadata/store-layout.scm` records the declared base
- native build info files record the declared base version/branch
## Result
Phase 15.1 is complete.
Fruix now has an explicit declarative FreeBSD base input in the system model, while still allowing the current validated `/usr/src`-based path to work unchanged by default.

View File

@@ -1,7 +1,20 @@
(define-module (fruix packages freebsd)
#:use-module (srfi srfi-1)
#:use-module (srfi srfi-9)
#:use-module (srfi srfi-13)
#:export (freebsd-release
freebsd-base
freebsd-base?
freebsd-base-name
freebsd-base-version-label
freebsd-base-release
freebsd-base-branch
freebsd-base-source-root
freebsd-base-target
freebsd-base-target-arch
freebsd-base-kernconf
freebsd-base-make-flags
%default-freebsd-base
freebsd-package?
freebsd-package-name
freebsd-package-version
@@ -33,6 +46,13 @@
freebsd-native-runtime
freebsd-native-bootloader
freebsd-native-headers
freebsd-native-kernel-for
freebsd-native-world-for
freebsd-native-runtime-for
freebsd-native-bootloader-for
freebsd-native-headers-for
freebsd-native-system-packages-for
freebsd-native-development-profile-packages-for
freebsd-native-build-package?
freebsd-host-staged-package?
%freebsd-native-system-packages
@@ -67,6 +87,53 @@
(define freebsd-release "15.0-STABLE")
(define-record-type <freebsd-base>
(make-freebsd-base name version-label release branch source-root target
target-arch kernconf make-flags)
freebsd-base?
(name freebsd-base-name)
(version-label freebsd-base-version-label)
(release freebsd-base-release)
(branch freebsd-base-branch)
(source-root freebsd-base-source-root)
(target freebsd-base-target)
(target-arch freebsd-base-target-arch)
(kernconf freebsd-base-kernconf)
(make-flags freebsd-base-make-flags))
(define default-native-make-flags
'("__MAKE_CONF=/dev/null"
"SRCCONF=/dev/null"
"SRC_ENV_CONF=/dev/null"
"MK_DEBUG_FILES=no"
"MK_TESTS=no"))
(define (default-freebsd-branch release)
(let ((major (car (string-split release #\.))))
(cond
((string-contains release "STABLE")
(string-append "stable/" major))
((string-contains release "RELEASE")
(string-append "releng/" major))
(else
"unknown"))))
(define* (freebsd-base #:key
(name "default")
(version-label freebsd-release)
(release freebsd-release)
(branch (default-freebsd-branch release))
(source-root "/usr/src")
(target "amd64")
(target-arch "amd64")
(kernconf "GENERIC")
(make-flags default-native-make-flags))
(make-freebsd-base name version-label release branch source-root target
target-arch kernconf make-flags))
(define %default-freebsd-base
(freebsd-base))
(define freebsd-kernel
(freebsd-package
#:name "freebsd-kernel"
@@ -469,150 +536,145 @@ library for profile experiments."
#:install-plan
'((file "/lib/libz.so.6" "lib/libz.so.6"))))
(define freebsd-native-kernel
(define default-native-world-prune-paths
'("usr/share/doc"
"usr/share/examples"
"usr/share/info"
"usr/share/man"
"usr/tests"))
(define default-native-runtime-prune-paths
'("boot"
"rescue"
"usr/include"
"usr/lib/debug"
"usr/lib32"
"usr/obj"
"usr/src"
"usr/share/doc"
"usr/share/examples"
"usr/share/info"
"usr/share/man"
"usr/share/mk"
"usr/tests"))
(define default-native-bootloader-keep-paths
'("boot/loader"
"boot/loader.efi"
"boot/device.hints"
"boot/defaults"
"boot/lua"))
(define default-native-headers-keep-paths
'("usr/include"
"usr/share/mk"))
(define (freebsd-base-native-plan base)
`((base-name . ,(freebsd-base-name base))
(base-version-label . ,(freebsd-base-version-label base))
(base-release . ,(freebsd-base-release base))
(base-branch . ,(freebsd-base-branch base))
(source-root . ,(freebsd-base-source-root base))
(target . ,(freebsd-base-target base))
(target-arch . ,(freebsd-base-target-arch base))
(kernconf . ,(freebsd-base-kernconf base))
(make-flags . ,(freebsd-base-make-flags base))))
(define (freebsd-native-plan base extra-fields)
(append (freebsd-base-native-plan base) extra-fields))
(define (freebsd-native-kernel-for base)
(freebsd-package
#:name "freebsd-native-kernel"
#:version freebsd-release
#:version (freebsd-base-version-label base)
#:build-system 'freebsd-kernel-build-system
#:home-page "https://www.freebsd.org/"
#:synopsis "Native Fruix-managed FreeBSD kernel artifact"
#:description
"FreeBSD-specific package definition that builds a kernel from /usr/src and
stages the resulting boot/kernel tree as a real Fruix store artifact. This is
the first native replacement for the earlier host-copy kernel package."
"FreeBSD-specific package definition that builds a kernel from a declared
FreeBSD base input and stages the resulting boot/kernel tree as a real Fruix
store artifact."
#:license 'bsd-2
#:install-plan
'((source-root . "/usr/src")
(target . "amd64")
(target-arch . "amd64")
(kernconf . "GENERIC")
(make-flags . ("__MAKE_CONF=/dev/null"
"SRCCONF=/dev/null"
"SRC_ENV_CONF=/dev/null"
"MK_DEBUG_FILES=no"
"MK_TESTS=no")))))
(freebsd-native-plan base '())))
(define freebsd-native-world
(define (freebsd-native-world-for base)
(freebsd-package
#:name "freebsd-native-world"
#:version freebsd-release
#:version (freebsd-base-version-label base)
#:build-system 'freebsd-world-build-system
#:home-page "https://www.freebsd.org/"
#:synopsis "Native Fruix-managed FreeBSD world artifact"
#:description
"FreeBSD-specific package definition that builds and installs a broad
native world from /usr/src into a real Fruix store artifact. It still keeps a
large cross-section of boot and runtime files together and now serves as the
broad source artifact that later native runtime/boot splits derive from."
native world from a declared FreeBSD base input into a real Fruix store
artifact."
#:license 'bsd-2
#:install-plan
'((source-root . "/usr/src")
(target . "amd64")
(target-arch . "amd64")
(kernconf . "GENERIC")
(make-flags . ("__MAKE_CONF=/dev/null"
"SRCCONF=/dev/null"
"SRC_ENV_CONF=/dev/null"
"MK_DEBUG_FILES=no"
"MK_TESTS=no"))
(prune-paths . ("usr/share/doc"
"usr/share/examples"
"usr/share/info"
"usr/share/man"
"usr/tests")))))
(freebsd-native-plan base
`((prune-paths . ,default-native-world-prune-paths)))))
(define freebsd-native-runtime
(define (freebsd-native-runtime-for base)
(freebsd-package
#:name "freebsd-native-runtime"
#:version freebsd-release
#:version (freebsd-base-version-label base)
#:build-system 'freebsd-world-build-system
#:home-page "https://www.freebsd.org/"
#:synopsis "Native Fruix-managed FreeBSD runtime slice"
#:description
"FreeBSD-specific package definition that stages a runtime-focused slice of
installworld/distribution from /usr/src. It removes the boot tree and obvious
development-oriented paths so the validated Fruix guest can use an explicit
native runtime output rather than reusing the broader native world artifact for
both boot and runtime roles."
installworld/distribution from a declared FreeBSD base input."
#:license 'bsd-2
#:install-plan
'((source-root . "/usr/src")
(target . "amd64")
(target-arch . "amd64")
(kernconf . "GENERIC")
(make-flags . ("__MAKE_CONF=/dev/null"
"SRCCONF=/dev/null"
"SRC_ENV_CONF=/dev/null"
"MK_DEBUG_FILES=no"
"MK_TESTS=no"))
(prune-paths . ("boot"
"rescue"
"usr/include"
"usr/lib/debug"
"usr/lib32"
"usr/obj"
"usr/src"
"usr/share/doc"
"usr/share/examples"
"usr/share/info"
"usr/share/man"
"usr/share/mk"
"usr/tests")))))
(freebsd-native-plan base
`((prune-paths . ,default-native-runtime-prune-paths)))))
(define freebsd-native-bootloader
(define (freebsd-native-bootloader-for base)
(freebsd-package
#:name "freebsd-native-bootloader"
#:version freebsd-release
#:version (freebsd-base-version-label base)
#:build-system 'freebsd-world-build-system
#:home-page "https://www.freebsd.org/"
#:synopsis "Native Fruix-managed FreeBSD boot asset slice"
#:description
"FreeBSD-specific package definition that stages only the loader and boot
support assets needed by the validated Fruix image path. It is the narrower
native replacement for using the broad native world output as a temporary
boot-source artifact."
support assets needed by the validated Fruix image path from a declared
FreeBSD base input."
#:license 'bsd-2
#:install-plan
'((source-root . "/usr/src")
(target . "amd64")
(target-arch . "amd64")
(kernconf . "GENERIC")
(make-flags . ("__MAKE_CONF=/dev/null"
"SRCCONF=/dev/null"
"SRC_ENV_CONF=/dev/null"
"MK_DEBUG_FILES=no"
"MK_TESTS=no"))
(keep-paths . ("boot/loader"
"boot/loader.efi"
"boot/device.hints"
"boot/defaults"
"boot/lua")))))
(freebsd-native-plan base
`((keep-paths . ,default-native-bootloader-keep-paths)))))
(define freebsd-native-headers
(define (freebsd-native-headers-for base)
(freebsd-package
#:name "freebsd-native-headers"
#:version freebsd-release
#:version (freebsd-base-version-label base)
#:build-system 'freebsd-world-build-system
#:home-page "https://www.freebsd.org/"
#:synopsis "Native Fruix-managed FreeBSD headers slice"
#:description
"FreeBSD-specific package definition that stages the userland header set and
build-system support files from installworld/distribution so development
profiles can depend on an explicit headers artifact rather than on the runtime
slice."
build-system support files from installworld/distribution for a declared
FreeBSD base input."
#:license 'bsd-2
#:install-plan
'((source-root . "/usr/src")
(target . "amd64")
(target-arch . "amd64")
(kernconf . "GENERIC")
(make-flags . ("__MAKE_CONF=/dev/null"
"SRCCONF=/dev/null"
"SRC_ENV_CONF=/dev/null"
"MK_DEBUG_FILES=no"
"MK_TESTS=no"))
(keep-paths . ("usr/include"
"usr/share/mk")))))
(freebsd-native-plan base
`((keep-paths . ,default-native-headers-keep-paths)))))
(define freebsd-native-kernel
(freebsd-native-kernel-for %default-freebsd-base))
(define freebsd-native-world
(freebsd-native-world-for %default-freebsd-base))
(define freebsd-native-runtime
(freebsd-native-runtime-for %default-freebsd-base))
(define freebsd-native-bootloader
(freebsd-native-bootloader-for %default-freebsd-base))
(define freebsd-native-headers
(freebsd-native-headers-for %default-freebsd-base))
(define (freebsd-native-build-package? package)
(not (not (memq (freebsd-package-build-system package)
@@ -681,12 +743,12 @@ slice."
(fourth-wave . (freebsd-kernel-headers freebsd-clang-toolchain))
(fifth-wave . (freebsd-gmake freebsd-autotools freebsd-openssl freebsd-zlib freebsd-sh freebsd-bash))))
(define %freebsd-native-system-packages
(list freebsd-native-runtime))
(define (freebsd-native-system-packages-for base)
(list (freebsd-native-runtime-for base)))
(define %freebsd-native-development-profile-packages
(list freebsd-native-runtime
freebsd-native-headers
(define (freebsd-native-development-profile-packages-for base)
(list (freebsd-native-runtime-for base)
(freebsd-native-headers-for base)
freebsd-clang-toolchain
freebsd-gmake
freebsd-autotools
@@ -695,6 +757,12 @@ slice."
freebsd-sh
freebsd-bash))
(define %freebsd-native-system-packages
(freebsd-native-system-packages-for %default-freebsd-base))
(define %freebsd-native-development-profile-packages
(freebsd-native-development-profile-packages-for %default-freebsd-base))
(define %freebsd-core-packages %freebsd-host-staged-core-packages)
(define %freebsd-development-profile-packages %freebsd-host-staged-development-profile-packages)
(define %freebsd-system-packages %freebsd-host-staged-system-packages)

View File

@@ -35,6 +35,7 @@
operating-system
operating-system?
operating-system-host-name
operating-system-freebsd-base
operating-system-kernel
operating-system-bootloader
operating-system-base-packages
@@ -96,11 +97,12 @@
(make-file-system device mount-point type options needed-for-boot?))
(define-record-type <operating-system>
(make-operating-system host-name kernel bootloader base-packages users groups
(make-operating-system host-name freebsd-base kernel bootloader base-packages users groups
file-systems services loader-entries rc-conf-entries
init-mode ready-marker root-authorized-keys)
operating-system?
(host-name operating-system-host-name)
(freebsd-base operating-system-freebsd-base)
(kernel operating-system-kernel)
(bootloader operating-system-bootloader)
(base-packages operating-system-base-packages)
@@ -116,6 +118,7 @@
(define* (operating-system #:key
(host-name "fruix-freebsd")
(freebsd-base %default-freebsd-base)
(kernel freebsd-kernel)
(bootloader freebsd-bootloader)
(base-packages %freebsd-system-packages)
@@ -160,7 +163,7 @@
(init-mode 'freebsd-init+rc.d-shepherd)
(ready-marker "/var/lib/fruix/ready")
(root-authorized-keys '()))
(make-operating-system host-name kernel bootloader base-packages users groups
(make-operating-system host-name freebsd-base kernel bootloader base-packages users groups
file-systems services loader-entries rc-conf-entries
init-mode ready-marker root-authorized-keys))
@@ -304,9 +307,16 @@
(kernconf-sha256 . ,(file-hash kernconf-path))
(make-flags . ,make-flags))))
(define (native-build-declared-base plan)
`((name . ,(build-plan-ref plan 'base-name "default"))
(version-label . ,(build-plan-ref plan 'base-version-label freebsd-release))
(release . ,(build-plan-ref plan 'base-release freebsd-release))
(branch . ,(build-plan-ref plan 'base-branch "unknown"))))
(define (native-build-manifest-string package input-paths)
(let* ((plan (freebsd-package-install-plan package))
(common (native-build-common-manifest plan))
(declared-base (native-build-declared-base plan))
(keep-paths (build-plan-ref plan 'keep-paths '()))
(prune-paths (build-plan-ref plan 'prune-paths '())))
(string-append
@@ -314,7 +324,9 @@
"version=" (freebsd-package-version package) "\n"
"build-system=" (symbol->string (freebsd-package-build-system package)) "\n"
"inputs=" (string-join input-paths ",") "\n"
"native-build-common=\n"
"declared-base=\n"
(object->string declared-base)
"\nnative-build-common=\n"
(object->string common)
"\nkeep-paths=\n"
(object->string keep-paths)
@@ -466,6 +478,7 @@
(let ((plan (freebsd-package-install-plan package)))
`((package . ,(freebsd-package-name package))
(version . ,(freebsd-package-version package))
(declared-base . ,(native-build-declared-base plan))
(build-system . ,(freebsd-package-build-system package))
(source-root . ,(assoc-ref common 'source-root))
(source-tree-sha256 . ,(assoc-ref common 'source-tree-sha256))
@@ -669,6 +682,17 @@
(define (package-names packages)
(map freebsd-package-name packages))
(define (freebsd-base-spec base)
`((name . ,(freebsd-base-name base))
(version-label . ,(freebsd-base-version-label base))
(release . ,(freebsd-base-release base))
(branch . ,(freebsd-base-branch base))
(source-root . ,(freebsd-base-source-root base))
(target . ,(freebsd-base-target base))
(target-arch . ,(freebsd-base-target-arch base))
(kernconf . ,(freebsd-base-kernconf base))
(make-flags . ,(freebsd-base-make-flags base))))
(define (duplicate-elements values)
(let loop ((rest values) (seen '()) (duplicates '()))
(match rest
@@ -680,6 +704,7 @@
(define (validate-operating-system os)
(let* ((host-name (operating-system-host-name os))
(base (operating-system-freebsd-base os))
(users (operating-system-users os))
(groups (operating-system-groups os))
(file-systems (operating-system-file-systems os))
@@ -689,6 +714,8 @@
(init-mode (operating-system-init-mode os)))
(when (string-null? host-name)
(error "operating-system host-name must not be empty"))
(unless (freebsd-base? base)
(error "operating-system freebsd-base must be a <freebsd-base> record"))
(let ((dups (duplicate-elements user-names)))
(unless (null? dups)
(error "duplicate user names in operating-system" dups)))
@@ -1196,6 +1223,7 @@
"etc/shells"
"etc/motd"
"etc/ttys"
"metadata/freebsd-base.scm"
"metadata/host-base-provenance.scm"
"metadata/store-layout.scm"
"activate"
@@ -1241,6 +1269,7 @@
(define (operating-system-closure-spec os)
(validate-operating-system os)
`((host-name . ,(operating-system-host-name os))
(freebsd-base . ,(freebsd-base-spec (operating-system-freebsd-base os)))
(kernel-package . ,(freebsd-package-name (operating-system-kernel os)))
(bootloader-package . ,(freebsd-package-name (operating-system-bootloader os)))
(base-package-count . ,(length (operating-system-base-packages os)))
@@ -1355,11 +1384,14 @@
store-classification))))
(fruix-runtime-stores (list guile-store guile-extra-store shepherd-store))
(metadata-files
`(("metadata/host-base-provenance.scm"
`(("metadata/freebsd-base.scm"
. ,(object->string (freebsd-base-spec (operating-system-freebsd-base os))))
("metadata/host-base-provenance.scm"
. ,(object->string (host-freebsd-provenance)))
("metadata/store-layout.scm"
. ,(object->string
`((host-base-store-count . ,(length host-base-stores))
`((freebsd-base . ,(freebsd-base-spec (operating-system-freebsd-base os)))
(host-base-store-count . ,(length host-base-stores))
(host-base-stores . ,host-base-stores)
(native-base-store-count . ,(length native-base-stores))
(native-base-stores . ,native-base-stores)
@@ -1433,6 +1465,7 @@
(host-base-stores . ,host-base-stores)
(native-base-stores . ,native-base-stores)
(fruix-runtime-stores . ,fruix-runtime-stores)
(freebsd-base-file . ,(string-append closure-path "/metadata/freebsd-base.scm"))
(host-base-provenance-file . ,(string-append closure-path "/metadata/host-base-provenance.scm"))
(store-layout-file . ,(string-append closure-path "/metadata/store-layout.scm"))
(generated-files . ,(map car generated-files))
@@ -1519,6 +1552,7 @@
(root-partition-label "fruix-root")
(serial-console "comconsole"))
`((host-name . ,(operating-system-host-name os))
(freebsd-base . ,(freebsd-base-spec (operating-system-freebsd-base os)))
(boot-mode . ,boot-mode)
(image-format . ,image-format)
(partition-scheme . ,partition-scheme)
@@ -1698,6 +1732,7 @@
(host-base-stores . ,(assoc-ref closure 'host-base-stores))
(native-base-stores . ,(assoc-ref closure 'native-base-stores))
(fruix-runtime-stores . ,(assoc-ref closure 'fruix-runtime-stores))
(freebsd-base-file . ,(assoc-ref closure 'freebsd-base-file))
(host-base-provenance-file . ,(assoc-ref closure 'host-base-provenance-file))
(store-layout-file . ,(assoc-ref closure 'store-layout-file))
(image-spec . ,image-spec)

View File

@@ -2,6 +2,7 @@
!#
(use-modules (fruix system freebsd)
(fruix packages freebsd)
(ice-9 format)
(ice-9 match)
(srfi srfi-1)
@@ -174,6 +175,7 @@ Options:\n\
(host-base-stores (assoc-ref result 'host-base-stores))
(native-base-stores (assoc-ref result 'native-base-stores))
(fruix-runtime-stores (assoc-ref result 'fruix-runtime-stores))
(base (operating-system-freebsd-base os))
(host-provenance (call-with-input-file (assoc-ref result 'host-base-provenance-file) read)))
(emit-metadata
`((action . "build")
@@ -181,6 +183,15 @@ Options:\n\
(system_variable . ,resolved-symbol)
(store_dir . ,store-dir)
(closure_path . ,closure-path)
(freebsd_base_name . ,(freebsd-base-name base))
(freebsd_base_version_label . ,(freebsd-base-version-label base))
(freebsd_base_release . ,(freebsd-base-release base))
(freebsd_base_branch . ,(freebsd-base-branch base))
(freebsd_base_source_root . ,(freebsd-base-source-root base))
(freebsd_base_target . ,(freebsd-base-target base))
(freebsd_base_target_arch . ,(freebsd-base-target-arch base))
(freebsd_base_kernconf . ,(freebsd-base-kernconf base))
(freebsd_base_file . ,(assoc-ref result 'freebsd-base-file))
(ready_marker . ,(operating-system-ready-marker os))
(kernel_store . ,(assoc-ref result 'kernel-store))
(bootloader_store . ,(assoc-ref result 'bootloader-store))
@@ -234,12 +245,22 @@ Options:\n\
(host-base-stores (assoc-ref result 'host-base-stores))
(native-base-stores (assoc-ref result 'native-base-stores))
(fruix-runtime-stores (assoc-ref result 'fruix-runtime-stores))
(base (operating-system-freebsd-base os))
(host-provenance (call-with-input-file (assoc-ref result 'host-base-provenance-file) read)))
(emit-metadata
`((action . "image")
(os_file . ,os-file)
(system_variable . ,resolved-symbol)
(store_dir . ,store-dir)
(freebsd_base_name . ,(freebsd-base-name base))
(freebsd_base_version_label . ,(freebsd-base-version-label base))
(freebsd_base_release . ,(freebsd-base-release base))
(freebsd_base_branch . ,(freebsd-base-branch base))
(freebsd_base_source_root . ,(freebsd-base-source-root base))
(freebsd_base_target . ,(freebsd-base-target base))
(freebsd_base_target_arch . ,(freebsd-base-target-arch base))
(freebsd_base_kernconf . ,(freebsd-base-kernconf base))
(freebsd_base_file . ,(assoc-ref result 'freebsd-base-file))
(disk_capacity . ,(assoc-ref image-spec 'disk-capacity))
(root_size . ,(assoc-ref image-spec 'root-size))
(image_store_path . ,(assoc-ref result 'image-store-path))

View File

@@ -0,0 +1,83 @@
(use-modules (fruix system freebsd)
(fruix packages freebsd))
(define phase15-base
(freebsd-base
#:name "__BASE_NAME__"
#:version-label "__BASE_VERSION_LABEL__"
#:release "__BASE_RELEASE__"
#:branch "__BASE_BRANCH__"
#:source-root "/usr/src"
#:target "amd64"
#:target-arch "amd64"
#:kernconf "GENERIC"))
(define phase15-operating-system
(operating-system
#:host-name "fruix-freebsd"
#:freebsd-base phase15-base
#:kernel (freebsd-native-kernel-for phase15-base)
#:bootloader (freebsd-native-bootloader-for phase15-base)
#:base-packages (freebsd-native-system-packages-for phase15-base)
#:groups (list (user-group #:name "wheel" #:gid 0 #:system? #t)
(user-group #:name "sshd" #:gid 22 #:system? #t)
(user-group #:name "_dhcp" #:gid 65 #:system? #t)
(user-group #:name "operator" #:gid 1000 #:system? #f))
#:users (list (user-account #:name "root"
#:uid 0
#:group "wheel"
#:comment "Charlie &"
#:home "/root"
#:shell "/bin/sh"
#:system? #t)
(user-account #:name "sshd"
#:uid 22
#:group "sshd"
#:comment "Secure Shell Daemon"
#:home "/var/empty"
#:shell "/usr/sbin/nologin"
#:system? #t)
(user-account #:name "_dhcp"
#:uid 65
#:group "_dhcp"
#:comment "dhcp programs"
#:home "/var/empty"
#:shell "/usr/sbin/nologin"
#:system? #t)
(user-account #:name "operator"
#:uid 1000
#:group "operator"
#:supplementary-groups '("wheel")
#:comment "Fruix Operator"
#:home "/home/operator"
#:shell "/bin/sh"
#:system? #f))
#:file-systems (list (file-system #:device "/dev/gpt/fruix-root"
#:mount-point "/"
#:type "ufs"
#:options "rw"
#:needed-for-boot? #t)
(file-system #:device "devfs"
#:mount-point "/dev"
#:type "devfs"
#:options "rw"
#:needed-for-boot? #t)
(file-system #:device "tmpfs"
#:mount-point "/tmp"
#:type "tmpfs"
#:options "rw,size=64m"))
#:services '(shepherd ready-marker sshd)
#:loader-entries '(("autoboot_delay" . "1")
("boot_multicons" . "YES")
("boot_serial" . "YES")
("console" . "comconsole,vidconsole"))
#:rc-conf-entries '(("clear_tmp_enable" . "NO")
("hostid_enable" . "NO")
("sendmail_enable" . "NONE")
("sshd_enable" . "YES")
("ifconfig_xn0" . "SYNCDHCP")
("ifconfig_em0" . "SYNCDHCP")
("ifconfig_vtnet0" . "SYNCDHCP"))
#:init-mode 'shepherd-pid1
#:ready-marker "/var/lib/fruix/ready"
#:root-authorized-keys '("__ROOT_AUTHORIZED_KEY__")))

View File

@@ -0,0 +1,180 @@
#!/bin/sh
set -eu
project_root=${PROJECT_ROOT:-$(pwd)}
script_dir=$(CDPATH= cd -- "$(dirname "$0")" && pwd)
fruix_cmd=$project_root/bin/fruix
os_template=${OS_TEMPLATE:-$script_dir/phase15-declarative-base-pid1-operating-system.scm.in}
system_name=${SYSTEM_NAME:-phase15-operating-system}
store_dir=${STORE_DIR:-/frx/store}
base_name=${BASE_NAME:-stable-default}
base_version_label=${BASE_VERSION_LABEL:-15.0-STABLE-declarative}
base_release=${BASE_RELEASE:-15.0-STABLE}
base_branch=${BASE_BRANCH:-stable/15}
metadata_target=${METADATA_OUT:-}
root_authorized_key_file=${ROOT_AUTHORIZED_KEY_FILE:-$HOME/.ssh/id_ed25519.pub}
[ -x "$fruix_cmd" ] || {
echo "fruix command is not executable: $fruix_cmd" >&2
exit 1
}
[ -f "$os_template" ] || {
echo "missing operating-system template: $os_template" >&2
exit 1
}
[ -f "$root_authorized_key_file" ] || {
echo "missing root authorized key file: $root_authorized_key_file" >&2
exit 1
}
cleanup=0
if [ -n "${WORKDIR:-}" ]; then
workdir=$WORKDIR
mkdir -p "$workdir"
else
workdir=$(mktemp -d /tmp/fruix-phase15-declarative-build.XXXXXX)
cleanup=1
fi
if [ "${KEEP_WORKDIR:-0}" -eq 1 ]; then
cleanup=0
fi
cleanup_workdir() {
if [ "$cleanup" -eq 1 ]; then
rm -rf "$workdir" 2>/dev/null || sudo rm -rf "$workdir"
fi
}
trap cleanup_workdir EXIT INT TERM
phase15_os_file=$workdir/phase15-declarative-base-operating-system.scm
build_out=$workdir/build.txt
metadata_file=$workdir/phase15-declarative-base-build-metadata.txt
root_authorized_key=$(tr -d '\n' < "$root_authorized_key_file")
sed \
-e "s|__BASE_NAME__|$base_name|g" \
-e "s|__BASE_VERSION_LABEL__|$base_version_label|g" \
-e "s|__BASE_RELEASE__|$base_release|g" \
-e "s|__BASE_BRANCH__|$base_branch|g" \
-e "s|__ROOT_AUTHORIZED_KEY__|$root_authorized_key|g" \
"$os_template" > "$phase15_os_file"
action_env() {
sudo env \
HOME="$HOME" \
GUILE_AUTO_COMPILE=0 \
FRUIX_FREEBSD_BUILD_JOBS="${FRUIX_FREEBSD_BUILD_JOBS:-8}" \
GUIX_SOURCE_DIR="${GUIX_SOURCE_DIR:-$HOME/repos/guix}" \
GUILE_BIN="${GUILE_BIN:-/tmp/guile-freebsd-validate-install/bin/guile}" \
GUILE_EXTRA_PREFIX="${GUILE_EXTRA_PREFIX:-/tmp/guile-gnutls-freebsd-validate-install}" \
SHEPHERD_PREFIX="${SHEPHERD_PREFIX:-/tmp/shepherd-freebsd-validate-install}" \
"$@"
}
action_env "$fruix_cmd" system build "$phase15_os_file" --system "$system_name" --store "$store_dir" >"$build_out"
closure_path=$(sed -n 's/^closure_path=//p' "$build_out")
kernel_store=$(sed -n 's/^kernel_store=//p' "$build_out")
bootloader_store=$(sed -n 's/^bootloader_store=//p' "$build_out")
native_base_store_count=$(sed -n 's/^native_base_store_count=//p' "$build_out")
native_base_stores=$(sed -n 's/^native_base_stores=//p' "$build_out")
host_base_store_count=$(sed -n 's/^host_base_store_count=//p' "$build_out")
freebsd_base_name_out=$(sed -n 's/^freebsd_base_name=//p' "$build_out")
freebsd_base_version_label_out=$(sed -n 's/^freebsd_base_version_label=//p' "$build_out")
freebsd_base_release_out=$(sed -n 's/^freebsd_base_release=//p' "$build_out")
freebsd_base_branch_out=$(sed -n 's/^freebsd_base_branch=//p' "$build_out")
freebsd_base_source_root_out=$(sed -n 's/^freebsd_base_source_root=//p' "$build_out")
freebsd_base_kernconf_out=$(sed -n 's/^freebsd_base_kernconf=//p' "$build_out")
freebsd_base_file=$(sed -n 's/^freebsd_base_file=//p' "$build_out")
store_layout_file=$(sed -n 's/^store_layout_file=//p' "$build_out")
[ -n "$closure_path" ] || { echo "missing closure path" >&2; exit 1; }
[ "$host_base_store_count" = 0 ] || { echo "expected zero host base stores, got: $host_base_store_count" >&2; exit 1; }
[ "$native_base_store_count" = 3 ] || { echo "expected three native base stores, got: $native_base_store_count" >&2; exit 1; }
[ "$freebsd_base_name_out" = "$base_name" ] || { echo "unexpected freebsd base name: $freebsd_base_name_out" >&2; exit 1; }
[ "$freebsd_base_version_label_out" = "$base_version_label" ] || { echo "unexpected freebsd base version label: $freebsd_base_version_label_out" >&2; exit 1; }
[ "$freebsd_base_release_out" = "$base_release" ] || { echo "unexpected freebsd base release: $freebsd_base_release_out" >&2; exit 1; }
[ "$freebsd_base_branch_out" = "$base_branch" ] || { echo "unexpected freebsd base branch: $freebsd_base_branch_out" >&2; exit 1; }
[ "$freebsd_base_source_root_out" = /usr/src ] || { echo "unexpected freebsd base source root: $freebsd_base_source_root_out" >&2; exit 1; }
[ "$freebsd_base_kernconf_out" = GENERIC ] || { echo "unexpected freebsd base kernconf: $freebsd_base_kernconf_out" >&2; exit 1; }
[ -f "$freebsd_base_file" ] || { echo "missing freebsd base file: $freebsd_base_file" >&2; exit 1; }
[ -f "$store_layout_file" ] || { echo "missing store layout file: $store_layout_file" >&2; exit 1; }
case "$kernel_store" in
/frx/store/*-freebsd-native-kernel-$base_version_label) : ;;
*) echo "unexpected kernel store path: $kernel_store" >&2; exit 1 ;;
esac
case "$bootloader_store" in
/frx/store/*-freebsd-native-bootloader-$base_version_label) : ;;
*) echo "unexpected bootloader store path: $bootloader_store" >&2; exit 1 ;;
esac
runtime_store=$(printf '%s\n' "$native_base_stores" | tr ',' '\n' | grep "freebsd-native-runtime-$base_version_label$" | head -n 1)
[ -n "$runtime_store" ] || { echo "failed to recover runtime store" >&2; exit 1; }
for path in "$kernel_store/.freebsd-native-build-info.scm" "$bootloader_store/.freebsd-native-build-info.scm" "$runtime_store/.freebsd-native-build-info.scm"; do
[ -f "$path" ] || {
echo "missing native build info file: $path" >&2
exit 1
}
grep -F "version-label . \"$base_version_label\"" "$path" >/dev/null || {
echo "native build info missing declared version label in $path" >&2
exit 1
}
grep -F "branch . \"$base_branch\"" "$path" >/dev/null || {
echo "native build info missing declared branch in $path" >&2
exit 1
}
done
grep -F "(name . \"$base_name\")" "$freebsd_base_file" >/dev/null || {
echo "freebsd base file missing name" >&2
exit 1
}
grep -F "(version-label . \"$base_version_label\")" "$freebsd_base_file" >/dev/null || {
echo "freebsd base file missing version label" >&2
exit 1
}
grep -F "(branch . \"$base_branch\")" "$store_layout_file" >/dev/null || {
echo "store layout file missing declared base branch" >&2
exit 1
}
grep -F "(freebsd-base" "$closure_path/parameters.scm" >/dev/null || {
echo "closure parameters do not record the freebsd base declaration" >&2
exit 1
}
closure_base=$(basename "$closure_path")
cat >"$metadata_file" <<EOF
workdir=$workdir
phase15_os_file=$phase15_os_file
closure_path=$closure_path
closure_base=$closure_base
kernel_store=$kernel_store
bootloader_store=$bootloader_store
runtime_store=$runtime_store
native_base_store_count=$native_base_store_count
native_base_stores=$native_base_stores
host_base_store_count=$host_base_store_count
freebsd_base_name=$freebsd_base_name_out
freebsd_base_version_label=$freebsd_base_version_label_out
freebsd_base_release=$freebsd_base_release_out
freebsd_base_branch=$freebsd_base_branch_out
freebsd_base_source_root=$freebsd_base_source_root_out
freebsd_base_kernconf=$freebsd_base_kernconf_out
freebsd_base_file=$freebsd_base_file
store_layout_file=$store_layout_file
declarative_base_input=ok
EOF
if [ -n "$metadata_target" ]; then
mkdir -p "$(dirname "$metadata_target")"
cp "$metadata_file" "$metadata_target"
fi
printf 'PASS phase15-declarative-base-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"