archlinux-s390x/scripts/common.sh

286 lines
6.6 KiB
Bash
Raw Permalink Normal View History

2025-06-05 07:03:58 -04:00
#!/bin/bash
# Common utilities for Arch Linux s390x build system
# SPDX-License-Identifier: GPL-2.0-only
# Color definitions
export RED='\033[0;31m'
export GREEN='\033[0;32m'
export YELLOW='\033[1;33m'
export BLUE='\033[0;34m'
export MAGENTA='\033[0;35m'
export CYAN='\033[0;36m'
export NC='\033[0m'
# Get project root directory
get_project_root() {
local script_dir="$(cd "$(dirname "${BASH_SOURCE[1]}")" && pwd)"
echo "$(dirname "$script_dir")"
}
# Get project paths
get_project_paths() {
export PROJECT_ROOT="$(get_project_root)"
export OUTPUT_DIR="$PROJECT_ROOT/output"
export BOOT_DIR="$PROJECT_ROOT/boot"
export BUILD_DIR="$PROJECT_ROOT/build-kernel"
export SCRIPTS_DIR="$PROJECT_ROOT/scripts"
export PATCHES_DIR="$PROJECT_ROOT/patches"
export CONFIG_DIR="$PROJECT_ROOT/config"
}
# Logging functions
log_info() {
echo -e "${BLUE}[INFO]${NC} $1"
}
log_success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
}
log_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $1" >&2
}
log_debug() {
if [ "${DEBUG:-0}" = "1" ]; then
echo -e "${MAGENTA}[DEBUG]${NC} $1" >&2
fi
}
# Error handling
die() {
log_error "$1"
exit "${2:-1}"
}
# Check if command exists
command_exists() {
command -v "$1" >/dev/null 2>&1
}
# Check if running in container
is_container() {
[ -f /.dockerenv ] || [ -f /run/.containerenv ] || [ "${container:-}" = "podman" ]
}
# Validate required commands
check_required_commands() {
local missing=()
for cmd in "$@"; do
if ! command_exists "$cmd"; then
missing+=("$cmd")
fi
done
if [ ${#missing[@]} -gt 0 ]; then
log_error "Missing required commands: ${missing[*]}"
return 1
fi
}
# Validate required files
check_required_files() {
local missing=()
for file in "$@"; do
if [ ! -f "$file" ]; then
missing+=("$file")
fi
done
if [ ${#missing[@]} -gt 0 ]; then
log_error "Missing required files: ${missing[*]}"
return 1
fi
}
# Validate required directories
check_required_dirs() {
local missing=()
for dir in "$@"; do
if [ ! -d "$dir" ]; then
missing+=("$dir")
fi
done
if [ ${#missing[@]} -gt 0 ]; then
log_error "Missing required directories: ${missing[*]}"
return 1
fi
}
# Create directory if it doesn't exist
ensure_dir() {
local dir="$1"
if [ ! -d "$dir" ]; then
log_debug "Creating directory: $dir"
mkdir -p "$dir" || die "Failed to create directory: $dir"
fi
}
# Load environment from .env file if it exists
load_env() {
local env_file="${1:-.env}"
if [ -f "$env_file" ]; then
log_debug "Loading environment from $env_file"
set -a
source "$env_file"
set +a
log_debug "Environment loaded successfully"
else
log_debug "No .env file found at $env_file"
fi
}
# Print script header
print_header() {
local title="$1"
local width=60
echo
echo -e "${CYAN}$(printf '=%.0s' $(seq 1 $width))${NC}"
echo -e "${CYAN}$(printf '%-*s' $width "$title")${NC}"
echo -e "${CYAN}$(printf '=%.0s' $(seq 1 $width))${NC}"
echo
}
# Print section separator
print_section() {
local title="$1"
echo
echo -e "${YELLOW}=== $title ===${NC}"
}
# Cleanup function for temporary files
cleanup_on_exit() {
local temp_files=("$@")
for file in "${temp_files[@]}"; do
if [ -f "$file" ]; then
log_debug "Cleaning up temporary file: $file"
rm -f "$file"
fi
done
}
# Set up cleanup trap
setup_cleanup() {
local temp_files=("$@")
trap 'cleanup_on_exit "${temp_files[@]}"' EXIT INT TERM
}
# Progress indicator
show_progress() {
local current="$1"
local total="$2"
local message="$3"
local width=40
local progress=$((current * width / total))
local remaining=$((width - progress))
printf "\r${CYAN}[%s%s] %d/%d %s${NC}" \
"$(printf '#%.0s' $(seq 1 $progress))" \
"$(printf '.%.0s' $(seq 1 $remaining))" \
"$current" "$total" "$message"
if [ "$current" -eq "$total" ]; then
echo
fi
}
# Timer functions
start_timer() {
export TIMER_START=$(date +%s)
}
end_timer() {
local start_time="${TIMER_START:-$(date +%s)}"
local end_time=$(date +%s)
local duration=$((end_time - start_time))
local minutes=$((duration / 60))
local seconds=$((duration % 60))
if [ $minutes -gt 0 ]; then
echo -e "${CYAN}Completed in ${minutes}m ${seconds}s${NC}"
else
echo -e "${CYAN}Completed in ${seconds}s${NC}"
fi
}
# File size formatting
format_size() {
local size="$1"
if [ "$size" -ge 1073741824 ]; then
echo "$((size / 1073741824))GB"
elif [ "$size" -ge 1048576 ]; then
echo "$((size / 1048576))MB"
elif [ "$size" -ge 1024 ]; then
echo "$((size / 1024))KB"
else
echo "${size}B"
fi
}
# Get file size in human readable format
get_file_size() {
local file="$1"
if [ -f "$file" ]; then
local size=$(stat -c%s "$file" 2>/dev/null || stat -f%z "$file" 2>/dev/null)
format_size "$size"
else
echo "N/A"
fi
}
# Common QEMU configuration
run_qemu_s390x() {
local append_args="$1"
local extra_args="${2:-}"
check_required_commands qemu-system-s390x
check_required_files "boot/vmlinuz-linux" "boot/initramfs-linux.img"
log_info "Starting QEMU s390x system..."
log_debug "Append args: $append_args"
log_debug "Extra args: $extra_args"
qemu-system-s390x \
-machine s390-ccw-virtio \
-cpu max \
-m 2G \
-kernel "boot/vmlinuz-linux" \
-initrd "boot/initramfs-linux.img" \
-append "console=ttyS0 $append_args" \
-nographic \
-device virtio-net-ccw,netdev=net0 \
-netdev user,id=net0 \
$extra_args
}
# Initialize common environment
init_common() {
# Set strict error handling
set -euo pipefail
# Initialize paths
get_project_paths
# Load environment if available
load_env
# Ensure output directory exists
ensure_dir "$OUTPUT_DIR"
}
# Export functions for use in other scripts
export -f get_project_root get_project_paths
export -f log_info log_success log_warning log_error log_debug die
export -f command_exists is_container
export -f check_required_commands check_required_files check_required_dirs
export -f ensure_dir load_env
export -f print_header print_section
export -f cleanup_on_exit setup_cleanup
export -f show_progress start_timer end_timer
export -f format_size get_file_size
export -f run_qemu_s390x init_common