#!/bin/bash # CCDJIT Build System # A comprehensive build and development tool for the CCDJIT compiler set -e # Exit on any error # Configuration PROJECT_NAME="ccdjit" BINARY_NAME="bin/ccdjit" SOURCE_DIR="src" TEST_DIR="tests" BUILD_DIR="bin" RELEASE_FLAGS="-DRELEASE -O2 -Wall -Wextra" DEBUG_FLAGS="-g -O0 -Wall -Wextra -DDEBUG" DEV_FLAGS="-g -O1 -Wall -Wextra" LINK_FLAGS="-lssl -lcrypto" # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' PURPLE='\033[0;35m' CYAN='\033[0;36m' WHITE='\033[1;37m' GRAY='\033[0;37m' NC='\033[0m' # No Color # Build status tracking BUILD_SUCCESS=false TEST_SUCCESS=false # Print colored output print_header() { echo -e "${CYAN}╔══════════════════════════════════════════════════════════════════════════════╗${NC}" echo -e "${CYAN}║${WHITE} CCDJIT Build System ${CYAN}║${NC}" echo -e "${CYAN}╚══════════════════════════════════════════════════════════════════════════════╝${NC}" echo } print_section() { echo -e "${BLUE}┌─ ${WHITE}$1${NC}" echo -e "${BLUE}│${NC} $2" } print_success() { echo -e "${BLUE}└─${GREEN} ✓ $1${NC}" } print_error() { echo -e "${BLUE}└─${RED} ✗ $1${NC}" } print_info() { echo -e "${BLUE}│${NC} $1" } # Check dependencies check_dependencies() { print_section "Checking Dependencies" "Verifying required tools are available" local missing_deps=() if ! command -v cc &> /dev/null; then missing_deps+=("cc (C compiler)") fi if ! command -v make &> /dev/null; then missing_deps+=("make") fi if [ ${#missing_deps[@]} -eq 0 ]; then print_success "All dependencies found" return 0 else print_error "Missing dependencies: ${missing_deps[*]}" echo -e "${RED}Please install the missing dependencies and try again.${NC}" exit 1 fi } # Clean build artifacts clean() { print_section "Cleaning" "Removing build artifacts and temporary files" rm -f .cb_checksum_ccdjit rm -f bin/ccdjit rm -f *.o rm -f core rm -rf .build/ print_success "Clean completed" } # Build the project build() { local build_type="$1" local flags="$2" local description="$3" print_section "Building" "$description" # Ensure bin directory exists mkdir -p "$BUILD_DIR" # Build command local build_cmd="cc -o $BINARY_NAME $flags $SOURCE_DIR/main.c $LINK_FLAGS" print_info "Command: $build_cmd" if eval "$build_cmd"; then print_success "Build completed successfully" BUILD_SUCCESS=true # Show binary info if [ -f "$BINARY_NAME" ]; then local size=$(du -h "$BINARY_NAME" | cut -f1) print_info "Binary size: $size" print_info "Location: $BINARY_NAME" fi else print_error "Build failed" BUILD_SUCCESS=false exit 1 fi } # Run the binary run() { local args="$*" if [ ! -f "$BINARY_NAME" ]; then print_error "Binary not found. Please build first." exit 1 fi print_section "Running" "Executing $BINARY_NAME" if [ -n "$args" ]; then print_info "Arguments: $args" ./"$BINARY_NAME" $args else ./"$BINARY_NAME" fi } # Development mode dev_mode() { print_header clean build "debug" "$DEV_FLAGS" "Development build with debugging symbols" if [ "$BUILD_SUCCESS" = true ]; then echo print_section "Development Mode" "Ready for development" print_info "Binary: $BINARY_NAME" print_info "Flags: $DEV_FLAGS" print_info "Run with: $0 run [args]" fi } # Release mode release_mode() { print_header clean build "release" "$RELEASE_FLAGS" "Release build optimized for performance" if [ "$BUILD_SUCCESS" = true ]; then echo print_section "Release Mode" "Production-ready build" print_info "Binary: $BINARY_NAME" print_info "Flags: $RELEASE_FLAGS" print_info "Optimized for maximum performance" fi } # Debug mode debug_mode() { print_header clean build "debug" "$DEBUG_FLAGS" "Debug build with full debugging information" if [ "$BUILD_SUCCESS" = true ]; then echo print_section "Debug Mode" "Debug build ready" print_info "Binary: $BINARY_NAME" print_info "Flags: $DEBUG_FLAGS" print_info "Use with debugger: gdb $BINARY_NAME" fi } # Install the binary install_binary() { local install_dir="${2:-/usr/local/bin}" if [ ! -f "$BINARY_NAME" ]; then print_error "Binary not found. Please build first." exit 1 fi print_section "Installing" "Installing $PROJECT_NAME to $install_dir" if [ ! -w "$install_dir" ]; then print_info "Using sudo for installation" sudo cp "$BINARY_NAME" "$install_dir/$PROJECT_NAME" sudo chmod +x "$install_dir/$PROJECT_NAME" else cp "$BINARY_NAME" "$install_dir/$PROJECT_NAME" chmod +x "$install_dir/$PROJECT_NAME" fi print_success "Installed to $install_dir/$PROJECT_NAME" } # Uninstall the binary uninstall_binary() { local install_dir="${2:-/usr/local/bin}" local binary_path="$install_dir/$PROJECT_NAME" print_section "Uninstalling" "Removing $PROJECT_NAME from $install_dir" if [ -f "$binary_path" ]; then if [ ! -w "$install_dir" ]; then print_info "Using sudo for removal" sudo rm "$binary_path" else rm "$binary_path" fi print_success "Removed $binary_path" else print_info "Binary not found at $binary_path" fi } # Show project information show_info() { print_header print_section "Project Information" "CCDJIT Compiler Details" print_info "Name: $PROJECT_NAME" print_info "Version: 1.0.0" print_info "Description: A C-like language JIT compiler" print_info "Source Directory: $SOURCE_DIR" print_info "Binary Location: $BINARY_NAME" print_info "Test Directory: $TEST_DIR" echo print_section "Build Status" "Current build state" if [ -f "$BINARY_NAME" ]; then local size=$(du -h "$BINARY_NAME" | cut -f1) local date=$(stat -c %y "$BINARY_NAME" 2>/dev/null || stat -f %Sm "$BINARY_NAME" 2>/dev/null || echo "Unknown") print_info "Binary exists: Yes" print_info "Size: $size" print_info "Last modified: $date" else print_info "Binary exists: No" fi echo print_section "Available Commands" "Build system commands" print_info "dev - Development build with debugging" print_info "release - Optimized release build" print_info "debug - Full debug build" print_info "clean - Clean build artifacts" print_info "run [args] - Run the binary with arguments" print_info "test - Run basic test suite" print_info "test-adv - Run advanced test suite" print_info "install - Install binary to system" print_info "uninstall - Remove binary from system" print_info "info - Show project information" print_info "help - Show this help message" } # Show help show_help() { print_header echo -e "${WHITE}Usage:${NC} $0 [COMMAND] [OPTIONS]" echo echo -e "${WHITE}Commands:${NC}" echo echo -e " ${GREEN}dev${NC} Build and prepare for development" echo -e " ${GREEN}release${NC} Build optimized release version" echo -e " ${GREEN}debug${NC} Build with full debugging information" echo -e " ${GREEN}clean${NC} Clean build artifacts" echo -e " ${GREEN}run [args]${NC} Run the binary with optional arguments" echo -e " ${GREEN}test${NC} Run basic test suite" echo -e " ${GREEN}test-adv [args]${NC} Run advanced test suite" echo -e " ${GREEN}install [dir]${NC} Install binary to system (default: /usr/local/bin)" echo -e " ${GREEN}uninstall [dir]${NC} Remove binary from system" echo -e " ${GREEN}info${NC} Show project information" echo -e " ${GREEN}help${NC} Show this help message" echo echo -e "${WHITE}Examples:${NC}" echo echo -e " ${GRAY}$0 dev${NC} # Development build" echo -e " ${GRAY}$0 release${NC} # Release build" echo -e " ${GRAY}$0 run ./tests/arithmetic.c${NC} # Run with test file" echo -e " ${GRAY}$0 test${NC} # Run tests" echo -e " ${GRAY}$0 test-adv all${NC} # Run all advanced tests" echo -e " ${GRAY}$0 install${NC} # Install to /usr/local/bin" echo -e " ${GRAY}$0 install ~/bin${NC} # Install to ~/bin" echo echo -e "${WHITE}Build Flags:${NC}" echo -e " ${GRAY}Development:${NC} $DEV_FLAGS" echo -e " ${GRAY}Release:${NC} $RELEASE_FLAGS" echo -e " ${GRAY}Debug:${NC} $DEBUG_FLAGS" } # Test configuration (global) declare -gA test_map test_map["./tests/add2.c"]=3 test_map["./tests/arithmetic.c"]=28 test_map["./tests/comparison.c"]=5 test_map["./tests/logical.c"]=3 test_map["./tests/if_else.c"]=12 test_map["./tests/while_loop.c"]=10 test_map["./tests/for_loop.c"]=6 test_map["./tests/function_call.c"]=17 test_map["./tests/recursive.c"]=24 test_map["./tests/bitwise.c"]=58 test_map["./tests/pointers.c"]=184 test_map["./tests/arrays.c"]=150 test_map["./tests/strings.c"]=5 test_map["./tests/edge_cases.c"]=12 # Test categories declare -gA test_categories test_categories["./tests/add2.c"]="Basic" test_categories["./tests/arithmetic.c"]="Arithmetic" test_categories["./tests/comparison.c"]="Comparison" test_categories["./tests/logical.c"]="Logical" test_categories["./tests/if_else.c"]="Control Flow" test_categories["./tests/while_loop.c"]="Control Flow" test_categories["./tests/for_loop.c"]="Control Flow" test_categories["./tests/function_call.c"]="Functions" test_categories["./tests/recursive.c"]="Functions" test_categories["./tests/bitwise.c"]="Bitwise" test_categories["./tests/pointers.c"]="Pointers" test_categories["./tests/arrays.c"]="Arrays" test_categories["./tests/strings.c"]="Strings" test_categories["./tests/edge_cases.c"]="Edge Cases" # Basic test functions (simplified version) print_test_header() { local test_file="$1" local category="${test_categories[$test_file]}" local test_name=$(basename "$test_file" .c) echo -e "${BLUE}┌─ ${WHITE}$test_name${BLUE} (${YELLOW}$category${BLUE})${NC}" echo -e "${BLUE}│${NC} File: $test_file" echo -e "${BLUE}│${NC} Expected: ${test_map[$test_file]}" } print_test_result() { local test_file="$1" local expected="$2" local actual="$3" local status="$4" if [ "$status" == "PASS" ]; then echo -e "${BLUE}│${NC} Result: ${GREEN}✓ PASSED${NC} (got $actual)" echo -e "${BLUE}└─${GREEN} SUCCESS${NC}" else echo -e "${BLUE}│${NC} Result: ${RED}✗ FAILED${NC} (expected $expected, got $actual)" echo -e "${BLUE}└─${RED} FAILURE${NC}" fi echo } print_test_summary() { local passed="$1" local failed="$2" local total="$3" echo -e "${CYAN}╔══════════════════════════════════════════════════════════════════════════════╗${NC}" echo -e "${CYAN}║${WHITE} Test Summary ${CYAN}║${NC}" echo -e "${CYAN}╠══════════════════════════════════════════════════════════════════════════════╣${NC}" if [ $failed -eq 0 ]; then echo -e "${CYAN}║${GREEN} All tests passed! ${WHITE}($passed/$total)${NC}${CYAN} ║${NC}" else echo -e "${CYAN}║${GREEN} Passed: $passed${NC}${CYAN} │ ${RED}Failed: $failed${NC}${CYAN} │ ${WHITE}Total: $total${NC}${CYAN} ║${NC}" fi echo -e "${CYAN}╚══════════════════════════════════════════════════════════════════════════════╝${NC}" } run_basic_tests() { print_section "Testing" "Running basic test suite" local count=0 local passed=0 local failed=0 for key in "${!test_map[@]}"; do print_test_header "$key" local output local exit_code local actual_result output=$(./bin/ccdjit "$key" 2>&1) exit_code=$? # Extract the actual result from "JIT returned: X" line actual_result=$(echo "$output" | grep "JIT returned:" | sed 's/.*JIT returned: //' | tail -1) if [ -z "$actual_result" ]; then # If no "JIT returned:" found, use exit code actual_result=$exit_code fi if [ "${test_map[$key]}" = "$actual_result" ]; then print_test_result "$key" "${test_map[$key]}" "$actual_result" "PASS" passed=$((passed+1)) else print_test_result "$key" "${test_map[$key]}" "$actual_result" "FAIL" failed=$((failed+1)) fi count=$((count+1)) done print_test_summary $passed $failed $count if [ $failed -eq 0 ]; then TEST_SUCCESS=true else TEST_SUCCESS=false fi } # Main command dispatcher main() { # Check dependencies first check_dependencies case "${1:-help}" in "dev"|"development") dev_mode ;; "release") release_mode ;; "debug") debug_mode ;; "clean") print_header clean ;; "run") shift run "$@" ;; "test") if [ ! -f "$BINARY_NAME" ]; then print_error "Binary not found. Building first..." build "test" "$RELEASE_FLAGS" "Test build" fi print_header run_basic_tests ;; "test-adv"|"test-advanced") if [ ! -f "$BINARY_NAME" ]; then print_error "Binary not found. Building first..." build "test" "$RELEASE_FLAGS" "Test build" fi shift ./test_runner.sh "$@" ;; "install") install_binary "$@" ;; "uninstall") uninstall_binary "$@" ;; "info") show_info ;; "help"|"-h"|"--help") show_help ;; *) echo -e "${RED}Error: Unknown command '$1'${NC}" echo "Use '$0 help' for usage information" exit 1 ;; esac } # Run main function with all arguments main "$@"