forked from tfgrid/zosbuilder
- Remove component copying from build functions (build_zinit, build_rfs, etc) - Add initramfs_copy_components() function to copy built components to initramfs - Add components_copy stage between init_script and modules_setup - Fix components_verify to check built components (not initramfs locations) - Now supports partial builds: build components separately, copy later - All 4 components (zinit 8.1M, rfs 13M, mycelium 21M, corex 4.0M) working
425 lines
14 KiB
Bash
Executable File
425 lines
14 KiB
Bash
Executable File
#!/bin/bash
|
|
# Main orchestrator script for Zero OS Alpine Initramfs Builder
|
|
|
|
set -euo pipefail
|
|
|
|
# Script directory and project root detection
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
|
|
|
|
# Source all libraries
|
|
source "${SCRIPT_DIR}/lib/common.sh"
|
|
source "${SCRIPT_DIR}/lib/stages.sh"
|
|
source "${SCRIPT_DIR}/lib/docker.sh"
|
|
source "${SCRIPT_DIR}/lib/alpine.sh"
|
|
source "${SCRIPT_DIR}/lib/components.sh"
|
|
source "${SCRIPT_DIR}/lib/initramfs.sh"
|
|
source "${SCRIPT_DIR}/lib/kernel.sh"
|
|
source "${SCRIPT_DIR}/lib/testing.sh"
|
|
|
|
# Build configuration loaded from config/build.conf via common.sh
|
|
# Environment variables can override config file values
|
|
ALPINE_VERSION="${ALPINE_VERSION:-3.22}"
|
|
KERNEL_VERSION="${KERNEL_VERSION:-6.12.44}"
|
|
RUST_TARGET="${RUST_TARGET:-x86_64-unknown-linux-musl}"
|
|
OPTIMIZATION_LEVEL="${OPTIMIZATION_LEVEL:-max}"
|
|
|
|
# Directory configuration
|
|
export INSTALL_DIR="${PROJECT_ROOT}/initramfs"
|
|
export COMPONENTS_DIR="${PROJECT_ROOT}/components"
|
|
export KERNEL_DIR="${PROJECT_ROOT}/kernel"
|
|
export DIST_DIR="${PROJECT_ROOT}/dist"
|
|
|
|
# Configuration files
|
|
CONFIG_DIR="${PROJECT_ROOT}/config"
|
|
PACKAGES_LIST="${CONFIG_DIR}/packages.list"
|
|
SOURCES_CONF="${CONFIG_DIR}/sources.conf"
|
|
MODULES_CONF="${CONFIG_DIR}/modules.conf"
|
|
KERNEL_CONFIG="${CONFIG_DIR}/kernel.config"
|
|
FIRMWARE_CONF="${CONFIG_DIR}/firmware.conf"
|
|
ZINIT_CONFIG_DIR="${CONFIG_DIR}/zinit"
|
|
|
|
# Build options
|
|
USE_CONTAINER="${USE_CONTAINER:-auto}"
|
|
CLEAN_BUILD="${CLEAN_BUILD:-false}"
|
|
SKIP_TESTS="${SKIP_TESTS:-false}"
|
|
KEEP_ARTIFACTS="${KEEP_ARTIFACTS:-false}"
|
|
|
|
# Display usage information
|
|
function show_usage() {
|
|
cat << EOF
|
|
Zero OS Alpine Initramfs Builder (Incremental)
|
|
|
|
Usage: $0 [OPTIONS]
|
|
|
|
Options:
|
|
--clean Clean build (remove all artifacts first)
|
|
--skip-tests Skip boot tests
|
|
--keep-artifacts Keep build artifacts after completion
|
|
--force-rebuild Force rebuild all stages (ignore completion markers)
|
|
--rebuild-from=STAGE Force rebuild from specific stage onward
|
|
--show-stages Show stage completion status
|
|
--help Show this help message
|
|
|
|
Environment Variables:
|
|
ALPINE_VERSION Alpine Linux version (default: 3.22)
|
|
KERNEL_VERSION Linux kernel version (default: 6.12.44)
|
|
RUST_TARGET Rust compilation target (default: x86_64-unknown-linux-musl)
|
|
OPTIMIZATION_LEVEL Optimization level: max|size|speed (default: max)
|
|
DEBUG Enable debug output (default: 0)
|
|
FORCE_REBUILD Force rebuild all stages (default: false)
|
|
|
|
Examples:
|
|
$0 # Incremental build (skip completed stages)
|
|
$0 --clean # Clean build (remove artifacts + stage markers)
|
|
$0 --force-rebuild # Force rebuild all stages
|
|
$0 --rebuild-from=zinit_setup # Rebuild from zinit setup onward
|
|
$0 --show-stages # Show which stages are completed
|
|
DEBUG=1 $0 # Build with debug output
|
|
|
|
Development Workflow:
|
|
./scripts/dev-container.sh start # Start persistent container
|
|
./scripts/dev-container.sh shell # Enter container for debugging
|
|
DEBUG=1 ./scripts/build.sh # Run incremental build inside container
|
|
EOF
|
|
}
|
|
|
|
# Parse command line arguments
|
|
function parse_arguments() {
|
|
while [[ $# -gt 0 ]]; do
|
|
case $1 in
|
|
--clean)
|
|
CLEAN_BUILD="true"
|
|
shift
|
|
;;
|
|
--skip-tests)
|
|
SKIP_TESTS="true"
|
|
shift
|
|
;;
|
|
--keep-artifacts)
|
|
KEEP_ARTIFACTS="true"
|
|
shift
|
|
;;
|
|
--force-rebuild)
|
|
export FORCE_REBUILD="true"
|
|
shift
|
|
;;
|
|
--rebuild-from=*)
|
|
export REBUILD_FROM_STAGE="${1#*=}"
|
|
export FORCE_REBUILD="true"
|
|
shift
|
|
;;
|
|
--show-stages)
|
|
# Initialize stage tracking and show status
|
|
source "${SCRIPT_DIR}/lib/stages.sh"
|
|
stages_init
|
|
stages_status
|
|
exit 0
|
|
;;
|
|
--help|-h)
|
|
show_usage
|
|
exit 0
|
|
;;
|
|
*)
|
|
log_error "Unknown option: $1"
|
|
show_usage
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
}
|
|
|
|
# Setup build environment
|
|
function setup_build_environment() {
|
|
section_header "Setting up build environment"
|
|
|
|
log_info "Project root: ${PROJECT_ROOT}"
|
|
log_info "Alpine version: ${ALPINE_VERSION}"
|
|
log_info "Kernel version: ${KERNEL_VERSION}"
|
|
log_info "Rust target: ${RUST_TARGET}"
|
|
log_info "Optimization level: ${OPTIMIZATION_LEVEL}"
|
|
|
|
# Create build directories only if we're in container
|
|
# Host will let container create them to avoid permission issues
|
|
if in_container; then
|
|
safe_mkdir "$INSTALL_DIR"
|
|
safe_mkdir "$COMPONENTS_DIR"
|
|
safe_mkdir "$KERNEL_DIR"
|
|
safe_mkdir "$DIST_DIR"
|
|
else
|
|
log_info "Skipping directory creation on host (container will create them)"
|
|
fi
|
|
|
|
# Check dependencies
|
|
if ! check_dependencies; then
|
|
log_error "Dependency check failed"
|
|
return 1
|
|
fi
|
|
|
|
# Verify configuration files exist
|
|
verify_configuration_files
|
|
|
|
log_info "Build environment setup complete"
|
|
}
|
|
|
|
# Verify all required configuration files exist
|
|
function verify_configuration_files() {
|
|
section_header "Verifying Configuration Files"
|
|
|
|
local required_configs=(
|
|
"$PACKAGES_LIST"
|
|
"$SOURCES_CONF"
|
|
"$MODULES_CONF"
|
|
"$KERNEL_CONFIG"
|
|
"$FIRMWARE_CONF"
|
|
)
|
|
|
|
local missing_configs=()
|
|
|
|
for config in "${required_configs[@]}"; do
|
|
if [[ ! -f "$config" ]]; then
|
|
missing_configs+=("$config")
|
|
else
|
|
log_info "✓ Configuration found: $(basename "$config")"
|
|
fi
|
|
done
|
|
|
|
if [[ ${#missing_configs[@]} -gt 0 ]]; then
|
|
log_error "Missing configuration files:"
|
|
for config in "${missing_configs[@]}"; do
|
|
log_error " - $config"
|
|
done
|
|
log_error "Run the setup script or create configuration files manually"
|
|
return 1
|
|
fi
|
|
|
|
# Check zinit configuration directory
|
|
if [[ ! -d "$ZINIT_CONFIG_DIR" ]]; then
|
|
log_error "zinit configuration directory not found: ${ZINIT_CONFIG_DIR}"
|
|
return 1
|
|
fi
|
|
|
|
log_info "All configuration files verified"
|
|
}
|
|
|
|
# Incremental build process with stage tracking
|
|
function main_build_process() {
|
|
section_header "Starting Zero OS Alpine Initramfs Build (Incremental)"
|
|
|
|
local start_time=$(date +%s)
|
|
|
|
# Initialize stage tracking
|
|
stages_init
|
|
|
|
# Define stage wrapper functions
|
|
function stage_alpine_extract() {
|
|
alpine_extract_miniroot "$INSTALL_DIR" "$ALPINE_VERSION"
|
|
}
|
|
|
|
function stage_alpine_configure() {
|
|
alpine_configure_repos "$INSTALL_DIR" "$ALPINE_VERSION"
|
|
alpine_configure_system "$INSTALL_DIR"
|
|
}
|
|
|
|
function stage_alpine_packages() {
|
|
alpine_install_packages "$INSTALL_DIR" "$PACKAGES_LIST"
|
|
}
|
|
|
|
function stage_alpine_firmware() {
|
|
alpine_install_firmware "$INSTALL_DIR" "$FIRMWARE_CONF"
|
|
}
|
|
|
|
function stage_components_build() {
|
|
components_parse_sources_conf "$SOURCES_CONF" "$COMPONENTS_DIR" "$INSTALL_DIR"
|
|
}
|
|
|
|
function stage_components_verify() {
|
|
components_verify_installation
|
|
}
|
|
|
|
function stage_kernel_modules() {
|
|
# Create placeholder for kernel build
|
|
local initramfs_archive="${DIST_DIR}/initramfs.cpio.xz"
|
|
safe_mkdir "$DIST_DIR"
|
|
safe_execute touch "$initramfs_archive"
|
|
|
|
# Download and build kernel modules
|
|
kernel_download_source "$KERNEL_DIR" "$KERNEL_VERSION"
|
|
kernel_apply_config "$KERNEL_DIR" "$initramfs_archive" "$KERNEL_CONFIG"
|
|
kernel_build_modules "$KERNEL_DIR" "$INSTALL_DIR" "$KERNEL_VERSION"
|
|
|
|
# Set full kernel version for later stages
|
|
FULL_KERNEL_VERSION=$(kernel_get_full_version "$KERNEL_VERSION" "$KERNEL_CONFIG")
|
|
export FULL_KERNEL_VERSION
|
|
log_info "Full kernel version: ${FULL_KERNEL_VERSION}"
|
|
}
|
|
|
|
function stage_zinit_setup() {
|
|
initramfs_setup_zinit "$INSTALL_DIR" "$ZINIT_CONFIG_DIR"
|
|
}
|
|
|
|
function stage_init_script() {
|
|
initramfs_install_init_script "$INSTALL_DIR" "${CONFIG_DIR}/init"
|
|
}
|
|
|
|
function stage_components_copy() {
|
|
initramfs_copy_components "$INSTALL_DIR" "$COMPONENTS_DIR"
|
|
}
|
|
|
|
function stage_modules_setup() {
|
|
# Calculate full kernel version (needed for incremental builds when kernel_modules stage is skipped)
|
|
local full_kernel_version=$(kernel_get_full_version "$KERNEL_VERSION" "$KERNEL_CONFIG")
|
|
export FULL_KERNEL_VERSION="$full_kernel_version"
|
|
log_info "Using full kernel version: ${full_kernel_version}"
|
|
|
|
initramfs_setup_modules "$INSTALL_DIR" "$MODULES_CONF" "$full_kernel_version"
|
|
}
|
|
|
|
function stage_modules_copy() {
|
|
# Ensure FULL_KERNEL_VERSION is set (for incremental builds)
|
|
if [[ -z "${FULL_KERNEL_VERSION:-}" ]]; then
|
|
FULL_KERNEL_VERSION=$(kernel_get_full_version "$KERNEL_VERSION" "$KERNEL_CONFIG")
|
|
export FULL_KERNEL_VERSION
|
|
fi
|
|
|
|
log_info "About to copy modules - FULL_KERNEL_VERSION: ${FULL_KERNEL_VERSION}"
|
|
log_info "CONTAINER_MODULES_PATH: ${CONTAINER_MODULES_PATH:-not-set}"
|
|
initramfs_copy_resolved_modules "$INSTALL_DIR" "$FULL_KERNEL_VERSION"
|
|
}
|
|
|
|
function stage_cleanup() {
|
|
alpine_aggressive_cleanup "$INSTALL_DIR"
|
|
}
|
|
|
|
function stage_validation() {
|
|
initramfs_validate "$INSTALL_DIR"
|
|
}
|
|
|
|
function stage_initramfs_create() {
|
|
local initramfs_archive="${DIST_DIR}/initramfs.cpio.xz"
|
|
initramfs_create_cpio "$INSTALL_DIR" "$initramfs_archive"
|
|
export INITRAMFS_ARCHIVE="$initramfs_archive"
|
|
}
|
|
|
|
function stage_initramfs_test() {
|
|
initramfs_test_archive "$INITRAMFS_ARCHIVE"
|
|
}
|
|
|
|
function stage_kernel_build() {
|
|
local kernel_output="${DIST_DIR}/vmlinuz.efi"
|
|
kernel_build_with_initramfs "$KERNEL_CONFIG" "$INITRAMFS_ARCHIVE" "$kernel_output"
|
|
export KERNEL_OUTPUT="$kernel_output"
|
|
}
|
|
|
|
function stage_boot_tests() {
|
|
if [[ "$SKIP_TESTS" != "true" ]]; then
|
|
# Ensure KERNEL_OUTPUT is set (for incremental builds)
|
|
if [[ -z "${KERNEL_OUTPUT:-}" ]]; then
|
|
KERNEL_OUTPUT="${DIST_DIR}/vmlinuz.efi"
|
|
export KERNEL_OUTPUT
|
|
fi
|
|
testing_run_all "$KERNEL_OUTPUT"
|
|
fi
|
|
}
|
|
|
|
# Run all stages with incremental tracking
|
|
stage_run "alpine_extract" stage_alpine_extract
|
|
stage_run "alpine_configure" stage_alpine_configure
|
|
stage_run "alpine_packages" stage_alpine_packages
|
|
stage_run "alpine_firmware" stage_alpine_firmware
|
|
stage_run "components_build" stage_components_build
|
|
stage_run "components_verify" stage_components_verify
|
|
stage_run "kernel_modules" stage_kernel_modules
|
|
stage_run "zinit_setup" stage_zinit_setup
|
|
stage_run "init_script" stage_init_script
|
|
stage_run "components_copy" stage_components_copy
|
|
stage_run "modules_setup" stage_modules_setup
|
|
stage_run "modules_copy" stage_modules_copy
|
|
stage_run "cleanup" stage_cleanup
|
|
stage_run "validation" stage_validation
|
|
stage_run "initramfs_create" stage_initramfs_create
|
|
stage_run "initramfs_test" stage_initramfs_test
|
|
stage_run "kernel_build" stage_kernel_build
|
|
stage_run "boot_tests" stage_boot_tests
|
|
|
|
# Calculate build time
|
|
local end_time=$(date +%s)
|
|
local build_time=$((end_time - start_time))
|
|
local build_minutes=$((build_time / 60))
|
|
local build_seconds=$((build_time % 60))
|
|
|
|
section_header "Build Complete"
|
|
log_info "Build time: ${build_minutes}m ${build_seconds}s"
|
|
log_info "Output files:"
|
|
if [[ -n "${KERNEL_OUTPUT:-}" ]]; then
|
|
log_info " Kernel: ${KERNEL_OUTPUT} ($(get_file_size "$KERNEL_OUTPUT"))"
|
|
else
|
|
log_info " Kernel: ${DIST_DIR}/vmlinuz.efi ($(get_file_size "${DIST_DIR}/vmlinuz.efi" 2>/dev/null || echo "not found"))"
|
|
fi
|
|
if [[ -n "${INITRAMFS_ARCHIVE:-}" ]]; then
|
|
log_info " Initramfs: ${INITRAMFS_ARCHIVE} ($(get_file_size "$INITRAMFS_ARCHIVE"))"
|
|
else
|
|
log_info " Initramfs: ${DIST_DIR}/initramfs.cpio.xz ($(get_file_size "${DIST_DIR}/initramfs.cpio.xz" 2>/dev/null || echo "not found"))"
|
|
fi
|
|
}
|
|
|
|
|
|
# Main function
|
|
function main() {
|
|
# Parse command line arguments
|
|
parse_arguments "$@"
|
|
|
|
# Show banner
|
|
echo ""
|
|
echo "=================================================="
|
|
echo "== ZERO-OS ALPINE INITRAMFS BUILDER =="
|
|
echo "== ThreeFold Edition =="
|
|
echo "=================================================="
|
|
echo ""
|
|
|
|
# Clean build if requested
|
|
if [[ "$CLEAN_BUILD" == "true" ]]; then
|
|
section_header "Clean Build Requested"
|
|
"$SCRIPT_DIR/clean.sh"
|
|
fi
|
|
|
|
# Setup environment
|
|
setup_build_environment
|
|
|
|
# Always use container builds for consistency
|
|
if in_container; then
|
|
log_info "Already in container, proceeding with build"
|
|
# Enable debug mode in container for better output visibility
|
|
if [[ "${DEBUG:-0}" != "1" ]]; then
|
|
log_info "Enabling debug mode for container build visibility"
|
|
export DEBUG=1
|
|
fi
|
|
main_build_process
|
|
elif command_exists "podman" || command_exists "docker"; then
|
|
log_info "Starting container build"
|
|
docker_detect_runtime
|
|
docker_build_container
|
|
|
|
# Pass through relevant arguments to container
|
|
local container_args=""
|
|
if [[ "$SKIP_TESTS" == "true" ]]; then
|
|
container_args="$container_args --skip-tests"
|
|
fi
|
|
if [[ "$KEEP_ARTIFACTS" == "true" ]]; then
|
|
container_args="$container_args --keep-artifacts"
|
|
fi
|
|
|
|
docker_run_build "./scripts/build.sh${container_args}"
|
|
else
|
|
log_error "Container runtime required (podman or docker)"
|
|
log_error "Install with: apt-get install podman"
|
|
return 1
|
|
fi
|
|
|
|
|
|
section_header "Zero OS Build Complete"
|
|
log_info "Ready to deploy Zero OS with Alpine Linux and zinit"
|
|
}
|
|
|
|
# Run main function with all arguments
|
|
main "$@" |