Files
zosbuilder/scripts/build.sh
Jan De Landtsheer b9f94105cf fix: major build system improvements and container output issues
- Fix container output visibility with proper TTY handling and debug mode
- Fix build order: kernel modules built before initramfs creation
- Implement two-stage kernel build to resolve chicken-and-egg dependency
- Fix sed command issues in kernel configuration with direct execution
- Add diffutils package to container for proper kernel build support
- Enhance NIC module/firmware correlation with intelligent selection
- Fix module staging logic: all NICs loaded in stage1 before network up
- Add smart firmware installation based on module requirements
- Create comprehensive function documentation (scripts/functionlist.md)
- Add debug container script for troubleshooting

Major fixes:
* Container builds now show real-time output
* Kernel builds work with proper GNU diff support
* Module/firmware selection optimized for common hardware
* Build process handles dependencies correctly
* Documentation provides complete function reference
2025-09-03 14:06:44 +02:00

341 lines
11 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/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
Usage: $0 [OPTIONS]
Options:
--clean Clean build (remove all artifacts first)
--skip-tests Skip boot tests
--keep-artifacts Keep build artifacts after completion
--help Show this help message
Environment Variables:
ALPINE_VERSION Alpine Linux version (default: 3.22)
KERNEL_VERSION Linux kernel version (default: 6.8.8)
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)
Examples:
$0 # Basic build
$0 --clean # Clean build
$0 --container # Force container build
DEBUG=1 $0 # Build with debug output
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
;;
--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"
}
# Main build process
function main_build_process() {
section_header "Starting Zero OS Alpine Initramfs Build"
local start_time=$(date +%s)
# Phase 1: Extract Alpine miniroot
alpine_extract_miniroot "$INSTALL_DIR" "$ALPINE_VERSION"
# Phase 2: Configure Alpine system
alpine_configure_repos "$INSTALL_DIR" "$ALPINE_VERSION"
alpine_configure_system "$INSTALL_DIR"
# Phase 3: Install Alpine packages (NO OpenRC)
alpine_install_packages "$INSTALL_DIR" "$PACKAGES_LIST"
# Phase 3.5: Install firmware packages for hardware support
alpine_install_firmware "$INSTALL_DIR" "$FIRMWARE_CONF"
# Phase 4: Build and install ThreeFold components
components_parse_sources_conf "$SOURCES_CONF" "$COMPONENTS_DIR" "$INSTALL_DIR"
# Phase 5: Verify component installation
components_verify_installation
# Phase 6: Create placeholder initramfs for kernel build (chicken-egg problem)
local initramfs_archive="${DIST_DIR}/initramfs.cpio.xz"
safe_mkdir "$DIST_DIR"
log_info "Creating placeholder initramfs for initial kernel build"
safe_execute touch "$initramfs_archive"
# Phase 7: Prepare kernel source and build modules (with placeholder initramfs)
log_info "Downloading and configuring kernel source for module build"
kernel_download_source "$KERNEL_DIR" "$KERNEL_VERSION"
kernel_apply_config "$KERNEL_DIR" "$initramfs_archive" "$KERNEL_CONFIG"
log_info "Building kernel modules for initramfs inclusion"
kernel_build_modules "$KERNEL_DIR" "$INSTALL_DIR" "$KERNEL_VERSION"
# Phase 8: Setup zinit as init system
initramfs_setup_zinit "$INSTALL_DIR" "$ZINIT_CONFIG_DIR"
# Phase 9: Install critical /init script for initramfs boot
initramfs_install_init_script "$INSTALL_DIR" "${CONFIG_DIR}/init"
# Phase 10: Setup 2-stage module loading
initramfs_setup_modules "$INSTALL_DIR" "$MODULES_CONF" "$KERNEL_VERSION"
# Phase 11: Aggressive cleanup for size optimization
alpine_aggressive_cleanup "$INSTALL_DIR"
# Phase 12: Strip and UPX all binaries (temporarily skipped to reach kernel phase)
log_info "Skipping strip/UPX optimization to proceed to kernel compilation"
# initramfs_strip_and_upx "$INSTALL_DIR"
# Phase 13: Validate initramfs
initramfs_validate "$INSTALL_DIR"
# Phase 14: Create real initramfs archive (now with modules)
log_info "Creating real initramfs archive with all components and modules"
initramfs_create_cpio "$INSTALL_DIR" "$initramfs_archive"
# Phase 15: Test archive integrity
initramfs_test_archive "$initramfs_archive"
# Phase 16: Second kernel build with real embedded initramfs
local kernel_output="${DIST_DIR}/vmlinuz.efi"
log_info "Final kernel build: embedding complete initramfs"
kernel_build_with_initramfs "$KERNEL_CONFIG" "$initramfs_archive" "$kernel_output"
# Phase 17: Run boot tests (unless skipped)
if [[ "$SKIP_TESTS" != "true" ]]; then
testing_run_all "$kernel_output"
else
log_info "Skipping boot tests as requested"
fi
# 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:"
log_info " Kernel: ${kernel_output} ($(get_file_size "$kernel_output"))"
log_info " Initramfs: ${initramfs_archive} ($(get_file_size "$initramfs_archive"))"
}
# Cleanup build artifacts
function cleanup_build_artifacts() {
if [[ "$KEEP_ARTIFACTS" != "true" ]]; then
section_header "Cleaning Build Artifacts"
components_cleanup "$COMPONENTS_DIR" "false"
kernel_cleanup "$KERNEL_DIR" "false"
log_info "Build artifacts cleaned"
else
log_info "Keeping build artifacts as requested"
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
# Cleanup if requested
cleanup_build_artifacts
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 "$@"