Produces a UEFI-bootable raw disk image for generic ARM64 hosts (QEMU virt, Ampere/Graviton cloud, ARM64 SBCs with UEFI). Reuses the existing 4-partition A/B layout from x86 (EFI 256 MB FAT32 + System A 512 MB ext4 + System B 512 MB ext4 + Data ext4 remainder). Changes: - build/scripts/create-disk-image.sh: TARGET_ARCH env var (amd64 default, arm64). Selects kernel source path, grub-mkimage target (x86_64-efi vs arm64-efi), EFI binary name (bootx64.efi vs BOOTAA64.EFI), grub.cfg variant, and whether to also install BIOS GRUB (x86 only). - build/grub/grub-arm64.cfg: ARM64 variant of grub.cfg. Identical A/B logic; console=ttyAMA0+ttyS0 to cover QEMU virt PL011, Ampere PL011, and Graviton 16550-compat. - build/Dockerfile.builder: add grub-efi-amd64-bin, grub-efi-arm64-bin, grub-pc-bin, grub-common, grub2-common so the builder container can produce EFI images for both architectures. - hack/dev-vm-arm64.sh: split into kernel mode (direct -kernel/-initrd, fast iteration) and --disk mode (UEFI firmware + GRUB + disk image, full integration test). Probes common UEFI firmware paths on Ubuntu/Fedora/macOS. Default kernel path now points at kernel-arm64-generic/Image with fallback to the renamed custom-kernel-rpi/Image. - test/qemu/test-boot-arm64-disk.sh: new CI test for the full UEFI -> GRUB -> kernel -> stage-90 boot chain. Uses a scratch copy of the disk so grubenv writes don't mutate the source artifact. - Makefile: new disk-image-arm64 target (depends on rootfs-arm64 + kernel-arm64), new test-boot-arm64-disk target, .PHONY + help updates. Phase 3 scaffold is in place. First real end-to-end ARM64 build runs in the next step on the Odroid runner — that's where we find out what's actually broken. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
314 lines
13 KiB
Makefile
314 lines
13 KiB
Makefile
.PHONY: all fetch kernel build-cloudinit build-update-agent build-cross rootfs initramfs \
|
|
iso disk-image disk-image-arm64 oci-image rpi-image \
|
|
kernel-arm64 kernel-rpi rootfs-arm64 rootfs-arm64-rpi \
|
|
test-boot test-k8s test-persistence test-deploy test-storage test-security test-all \
|
|
test-boot-arm64 test-boot-arm64-disk test-cloudinit test-update-agent \
|
|
bench-boot bench-resources \
|
|
dev-vm dev-vm-shell dev-vm-arm64 quick docker-build shellcheck \
|
|
kernel-audit clean distclean help
|
|
|
|
SHELL := /bin/bash
|
|
VERSION := $(shell cat VERSION)
|
|
BUILD_DIR := build
|
|
CACHE_DIR := $(BUILD_DIR)/cache
|
|
OUTPUT_DIR := output
|
|
ROOTFS_DIR := $(BUILD_DIR)/rootfs-work
|
|
|
|
# Load component versions
|
|
include $(BUILD_DIR)/config/versions.env
|
|
|
|
# Default target
|
|
all: iso
|
|
|
|
# =============================================================================
|
|
# Download external components
|
|
# =============================================================================
|
|
fetch:
|
|
@echo "==> Fetching components..."
|
|
@mkdir -p $(CACHE_DIR)
|
|
$(BUILD_DIR)/scripts/fetch-components.sh
|
|
|
|
# =============================================================================
|
|
# Build stages
|
|
# =============================================================================
|
|
kernel:
|
|
@echo "==> Building custom kernel (CONFIG_CGROUP_BPF=y)..."
|
|
$(BUILD_DIR)/scripts/build-kernel.sh
|
|
|
|
build-cloudinit:
|
|
@echo "==> Building cloud-init binary..."
|
|
$(BUILD_DIR)/scripts/build-cloudinit.sh
|
|
|
|
build-update-agent:
|
|
@echo "==> Building update agent..."
|
|
$(BUILD_DIR)/scripts/build-update-agent.sh
|
|
|
|
rootfs: fetch kernel build-cloudinit build-update-agent
|
|
@echo "==> Preparing rootfs..."
|
|
$(BUILD_DIR)/scripts/extract-core.sh
|
|
$(BUILD_DIR)/scripts/inject-kubesolo.sh
|
|
|
|
initramfs: rootfs
|
|
@echo "==> Packing initramfs..."
|
|
$(BUILD_DIR)/scripts/pack-initramfs.sh
|
|
|
|
iso: initramfs
|
|
@echo "==> Creating bootable ISO..."
|
|
$(BUILD_DIR)/scripts/create-iso.sh
|
|
@echo "==> Built: $(OUTPUT_DIR)/$(OS_NAME)-$(VERSION).iso"
|
|
|
|
disk-image: initramfs
|
|
@echo "==> Creating disk image..."
|
|
$(BUILD_DIR)/scripts/create-disk-image.sh
|
|
@echo "==> Built: $(OUTPUT_DIR)/$(OS_NAME)-$(VERSION).img"
|
|
|
|
oci-image: initramfs
|
|
@echo "==> Creating OCI container image..."
|
|
$(BUILD_DIR)/scripts/create-oci-image.sh
|
|
@echo "==> OCI image built"
|
|
|
|
# Cross-compile Go binaries for amd64 + arm64
|
|
build-cross:
|
|
@echo "==> Cross-compiling for amd64 + arm64..."
|
|
$(BUILD_DIR)/scripts/build-cross.sh
|
|
|
|
# =============================================================================
|
|
# ARM64 generic targets (mainline kernel, UEFI, virtio — for cloud / SBCs)
|
|
# =============================================================================
|
|
kernel-arm64:
|
|
@echo "==> Building generic ARM64 kernel (mainline LTS)..."
|
|
$(BUILD_DIR)/scripts/build-kernel-arm64.sh
|
|
|
|
# Generic ARM64 rootfs consumes the mainline kernel modules.
|
|
rootfs-arm64: build-cross
|
|
@echo "==> Preparing generic ARM64 rootfs..."
|
|
TARGET_ARCH=arm64 $(BUILD_DIR)/scripts/fetch-components.sh
|
|
TARGET_ARCH=arm64 $(BUILD_DIR)/scripts/extract-core.sh
|
|
TARGET_ARCH=arm64 TARGET_VARIANT=generic $(BUILD_DIR)/scripts/inject-kubesolo.sh
|
|
@echo "==> Packing generic ARM64 initramfs..."
|
|
$(BUILD_DIR)/scripts/pack-initramfs.sh
|
|
|
|
disk-image-arm64: rootfs-arm64 kernel-arm64
|
|
@echo "==> Creating generic ARM64 disk image (UEFI + GRUB A/B)..."
|
|
TARGET_ARCH=arm64 $(BUILD_DIR)/scripts/create-disk-image.sh
|
|
@echo "==> Built: $(OUTPUT_DIR)/$(OS_NAME)-$(VERSION).arm64.img"
|
|
|
|
# =============================================================================
|
|
# ARM64 Raspberry Pi targets (RPi-patched kernel, firmware blobs, SD card)
|
|
# =============================================================================
|
|
kernel-rpi:
|
|
@echo "==> Building RPi kernel (raspberrypi/linux)..."
|
|
$(BUILD_DIR)/scripts/build-kernel-rpi.sh
|
|
|
|
# RPi-flavoured rootfs consumes the RPi kernel modules.
|
|
rootfs-arm64-rpi: build-cross
|
|
@echo "==> Preparing RPi ARM64 rootfs..."
|
|
TARGET_ARCH=arm64 $(BUILD_DIR)/scripts/fetch-components.sh
|
|
TARGET_ARCH=arm64 $(BUILD_DIR)/scripts/extract-core.sh
|
|
TARGET_ARCH=arm64 TARGET_VARIANT=rpi $(BUILD_DIR)/scripts/inject-kubesolo.sh
|
|
@echo "==> Packing RPi ARM64 initramfs..."
|
|
$(BUILD_DIR)/scripts/pack-initramfs.sh
|
|
|
|
rpi-image: rootfs-arm64-rpi kernel-rpi
|
|
@echo "==> Creating Raspberry Pi SD card image..."
|
|
$(BUILD_DIR)/scripts/create-rpi-image.sh
|
|
@echo "==> Built: $(OUTPUT_DIR)/$(OS_NAME)-$(VERSION).rpi.img"
|
|
|
|
# =============================================================================
|
|
# Kernel validation
|
|
# =============================================================================
|
|
kernel-audit:
|
|
@echo "==> Auditing kernel configuration..."
|
|
$(BUILD_DIR)/config/kernel-audit.sh
|
|
|
|
# =============================================================================
|
|
# Testing
|
|
# =============================================================================
|
|
test-boot: iso
|
|
@echo "==> Testing boot in QEMU..."
|
|
test/qemu/test-boot.sh $(OUTPUT_DIR)/$(OS_NAME)-$(VERSION).iso
|
|
|
|
test-k8s: iso
|
|
@echo "==> Testing K8s readiness..."
|
|
test/integration/test-k8s-ready.sh $(OUTPUT_DIR)/$(OS_NAME)-$(VERSION).iso
|
|
|
|
test-persistence: disk-image
|
|
@echo "==> Testing persistence across reboot..."
|
|
test/qemu/test-persistence.sh $(OUTPUT_DIR)/$(OS_NAME)-$(VERSION).img
|
|
|
|
test-deploy: iso
|
|
@echo "==> Testing workload deployment..."
|
|
test/integration/test-deploy-workload.sh $(OUTPUT_DIR)/$(OS_NAME)-$(VERSION).iso
|
|
|
|
test-storage: iso
|
|
@echo "==> Testing local storage provisioning..."
|
|
test/integration/test-local-storage.sh $(OUTPUT_DIR)/$(OS_NAME)-$(VERSION).iso
|
|
|
|
test-security: iso
|
|
@echo "==> Testing security hardening..."
|
|
test/integration/test-security-hardening.sh $(OUTPUT_DIR)/$(OS_NAME)-$(VERSION).iso
|
|
|
|
test-boot-arm64:
|
|
@echo "==> Testing ARM64 boot in QEMU (direct kernel)..."
|
|
test/qemu/test-boot-arm64.sh
|
|
|
|
test-boot-arm64-disk: disk-image-arm64
|
|
@echo "==> Testing ARM64 UEFI disk boot in QEMU..."
|
|
test/qemu/test-boot-arm64-disk.sh $(OUTPUT_DIR)/$(OS_NAME)-$(VERSION).arm64.img
|
|
|
|
test-all: test-boot test-k8s test-persistence
|
|
|
|
# Cloud-init Go tests
|
|
test-cloudinit:
|
|
@echo "==> Testing cloud-init parser..."
|
|
cd cloud-init && go test ./... -v -count=1
|
|
|
|
# Update agent Go tests
|
|
test-update-agent:
|
|
@echo "==> Testing update agent..."
|
|
cd update && go test ./... -v -count=1
|
|
|
|
# A/B update integration tests
|
|
test-update: disk-image
|
|
@echo "==> Testing A/B update cycle..."
|
|
test/qemu/test-update.sh $(OUTPUT_DIR)/$(OS_NAME)-$(VERSION).img
|
|
|
|
test-rollback: disk-image
|
|
@echo "==> Testing rollback..."
|
|
test/qemu/test-rollback.sh $(OUTPUT_DIR)/$(OS_NAME)-$(VERSION).img
|
|
|
|
# Full integration test suite (requires more time)
|
|
test-integration: test-k8s test-deploy test-storage
|
|
|
|
# Benchmarks
|
|
bench-boot: iso
|
|
@echo "==> Benchmarking boot performance..."
|
|
test/benchmark/bench-boot.sh $(OUTPUT_DIR)/$(OS_NAME)-$(VERSION).iso --runs 3
|
|
|
|
bench-resources:
|
|
@echo "==> Benchmarking resource usage (requires running VM)..."
|
|
test/benchmark/bench-resources.sh
|
|
|
|
# =============================================================================
|
|
# Code quality
|
|
# =============================================================================
|
|
shellcheck:
|
|
@echo "==> Running shellcheck on init scripts..."
|
|
shellcheck -s sh init/init.sh init/lib/*.sh init/emergency-shell.sh
|
|
@echo "==> Running shellcheck on build scripts..."
|
|
shellcheck -s bash build/scripts/*.sh build/config/kernel-audit.sh
|
|
@echo "==> Running shellcheck on test scripts..."
|
|
shellcheck -s bash test/qemu/*.sh test/integration/*.sh test/kernel/*.sh
|
|
@echo "==> Running shellcheck on hack scripts..."
|
|
shellcheck -s bash hack/*.sh
|
|
@echo "==> All shellcheck checks passed"
|
|
|
|
# =============================================================================
|
|
# Development helpers
|
|
# =============================================================================
|
|
dev-vm: iso
|
|
@echo "==> Launching dev VM..."
|
|
hack/dev-vm.sh $(OUTPUT_DIR)/$(OS_NAME)-$(VERSION).iso
|
|
|
|
dev-vm-shell: iso
|
|
@echo "==> Launching dev VM (emergency shell)..."
|
|
hack/dev-vm.sh $(OUTPUT_DIR)/$(OS_NAME)-$(VERSION).iso --shell
|
|
|
|
dev-vm-debug: iso
|
|
@echo "==> Launching dev VM (debug mode)..."
|
|
hack/dev-vm.sh $(OUTPUT_DIR)/$(OS_NAME)-$(VERSION).iso --debug
|
|
|
|
dev-vm-arm64:
|
|
@echo "==> Launching ARM64 dev VM..."
|
|
hack/dev-vm-arm64.sh
|
|
|
|
# Fast rebuild: only repack initramfs + ISO (skip fetch/extract)
|
|
quick:
|
|
@echo "==> Quick rebuild (repack + ISO only)..."
|
|
$(BUILD_DIR)/scripts/inject-kubesolo.sh
|
|
$(BUILD_DIR)/scripts/pack-initramfs.sh
|
|
$(BUILD_DIR)/scripts/create-iso.sh
|
|
@echo "==> Quick rebuild complete: $(OUTPUT_DIR)/$(OS_NAME)-$(VERSION).iso"
|
|
|
|
# =============================================================================
|
|
# Docker-based reproducible build
|
|
# =============================================================================
|
|
docker-build:
|
|
@echo "==> Building in Docker..."
|
|
docker build -t kubesolo-os-builder -f $(BUILD_DIR)/Dockerfile.builder .
|
|
docker run --rm --privileged \
|
|
-v $(PWD)/$(OUTPUT_DIR):/output \
|
|
-v $(PWD)/$(CACHE_DIR):/cache \
|
|
kubesolo-os-builder iso OUTPUT_DIR=/output CACHE_DIR=/cache
|
|
|
|
# =============================================================================
|
|
# Cleanup
|
|
# =============================================================================
|
|
clean:
|
|
@echo "==> Cleaning build artifacts..."
|
|
rm -rf $(ROOTFS_DIR) $(OUTPUT_DIR)
|
|
@echo "==> Clean. (Cache preserved in $(CACHE_DIR); use 'make distclean' to remove)"
|
|
|
|
distclean: clean
|
|
rm -rf $(CACHE_DIR)
|
|
|
|
# =============================================================================
|
|
# Help
|
|
# =============================================================================
|
|
help:
|
|
@echo "KubeSolo OS Build System (v$(VERSION))"
|
|
@echo ""
|
|
@echo "Build targets (x86_64):"
|
|
@echo " make fetch Download Tiny Core ISO, KubeSolo, dependencies"
|
|
@echo " make kernel Build custom kernel with CONFIG_CGROUP_BPF=y"
|
|
@echo " make build-cloudinit Build cloud-init Go binary"
|
|
@echo " make build-update-agent Build update agent Go binary"
|
|
@echo " make rootfs Extract + prepare rootfs with KubeSolo"
|
|
@echo " make initramfs Repack rootfs into kubesolo-os.gz"
|
|
@echo " make iso Create bootable ISO (default target)"
|
|
@echo " make disk-image Create raw disk image with A/B partitions + GRUB"
|
|
@echo " make oci-image Create OCI container image for registry distribution"
|
|
@echo " make build-cross Cross-compile Go binaries for amd64 + arm64"
|
|
@echo " make quick Fast rebuild (re-inject + repack + ISO only)"
|
|
@echo " make docker-build Reproducible build inside Docker"
|
|
@echo ""
|
|
@echo "Build targets (ARM64 generic — UEFI / cloud / SBCs):"
|
|
@echo " make kernel-arm64 Build mainline ARM64 kernel from kernel.org LTS"
|
|
@echo " make rootfs-arm64 Prepare generic ARM64 rootfs (mainline kernel modules)"
|
|
@echo " make disk-image-arm64 Create UEFI-bootable A/B GPT disk image (.arm64.img)"
|
|
@echo ""
|
|
@echo "Build targets (ARM64 Raspberry Pi):"
|
|
@echo " make kernel-rpi Build RPi kernel from raspberrypi/linux"
|
|
@echo " make rootfs-arm64-rpi Prepare RPi-flavoured rootfs (RPi kernel modules)"
|
|
@echo " make rpi-image Create Raspberry Pi SD card image with A/B autoboot"
|
|
@echo ""
|
|
@echo "Test targets:"
|
|
@echo " make test-boot Boot ISO in QEMU, verify boot success"
|
|
@echo " make test-k8s Boot + verify K8s node reaches Ready"
|
|
@echo " make test-persist Reboot disk image, verify state persists"
|
|
@echo " make test-deploy Deploy nginx pod, verify Running"
|
|
@echo " make test-storage Test PVC with local-path provisioner"
|
|
@echo " make test-security Verify security hardening (AppArmor, sysctl, mounts)"
|
|
@echo " make test-cloudinit Run cloud-init Go unit tests"
|
|
@echo " make test-update-agent Run update agent Go unit tests"
|
|
@echo " make test-update A/B update cycle integration test"
|
|
@echo " make test-rollback Forced rollback integration test"
|
|
@echo " make test-boot-arm64 ARM64 boot test (direct kernel, fast)"
|
|
@echo " make test-boot-arm64-disk ARM64 full UEFI disk-boot test"
|
|
@echo " make test-all Run core tests (boot + k8s + persistence)"
|
|
@echo " make test-integ Run full integration suite"
|
|
@echo " make bench-boot Benchmark boot performance (3 runs)"
|
|
@echo " make bench-resources Benchmark resource usage (requires running VM)"
|
|
@echo ""
|
|
@echo "Dev targets:"
|
|
@echo " make dev-vm Launch interactive QEMU VM (x86_64)"
|
|
@echo " make dev-vm-shell Launch QEMU VM -> emergency shell"
|
|
@echo " make dev-vm-debug Launch QEMU VM with debug logging"
|
|
@echo " make dev-vm-arm64 Launch ARM64 QEMU VM"
|
|
@echo " make kernel-audit Check kernel config against requirements"
|
|
@echo " make shellcheck Lint all shell scripts"
|
|
@echo ""
|
|
@echo "Cleanup:"
|
|
@echo " make clean Remove build artifacts (preserve cache)"
|
|
@echo " make distclean Remove everything including cache"
|