#!/bin/bash # Colors RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' CYAN='\033[0;36m' MAGENTA='\033[0;35m' NC='\033[0m' # No Color BOLD='\033[1m' # Unicode symbols CHECK="✓" CROSS="✗" ARROW="➜" GEAR="⚙" HAMMER="🔨" ROCKET="🚀" # Default values BUILD_TYPE="Debug" CLEAN_BUILD=false VERBOSE=false JOBS=$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 4) # Print functions print_header() { echo -e "${BOLD}${BLUE}╔════════════════════════════════════════════════════════╗${NC}" echo -e "${BOLD}${BLUE}║${NC} ${HAMMER} ${BOLD}${CYAN} C/C++ Project Builder${NC} ${BOLD}${BLUE}║${NC}" echo -e "${BOLD}${BLUE}╚════════════════════════════════════════════════════════╝${NC}" echo "" } print_separator() { echo -e "${BLUE}────────────────────────────────────────────────────────${NC}" } print_success() { echo -e "${GREEN}${CHECK}${NC} $1" } print_error() { echo -e "${RED}${CROSS}${NC} $1" } print_info() { echo -e "${CYAN}${ARROW}${NC} $1" } print_step() { echo -e "${YELLOW}${GEAR}${NC} ${BOLD}$1${NC}" } show_progress() { local duration=$1 local prefix=$2 local size=40 already_done() { for ((done=0; done<$elapsed; done++)); do printf "▓"; done } remaining() { for ((remain=$elapsed; remain<$size; remain++)); do printf " "; done } percentage() { printf "| %s%%" $(( (($elapsed)*100)/($size)*100/100 )); } for (( elapsed=1; elapsed<=$size; elapsed++ )); do printf "\r${CYAN}${prefix}${NC} [$(already_done)$(remaining)] $(percentage)" sleep $(echo "scale=3; $duration/$size" | bc) done printf "\n" } usage() { echo -e "${BOLD}Usage:${NC} $0 [OPTIONS] " echo "" echo -e "${BOLD}Options:${NC}" echo -e " -r, --release Build in Release mode (default: Debug)" echo -e " -c, --clean Clean build directory before building" echo -e " -v, --verbose Verbose make output" echo -e " -j, --jobs Number of parallel jobs (default: $JOBS)" echo -e " -h, --help Show this help message" echo "" echo -e "${BOLD}Examples:${NC}" echo -e " $0 myprogram" echo -e " $0 -r -j8 myprogram" echo -e " $0 --clean --release myprogram" exit 1 } # Parse arguments POSITIONAL_ARGS=() while [[ $# -gt 0 ]]; do case $1 in -r|--release) BUILD_TYPE="Release" shift ;; -c|--clean) CLEAN_BUILD=true shift ;; -v|--verbose) VERBOSE=true shift ;; -j|--jobs) JOBS="$2" shift 2 ;; -h|--help) usage ;; *) POSITIONAL_ARGS+=("$1") shift ;; esac done set -- "${POSITIONAL_ARGS[@]}" # Check if executable name is provided if [ -z "$1" ]; then print_header print_error "No executable name provided" echo "" usage fi EXECUTABLE_NAME=$1 # Start build process print_header # Build configuration info print_info "Build Configuration:" echo -e " ${BOLD}Executable:${NC} $EXECUTABLE_NAME" echo -e " ${BOLD}Build Type:${NC} $BUILD_TYPE" echo -e " ${BOLD}Jobs:${NC} $JOBS" echo -e " ${BOLD}Clean Build:${NC} $CLEAN_BUILD" echo "" print_separator echo "" # Clean build directory if requested if [ "$CLEAN_BUILD" = true ] && [ -d "./build" ]; then print_step "Cleaning build directory..." rm -rf ./build print_success "Build directory cleaned" echo "" fi # Create build directory if [ ! -d "./build" ]; then print_step "Creating build directory..." mkdir -p build print_success "Build directory created" else print_info "Using existing build directory" fi echo "" # CMake configuration print_step "Configuring CMake..." print_separator echo "" cd ./build CMAKE_CMD="cmake -DOUTPUT_NAME=$EXECUTABLE_NAME -DCMAKE_BUILD_TYPE=$BUILD_TYPE .." if [ "$VERBOSE" = true ]; then eval $CMAKE_CMD else eval $CMAKE_CMD > /dev/null 2>&1 fi if [ $? -ne 0 ]; then print_error "CMake configuration failed" exit 1 fi print_success "CMake configuration complete" echo "" # Compilation print_step "Compiling project..." print_separator echo "" MAKE_CMD="make -j$JOBS" if [ "$VERBOSE" = true ]; then MAKE_CMD="$MAKE_CMD VERBOSE=1" fi START_TIME=$(date +%s) if [ "$VERBOSE" = true ]; then eval $MAKE_CMD BUILD_RESULT=$? else eval $MAKE_CMD 2>&1 | tee build.log | while IFS= read -r line; do if echo "$line" | grep -q "\[.*%\]"; then printf "\r${CYAN}${ARROW}${NC} Compiling: %s" "$line" elif echo "$line" | grep -qE "error:|Error|ERROR"; then echo "" print_error "$line" fi done BUILD_RESULT=${PIPESTATUS[0]} fi END_TIME=$(date +%s) BUILD_TIME=$((END_TIME - START_TIME)) echo "" if [ $BUILD_RESULT -ne 0 ]; then print_error "Build failed!" echo "" print_info "Check build/build.log for details" exit 1 fi print_success "Compilation complete (${BUILD_TIME}s)" echo "" # Copy executable print_step "Copying executable to project root..." if [ ! -f "./bin/$EXECUTABLE_NAME" ]; then print_error "Executable not found: ./bin/$EXECUTABLE_NAME" exit 1 fi cp ./bin/$EXECUTABLE_NAME ../ print_success "Executable copied" echo "" # Build summary print_separator echo -e "${BOLD}${GREEN}${ROCKET} Build Complete!${NC}" print_separator echo "" echo -e "${BOLD}Summary:${NC}" echo -e " ${BOLD}Executable:${NC} ./$EXECUTABLE_NAME" echo -e " ${BOLD}Build Type:${NC} $BUILD_TYPE" echo -e " ${BOLD}Build Time:${NC} ${BUILD_TIME}s" echo -e " ${BOLD}Binary Location:${NC} ./build/bin/$EXECUTABLE_NAME" # File size info if command -v du &> /dev/null; then SIZE=$(du -h "./$EXECUTABLE_NAME" | cut -f1) echo -e " ${BOLD}Binary Size:${NC} $SIZE" fi echo "" print_info "Run with: ${BOLD}./$EXECUTABLE_NAME${NC}" echo ""