472 lines
13 KiB
Bash
Executable file
472 lines
13 KiB
Bash
Executable file
#!/bin/bash
|
|
# UniversalisOS Hypervisor — Canonical Test/Lint/Build Suite
|
|
#
|
|
# This script provides the canonical commands for building, testing, and
|
|
# linting the UniversalisOS hypervisor across all supported architectures.
|
|
#
|
|
# Usage:
|
|
# ./uos-check.sh [command]
|
|
#
|
|
# Commands:
|
|
# build-all Build all architectures (armv7, aarch64, riscv)
|
|
# build-armv7 Build ARMv7 (qemu-arm-virt)
|
|
# build-aarch64 Build AArch64 (qemu-aarch64-virt)
|
|
# build-riscv Build RISC-V (polarfire)
|
|
# test Run all tests (build + boot smoke tests)
|
|
# lint Run lint checks (format, static analysis)
|
|
# clean Clean all build trees
|
|
# help Show this help
|
|
#
|
|
# Exit codes:
|
|
# 0 = success
|
|
# 1 = build failure
|
|
# 2 = test failure
|
|
# 3 = lint failure
|
|
|
|
set -e
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
KERNEL_DIR="$SCRIPT_DIR"
|
|
BUILD_DIR="$KERNEL_DIR/build"
|
|
|
|
# Colors for output
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
NC='\033[0m' # No Color
|
|
|
|
# Logging functions
|
|
log_info() {
|
|
echo -e "${BLUE}[INFO]${NC} $1"
|
|
}
|
|
|
|
log_success() {
|
|
echo -e "${GREEN}[PASS]${NC} $1"
|
|
}
|
|
|
|
log_warning() {
|
|
echo -e "${YELLOW}[WARN]${NC} $1"
|
|
}
|
|
|
|
log_error() {
|
|
echo -e "${RED}[FAIL]${NC} $1"
|
|
}
|
|
|
|
# Check if a command exists
|
|
command_exists() {
|
|
command -v "$1" >/dev/null 2>&1
|
|
}
|
|
|
|
# Check required tools
|
|
check_tools() {
|
|
local missing=()
|
|
|
|
# ARMv7 toolchain
|
|
if ! command_exists arm-none-eabi-gcc; then
|
|
missing+=("arm-none-eabi-gcc")
|
|
fi
|
|
|
|
# AArch64 toolchain
|
|
if ! command_exists aarch64-linux-gnu-gcc; then
|
|
missing+=("aarch64-linux-gnu-gcc")
|
|
fi
|
|
|
|
# RISC-V toolchain
|
|
if ! command_exists riscv64-unknown-elf-gcc; then
|
|
missing+=("riscv64-unknown-elf-gcc")
|
|
fi
|
|
|
|
# QEMU
|
|
if ! command_exists qemu-system-arm; then
|
|
missing+=("qemu-system-arm")
|
|
fi
|
|
if ! command_exists qemu-system-aarch64; then
|
|
missing+=("qemu-system-aarch64")
|
|
fi
|
|
if ! command_exists qemu-system-riscv64; then
|
|
missing+=("qemu-system-riscv64")
|
|
fi
|
|
|
|
if [ ${#missing[@]} -gt 0 ]; then
|
|
log_warning "Missing tools: ${missing[*]}"
|
|
log_warning "Some builds may fail. Install with:"
|
|
log_warning " sudo dnf install gcc-arm-none-eabi gcc-aarch64-linux-gnu gcc-riscv64-unknown-elf qemu-system-arm qemu-system-aarch64 qemu-system-riscv"
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
# Build a specific architecture
|
|
build_arch() {
|
|
local arch=$1
|
|
local platform=$2
|
|
local name=$3
|
|
|
|
log_info "Building $name ($arch/$platform)..."
|
|
|
|
cd "$KERNEL_DIR"
|
|
|
|
# Clean previous build
|
|
make ARCH="$arch" PLATFORM="$platform" clean >/dev/null 2>&1 || true
|
|
|
|
# Build
|
|
if make ARCH="$arch" PLATFORM="$platform" 2>&1 | tee "/tmp/uos-build-$arch.log"; then
|
|
# Check if ELF was produced
|
|
local elf="$BUILD_DIR/$arch/$platform/universalisos.elf"
|
|
if [ -f "$elf" ]; then
|
|
local size=$(stat -c%s "$elf" 2>/dev/null || stat -f%z "$elf" 2>/dev/null)
|
|
log_success "$name built successfully ($size bytes)"
|
|
return 0
|
|
else
|
|
log_error "$name build succeeded but ELF not found at $elf"
|
|
return 1
|
|
fi
|
|
else
|
|
log_error "$name build failed (see /tmp/uos-build-$arch.log)"
|
|
log_warning "Note: Some builds may fail due to pre-existing issues"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# Build core components only (for testing individual files)
|
|
build_core() {
|
|
log_info "Building core components..."
|
|
|
|
cd "$KERNEL_DIR"
|
|
|
|
# Test compile key files
|
|
local files=(
|
|
"src/core/abi/uos_posix_abi.cpp"
|
|
"src/core/mm.cpp"
|
|
"src/core/scheduler.cpp"
|
|
)
|
|
|
|
local failed=0
|
|
for file in "${files[@]}"; do
|
|
if [ -f "$file" ]; then
|
|
log_info "Compiling $file..."
|
|
if arm-none-eabi-g++ -Iinclude -Iinclude/universalisos -Iinclude/universalisos/j_space \
|
|
-Isrc/arch/armv7/inc -Isrc/platform/qemu-arm-virt/inc -Isrc/core -Isrc/platform \
|
|
-mcpu=cortex-a15 -DARCH_ARMV7 -DARCH_ARM -DPLATFORM_QEMU_ARM_VIRT \
|
|
-Wall -Wextra -ffreestanding -O2 -fno-tree-vectorize -g -fno-exceptions -fno-rtti \
|
|
-c "$file" -o "/tmp/$(basename "$file" .cpp).o" 2>/dev/null; then
|
|
log_success "$file compiles"
|
|
else
|
|
log_error "$file failed to compile"
|
|
failed=$((failed + 1))
|
|
fi
|
|
fi
|
|
done
|
|
|
|
if [ $failed -eq 0 ]; then
|
|
log_success "All core components compile"
|
|
return 0
|
|
else
|
|
log_error "$failed core component(s) failed to compile"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# Build all architectures
|
|
build_all() {
|
|
log_info "=== Building all architectures ==="
|
|
local failed=0
|
|
|
|
# ARMv7
|
|
if ! build_arch "armv7" "qemu-arm-virt" "ARMv7"; then
|
|
failed=$((failed + 1))
|
|
fi
|
|
|
|
# AArch64
|
|
if ! build_arch "aarch64" "qemu-aarch64-virt" "AArch64"; then
|
|
failed=$((failed + 1))
|
|
fi
|
|
|
|
# RISC-V
|
|
if ! build_arch "riscv" "polarfire" "RISC-V"; then
|
|
failed=$((failed + 1))
|
|
fi
|
|
|
|
if [ $failed -eq 0 ]; then
|
|
log_success "All architectures built successfully"
|
|
return 0
|
|
else
|
|
log_error "$failed architecture(s) failed to build"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# Boot smoke test for ARMv7
|
|
test_boot_armv7() {
|
|
log_info "Running ARMv7 boot smoke test..."
|
|
|
|
local elf="$BUILD_DIR/armv7/qemu-arm-virt/universalisos.elf"
|
|
if [ ! -f "$elf" ]; then
|
|
log_error "ARMv7 ELF not found. Run 'build-armv7' first."
|
|
return 1
|
|
fi
|
|
|
|
# Run QEMU with timeout, capture output
|
|
local output
|
|
output=$(timeout 10 qemu-system-arm -M virt -cpu cortex-a15 -m 512M \
|
|
-nographic -kernel "$elf" 2>&1 || true)
|
|
|
|
# Check for expected boot messages
|
|
if echo "$output" | grep -q "UniversalisOS"; then
|
|
log_success "ARMv7 boot smoke test passed"
|
|
return 0
|
|
else
|
|
log_error "ARMv7 boot smoke test failed (no boot banner)"
|
|
echo "$output" | head -20
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# Boot smoke test for AArch64
|
|
test_boot_aarch64() {
|
|
log_info "Running AArch64 boot smoke test..."
|
|
|
|
local elf="$BUILD_DIR/aarch64/qemu-aarch64-virt/universalisos.elf"
|
|
if [ ! -f "$elf" ]; then
|
|
log_error "AArch64 ELF not found. Run 'build-aarch64' first."
|
|
return 1
|
|
fi
|
|
|
|
# Run QEMU with timeout, capture output
|
|
local output
|
|
output=$(timeout 10 qemu-system-aarch64 -M virt,gic-version=3,virtualization=on \
|
|
-cpu cortex-a53 -m 512M -smp 4 -nographic -kernel "$elf" 2>&1 || true)
|
|
|
|
# Check for expected boot messages
|
|
if echo "$output" | grep -q "UniversalisOS"; then
|
|
log_success "AArch64 boot smoke test passed"
|
|
return 0
|
|
else
|
|
log_error "AArch64 boot smoke test failed (no boot banner)"
|
|
echo "$output" | head -20
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# Boot smoke test for RISC-V
|
|
test_boot_riscv() {
|
|
log_info "Running RISC-V boot smoke test..."
|
|
|
|
local elf="$BUILD_DIR/riscv/polarfire/universalisos.elf"
|
|
if [ ! -f "$elf" ]; then
|
|
log_error "RISC-V ELF not found. Run 'build-riscv' first."
|
|
return 1
|
|
fi
|
|
|
|
# Run QEMU with timeout, capture output
|
|
local output
|
|
output=$(timeout 10 qemu-system-riscv64 -machine microchip-icicle-kit \
|
|
-smp 5 -m 2G -nographic -bios none -kernel "$elf" 2>&1 || true)
|
|
|
|
# Check for expected boot messages
|
|
if echo "$output" | grep -q "UniversalisOS\|Partition"; then
|
|
log_success "RISC-V boot smoke test passed"
|
|
return 0
|
|
else
|
|
log_error "RISC-V boot smoke test failed (no boot banner)"
|
|
echo "$output" | head -20
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# Run all tests
|
|
run_tests() {
|
|
log_info "=== Running all tests ==="
|
|
local failed=0
|
|
|
|
# Build first
|
|
if ! build_all; then
|
|
log_error "Build failed, skipping tests"
|
|
return 1
|
|
fi
|
|
|
|
# Boot smoke tests
|
|
if ! test_boot_armv7; then
|
|
failed=$((failed + 1))
|
|
fi
|
|
|
|
if ! test_boot_aarch64; then
|
|
failed=$((failed + 1))
|
|
fi
|
|
|
|
if ! test_boot_riscv; then
|
|
failed=$((failed + 1))
|
|
fi
|
|
|
|
if [ $failed -eq 0 ]; then
|
|
log_success "All tests passed"
|
|
return 0
|
|
else
|
|
log_error "$failed test(s) failed"
|
|
return 2
|
|
fi
|
|
}
|
|
|
|
# Lint checks
|
|
run_lint() {
|
|
log_info "=== Running lint checks ==="
|
|
local failed=0
|
|
|
|
# Check for TODO/FIXME/HACK comments
|
|
log_info "Checking for TODO/FIXME/HACK comments..."
|
|
local todo_count
|
|
todo_count=$(grep -r "TODO\|FIXME\|HACK" "$KERNEL_DIR/src" --include="*.c" --include="*.cpp" --include="*.h" 2>/dev/null | wc -l)
|
|
if [ "$todo_count" -gt 0 ]; then
|
|
log_warning "Found $todo_count TODO/FIXME/HACK comments"
|
|
else
|
|
log_success "No TODO/FIXME/HACK comments found"
|
|
fi
|
|
|
|
# Check for trailing whitespace
|
|
log_info "Checking for trailing whitespace..."
|
|
local ws_count
|
|
ws_count=$(grep -r " $" "$KERNEL_DIR/src" --include="*.c" --include="*.cpp" --include="*.h" 2>/dev/null | wc -l)
|
|
if [ "$ws_count" -gt 0 ]; then
|
|
log_warning "Found $ws_count lines with trailing whitespace"
|
|
else
|
|
log_success "No trailing whitespace found"
|
|
fi
|
|
|
|
# Check for tabs (should use spaces)
|
|
log_info "Checking for tab characters..."
|
|
local tab_count
|
|
tab_count=$(grep -r $'\t' "$KERNEL_DIR/src" --include="*.c" --include="*.cpp" --include="*.h" 2>/dev/null | wc -l)
|
|
if [ "$tab_count" -gt 0 ]; then
|
|
log_warning "Found $tab_count lines with tab characters"
|
|
else
|
|
log_success "No tab characters found"
|
|
fi
|
|
|
|
# Check for long lines (>120 chars)
|
|
log_info "Checking for long lines (>120 chars)..."
|
|
local long_count
|
|
long_count=$(find "$KERNEL_DIR/src" -name "*.c" -o -name "*.cpp" -o -name "*.h" 2>/dev/null | xargs awk 'length > 120 {count++} END {print count+0}' 2>/dev/null || echo "0")
|
|
if [ "$long_count" -gt 0 ]; then
|
|
log_warning "Found $long_count lines longer than 120 characters"
|
|
else
|
|
log_success "No long lines found"
|
|
fi
|
|
|
|
# Check for UOS-STUB markers
|
|
log_info "Checking for UOS-STUB markers..."
|
|
local stub_count
|
|
stub_count=$(grep -r "UOS-STUB" "$KERNEL_DIR/src" --include="*.c" --include="*.cpp" --include="*.h" 2>/dev/null | wc -l)
|
|
if [ "$stub_count" -gt 0 ]; then
|
|
log_warning "Found $stub_count UOS-STUB markers (see docs/STUB_REGISTRY.md)"
|
|
else
|
|
log_success "No UOS-STUB markers found"
|
|
fi
|
|
|
|
# Check for unmarked stubs
|
|
log_info "Checking for unmarked stubs..."
|
|
local unmarked_count
|
|
unmarked_count=$(grep -r "not implemented\|stub" "$KERNEL_DIR/src" --include="*.c" --include="*.cpp" --include="*.h" 2>/dev/null | grep -v "UOS-STUB" | wc -l)
|
|
if [ "$unmarked_count" -gt 0 ]; then
|
|
log_warning "Found $unmarked_count unmarked stubs (should use UOS-STUB marker)"
|
|
else
|
|
log_success "No unmarked stubs found"
|
|
fi
|
|
|
|
if [ $failed -eq 0 ]; then
|
|
log_success "Lint checks completed"
|
|
return 0
|
|
else
|
|
log_error "$failed lint check(s) failed"
|
|
return 3
|
|
fi
|
|
}
|
|
|
|
# Clean all build trees
|
|
clean_all() {
|
|
log_info "Cleaning all build trees..."
|
|
cd "$KERNEL_DIR"
|
|
make clean-all
|
|
log_success "All build trees cleaned"
|
|
}
|
|
|
|
# Show help
|
|
show_help() {
|
|
cat << EOF
|
|
UniversalisOS Hypervisor — Canonical Test/Lint/Build Suite
|
|
|
|
Usage: $0 [command]
|
|
|
|
Commands:
|
|
build-core Build core components only (for testing individual files)
|
|
build-all Build all architectures (armv7, aarch64, riscv)
|
|
build-armv7 Build ARMv7 (qemu-arm-virt)
|
|
build-aarch64 Build AArch64 (qemu-aarch64-virt)
|
|
build-riscv Build RISC-V (polarfire)
|
|
test Run all tests (build + boot smoke tests)
|
|
lint Run lint checks (format, static analysis)
|
|
clean Clean all build trees
|
|
help Show this help
|
|
|
|
Examples:
|
|
$0 build-all # Build all architectures
|
|
$0 test # Build and run boot smoke tests
|
|
$0 lint # Run lint checks
|
|
$0 clean # Clean all build trees
|
|
|
|
Exit codes:
|
|
0 = success
|
|
1 = build failure
|
|
2 = test failure
|
|
3 = lint failure
|
|
|
|
EOF
|
|
}
|
|
|
|
# Main
|
|
main() {
|
|
local command="${1:-help}"
|
|
|
|
case "$command" in
|
|
build-core)
|
|
check_tools
|
|
build_core
|
|
;;
|
|
build-all)
|
|
check_tools
|
|
build_all
|
|
;;
|
|
build-armv7)
|
|
check_tools
|
|
build_arch "armv7" "qemu-arm-virt" "ARMv7"
|
|
;;
|
|
build-aarch64)
|
|
check_tools
|
|
build_arch "aarch64" "qemu-aarch64-virt" "AArch64"
|
|
;;
|
|
build-riscv)
|
|
check_tools
|
|
build_arch "riscv" "polarfire" "RISC-V"
|
|
;;
|
|
test)
|
|
check_tools
|
|
run_tests
|
|
;;
|
|
lint)
|
|
run_lint
|
|
;;
|
|
clean)
|
|
clean_all
|
|
;;
|
|
help|--help|-h)
|
|
show_help
|
|
;;
|
|
*)
|
|
log_error "Unknown command: $command"
|
|
show_help
|
|
exit 1
|
|
;;
|
|
esac
|
|
}
|
|
|
|
main "$@"
|