- Remove duplicate /sbin/init copying from initramfs_setup_zinit() - Only /init should be config/init (initramfs setup script) - No /sbin/init needed - config/init calls 'switch_root /mnt/root /sbin/zinit init' - Remove unsupported cpio --owner option that broke CPIO creation - Fix validation to not expect /sbin/init file - Correct boot flow: /init → switch_root → /sbin/zinit init - Remove strip and UPX compression from zinit binary copying - UPX compression was corrupting the zinit binary causing segfaults after switch_root - Keep zinit unmodified as it's
171 lines
5.2 KiB
Bash
171 lines
5.2 KiB
Bash
#!/bin/bash
|
|
# Build stage tracking and incremental build support
|
|
|
|
# Source common functions
|
|
LIB_SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
source "${LIB_SCRIPT_DIR}/common.sh"
|
|
|
|
# Stage tracking configuration
|
|
STAGES_DIR="${PROJECT_ROOT:-/workspace}/.build-stages"
|
|
|
|
# Initialize stage tracking
|
|
function stages_init() {
|
|
section_header "Initializing Stage Tracking"
|
|
|
|
safe_mkdir "$STAGES_DIR"
|
|
log_info "Stage tracking directory: ${STAGES_DIR}"
|
|
|
|
# Show existing completed stages
|
|
local completed_stages=()
|
|
if ls "$STAGES_DIR"/*.done >/dev/null 2>&1; then
|
|
while IFS= read -r stage_file; do
|
|
local stage_name=$(basename "$stage_file" .done)
|
|
completed_stages+=("$stage_name")
|
|
done < <(ls "$STAGES_DIR"/*.done 2>/dev/null)
|
|
|
|
log_info "Previously completed stages: ${completed_stages[*]}"
|
|
else
|
|
log_info "No previously completed stages found"
|
|
fi
|
|
}
|
|
|
|
# Check if stage is already completed
|
|
function stage_is_completed() {
|
|
local stage_name="$1"
|
|
local stage_file="${STAGES_DIR}/${stage_name}.done"
|
|
|
|
if [[ -f "$stage_file" ]]; then
|
|
local completion_time=$(stat -c %Y "$stage_file" 2>/dev/null || echo "unknown")
|
|
log_debug "Stage '$stage_name' already completed at $(date -d @$completion_time 2>/dev/null || echo "unknown time")"
|
|
return 0
|
|
else
|
|
log_debug "Stage '$stage_name' not completed yet"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# Mark stage as completed
|
|
function stage_mark_completed() {
|
|
local stage_name="$1"
|
|
local stage_details="${2:-}"
|
|
local stage_file="${STAGES_DIR}/${stage_name}.done"
|
|
|
|
# Create completion marker with metadata
|
|
cat > "$stage_file" << EOF
|
|
# Stage completion marker
|
|
STAGE_NAME="$stage_name"
|
|
COMPLETED_AT="$(date -Iseconds)"
|
|
COMPLETED_BY="$(whoami)"
|
|
DETAILS="$stage_details"
|
|
EOF
|
|
|
|
log_info "Stage completed: $stage_name"
|
|
if [[ -n "$stage_details" ]]; then
|
|
log_debug " Details: $stage_details"
|
|
fi
|
|
}
|
|
|
|
# Remove stage completion marker (force rebuild)
|
|
function stage_force_rebuild() {
|
|
local stage_name="$1"
|
|
local stage_file="${STAGES_DIR}/${stage_name}.done"
|
|
|
|
if [[ -f "$stage_file" ]]; then
|
|
safe_execute rm "$stage_file"
|
|
log_info "Stage marked for rebuild: $stage_name"
|
|
else
|
|
log_debug "Stage not completed, no need to force rebuild: $stage_name"
|
|
fi
|
|
}
|
|
|
|
# Clear all stage markers (full rebuild)
|
|
function stages_clear_all() {
|
|
section_header "Clearing All Stage Markers"
|
|
|
|
if [[ -d "$STAGES_DIR" ]]; then
|
|
local marker_count=$(ls "$STAGES_DIR"/*.done 2>/dev/null | wc -l || echo "0")
|
|
if [[ $marker_count -gt 0 ]]; then
|
|
safe_execute rm -f "$STAGES_DIR"/*.done
|
|
log_info "Cleared ${marker_count} stage completion markers"
|
|
else
|
|
log_info "No stage markers to clear"
|
|
fi
|
|
fi
|
|
|
|
log_info "Next build will rebuild all stages"
|
|
}
|
|
|
|
# Run stage with completion tracking
|
|
function stage_run() {
|
|
local stage_name="$1"
|
|
local stage_function="$2"
|
|
shift 2
|
|
local stage_args=("$@")
|
|
|
|
log_info "=== STAGE: $stage_name ==="
|
|
|
|
# Check if stage is already completed (unless forced)
|
|
if [[ "${FORCE_REBUILD:-false}" != "true" ]] && stage_is_completed "$stage_name"; then
|
|
log_info "Skipping completed stage: $stage_name"
|
|
log_info " (Use FORCE_REBUILD=true or remove ${STAGES_DIR}/${stage_name}.done to rebuild)"
|
|
return 0
|
|
fi
|
|
|
|
log_info "Running stage: $stage_name"
|
|
local start_time=$(date +%s)
|
|
|
|
# Run the stage function with its arguments
|
|
if "$stage_function" "${stage_args[@]}"; then
|
|
local end_time=$(date +%s)
|
|
local duration=$((end_time - start_time))
|
|
|
|
# Mark as completed with timing info
|
|
stage_mark_completed "$stage_name" "Duration: ${duration}s, Function: $stage_function"
|
|
log_info "Stage '$stage_name' completed successfully (${duration}s)"
|
|
return 0
|
|
else
|
|
local exit_code=$?
|
|
log_error "Stage '$stage_name' failed with exit code: $exit_code"
|
|
return $exit_code
|
|
fi
|
|
}
|
|
|
|
# Show stage status
|
|
function stages_status() {
|
|
section_header "Build Stages Status"
|
|
|
|
local all_stages=(
|
|
"alpine_extract"
|
|
"alpine_configure"
|
|
"alpine_packages"
|
|
"alpine_firmware"
|
|
"components_build"
|
|
"components_verify"
|
|
"kernel_modules"
|
|
"zinit_setup"
|
|
"init_script"
|
|
"modules_setup"
|
|
"modules_copy"
|
|
"cleanup"
|
|
"validation"
|
|
"initramfs_create"
|
|
"initramfs_test"
|
|
"kernel_build"
|
|
)
|
|
|
|
log_info "Stage completion status:"
|
|
|
|
for stage in "${all_stages[@]}"; do
|
|
if stage_is_completed "$stage"; then
|
|
local completion_time=$(stat -c %Y "${STAGES_DIR}/${stage}.done" 2>/dev/null || echo "0")
|
|
local time_str=$(date -d @$completion_time '+%H:%M:%S' 2>/dev/null || echo "unknown")
|
|
log_info " [DONE] $stage (completed at $time_str)"
|
|
else
|
|
log_info " [TODO] $stage (pending)"
|
|
fi
|
|
done
|
|
}
|
|
|
|
# Export functions
|
|
export -f stages_init stage_is_completed stage_mark_completed stage_force_rebuild
|
|
export -f stages_clear_all stage_run stages_status |