92 lines
5.2 KiB
Bash
Executable File
92 lines
5.2 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
source "$(dirname -- "${BASH_SOURCE[0]}")/lib.sh"
|
|
[[ $# == 0 ]] || die 'Usage: PROFILE=cli tools/build-rootfs'
|
|
profile=${PROFILE:-cli}
|
|
[[ $profile == cli || $profile == development || $profile == recovery ]] || die 'Supported profiles: cli, development, recovery'
|
|
use_xbps
|
|
check_void_pin
|
|
need python3
|
|
python3 -c 'import sys; assert sys.version_info >= (3, 14), "Rootfs assembly requires Python 3.14+ for zstd XBPS archives"'
|
|
cd "$FDS_ROOT"
|
|
mkdir -p out/logs out/manifests out/packages out/cache/rootfs
|
|
exec 9>out/.rootfs.lock
|
|
flock -n 9 || die 'Another rootfs build is already running'
|
|
missing=()
|
|
for package in qemu-user-aarch64 util-linux; do
|
|
if ! xbps-query -r "$FDS_VOID/masterdir-x86_64" "$package" >/dev/null 2>&1; then
|
|
missing+=("$package")
|
|
fi
|
|
done
|
|
if (( ${#missing[@]} )); then
|
|
tools/in-void xbps-install -y "${missing[@]}"
|
|
fi
|
|
tools/build-base-packages
|
|
work=$(mktemp -d "$FDS_ROOT/out/rootfs-build.XXXXXX")
|
|
root="$work/root"
|
|
printf 'Rootfs build workspace: %s\n' "$work"
|
|
# Keep failed workspaces for diagnosis. No partial result replaces a good archive.
|
|
mkdir -p "$root"
|
|
python3 tools/rootfs-layout "$root" packages/fds-base-files/files/layout.json
|
|
mkdir -p "$root/var/db/xbps/keys" "$work/config"
|
|
cp "$FDS_VOID/common/repo-keys/"*.plist "$root/var/db/xbps/keys/"
|
|
cp packages/fds-base-files/files/10-fds.conf "$work/config/"
|
|
mapfile -t packages < <(sed -e 's/#.*//' -e '/^[[:space:]]*$/d' image/base-packages.list "profiles/$profile.list")
|
|
(( ${#packages[@]} )) || die 'Empty image/base-packages.list'
|
|
for package in "${packages[@]}"; do
|
|
[[ $package =~ ^[a-zA-Z0-9][a-zA-Z0-9+_.-]*$ ]] || die "Invalid base package: $package"
|
|
done
|
|
# Extract with native XBPS in the build user namespace. The on-disk tree belongs
|
|
# to the host user; rootfs-archive restores ownership from package headers.
|
|
repository=https://repo-default.voidlinux.org/current/aarch64
|
|
if [[ ${FDS_OFFLINE:-0} == 1 ]]; then
|
|
repository="$FDS_ROOT/.host/frozen/$profile"
|
|
[[ -f $repository/aarch64-repodata ]] || die "Missing frozen repository for $profile"
|
|
fi
|
|
tools/in-void env XBPS_ARCH=aarch64 XBPS_TARGET_ARCH=aarch64 \
|
|
xbps-install -r "$root" -C "$work/config" \
|
|
-c "$FDS_ROOT/out/cache/rootfs" -i \
|
|
-R "$repository" \
|
|
-R "$FDS_ROOT/out/packages" -SyU --reproducible "${packages[@]}"
|
|
printf '%s\n' "$profile" >"$root/usr/share/fds/image-profile"
|
|
install -Dm644 docs/internal-storage.md "$root/usr/share/doc/fds/internal-storage.md"
|
|
install -Dm644 docs/recovery.md "$root/usr/share/doc/fds/recovery.md"
|
|
install -Dm644 docs/releases.md "$root/usr/share/doc/fds/releases.md"
|
|
install -Dm644 tools/capture-hardware "$root/usr/share/fds/capture-hardware"
|
|
python3 tools/rootfs-audit "$root" --unconfigured
|
|
epoch=$(git -C "$FDS_VOID" show -s --format=%ct HEAD)
|
|
tools/in-rootfs "$root" /usr/bin/env SOURCE_DATE_EPOCH="$epoch" /bin/bash /tmp/fds-finalize
|
|
# Apply the upstream iputils policy with direct QEMU and a namespace-local
|
|
# CAP_SETFCAP; the exported capability must be an actual persisted xattr.
|
|
tools/in-rootfs "$root" --direct /usr/bin/setcap CAP_NET_RAW+p /usr/bin/iputils-ping
|
|
tools/in-rootfs "$root" --direct /usr/bin/getcap /usr/bin/iputils-ping | grep -qx '/usr/bin/iputils-ping cap_net_raw=p'
|
|
python3 tools/rootfs-audit "$root"
|
|
tools/rootfs-runtime-check "$root"
|
|
# Preserve the exact selected package inputs, independently of future repository
|
|
# updates. Local FDS package versions can be rebuilt, so copy them per build.
|
|
archive_inputs=(out/cache/rootfs out/packages)
|
|
if [[ ${FDS_OFFLINE:-0} == 1 ]]; then
|
|
archive_inputs+=("$repository")
|
|
fi
|
|
python3 tools/rootfs-archive "$root" "$work" "${archive_inputs[@]}"
|
|
{
|
|
printf 'profile=%s\nvoid_commit=%s\n' "$profile" "$(cat VOID_PACKAGES_COMMIT)"
|
|
printf 'emulation=private-user-namespace-binfmt\n'
|
|
tools/in-void xbps-query -p pkgver qemu-user-aarch64
|
|
date -u '+built_at=%Y-%m-%dT%H:%M:%SZ'
|
|
} >"$work/build.txt"
|
|
find packages/fds-base packages/fds-base-files packages/fds-init packages/fds-cli packages/fds-cartridged packages/fds-kernel packages/fds-eink packages/fds-dhcpcd profiles s6/source -type f -print0 | sort -z | \
|
|
xargs -0 sha256sum >"$work/build-inputs.sha256"
|
|
sha256sum image/base-packages.list tools/{build-rootfs,build-base-packages,build-fds,build-fds-package,build-kernel,in-void,in-rootfs,rootfs-namespace,finalize-rootfs,rootfs-audit,rootfs-archive,rootfs-runtime-check,rootfs-layout,rootfs_lib.py,lib.sh} \
|
|
>>"$work/build-inputs.sha256"
|
|
sha256sum docs/recovery.md docs/internal-storage.md docs/releases.md tools/capture-hardware tools/rust-notices tools/cargo-build .cargo/config.toml >>"$work/build-inputs.sha256"
|
|
cp out/manifests/fds-tools*.sha256 "$work/"
|
|
# The versioned build directory is the authoritative result; stable links are
|
|
# convenience pointers. Rename the archive last, after every acceptance check.
|
|
ln -sfn "${work##*/}/root" out/rootfs-aarch64
|
|
ln -sfn "../${work##*/}" out/manifests/rootfs-latest
|
|
ln -s "${work##*/}/rootfs-aarch64.tar" out/rootfs-aarch64.tar.next
|
|
mv -Tf out/rootfs-aarch64.tar.next out/rootfs-aarch64.tar
|
|
ln -s "${work##*/}/rootfs-aarch64.tar" "out/rootfs-$profile.tar.next"
|
|
mv -Tf "out/rootfs-$profile.tar.next" "out/rootfs-$profile.tar"
|
|
printf 'PASS: FDS rootfs built and verified: out/rootfs-aarch64.tar\n'
|