webserv/scripts/check_iwyu.sh
2025-10-10 07:56:49 +02:00

181 lines
5.7 KiB
Bash
Executable File

#!/bin/bash
# Don't exit on first error - we want to continue checking all files
# set -e
# Change to project root directory (parent of scripts directory)
cd "$(dirname "$0")/.." || exit 1
PROJECT_ROOT="$(pwd)"
# Find the build directory - check multiple possible locations
BUILD_DIR=""
echo -e "${BLUE}🔍 Looking for build directory with compile_commands.json...${NC}"
for build_candidate in "$PROJECT_ROOT/build-container" "$PROJECT_ROOT/build-local" "$PROJECT_ROOT/build"; do
echo -e " Checking: $build_candidate"
if [ -d "$build_candidate" ] && [ -f "$build_candidate/compile_commands.json" ]; then
BUILD_DIR="$build_candidate"
echo -e "${GREEN} ✅ Found!${NC}"
break
else
echo -e "${YELLOW} ❌ Not found or no compile_commands.json${NC}"
fi
done
IWYU_MAPPING="$PROJECT_ROOT/scripts/.iwyu.imp"
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
echo -e "${BLUE}🔍 Running Include What You Use Analysis...${NC}"
echo -e "${BLUE}📁 Project root: $PROJECT_ROOT${NC}"
# Check if IWYU is available (try both common names)
IWYU_CMD=""
if command -v include-what-you-use >/dev/null 2>&1; then
IWYU_CMD="include-what-you-use"
echo -e "${GREEN}✅ Found IWYU as: include-what-you-use${NC}"
elif command -v iwyu >/dev/null 2>&1; then
IWYU_CMD="iwyu"
echo -e "${GREEN}✅ Found IWYU as: iwyu${NC}"
else
echo -e "${RED}❌ IWYU not found. Please install it first.${NC}"
echo -e "${YELLOW}💡 Try: sudo apt install iwyu or yay -S include-what-you-use${NC}"
exit 1
fi
echo -e "${BLUE}🛠️ Using IWYU command: $IWYU_CMD${NC}"
# Check if mapping file exists
if [ -f "$IWYU_MAPPING" ]; then
echo -e "${GREEN}📋 Using IWYU mapping file: $IWYU_MAPPING${NC}"
else
echo -e "${YELLOW}⚠️ No IWYU mapping file found at: $IWYU_MAPPING${NC}"
echo -e "${YELLOW}💡 Consider creating one for better IWYU suggestions${NC}"
fi
# Check if we found a build directory
if [ -z "$BUILD_DIR" ]; then
echo -e "${YELLOW}⚠️ No build directory with compile_commands.json found.${NC}"
echo -e "${YELLOW}📂 Checked: build-container/, build-local/, build/${NC}"
echo -e "${YELLOW}🔨 Running cmake to create build directory...${NC}"
cd "$PROJECT_ROOT"
BUILD_DIR="$PROJECT_ROOT/build"
mkdir -p "$BUILD_DIR"
cd "$BUILD_DIR"
cmake .. -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
else
echo -e "${GREEN}✅ Found build directory: $BUILD_DIR${NC}"
fi
# Final check that compile_commands.json exists
if [ ! -f "$BUILD_DIR/compile_commands.json" ]; then
echo -e "${RED}❌ Failed to create compile_commands.json in $BUILD_DIR${NC}"
cd "$PROJECT_ROOT"
cmake -B "$BUILD_DIR" -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_BUILD_TYPE=Debug
# Check again after cmake
if [ ! -f "$BUILD_DIR/compile_commands.json" ]; then
echo -e "${RED}❌ Still no compile_commands.json after cmake. Exiting.${NC}"
exit 1
fi
fi
# Create results directory
RESULTS_DIR="$PROJECT_ROOT/scripts/iwyu_results"
mkdir -p "$RESULTS_DIR"
# Function to run IWYU on a single file
run_iwyu_on_file() {
local file="$1"
local relative_path="${file#$PROJECT_ROOT/}"
local output_file="$RESULTS_DIR/$(basename "$file" .cpp).iwyu"
echo -e "${BLUE}Analyzing: ${relative_path}${NC}"
# Run IWYU with compile commands and mapping file
if "$IWYU_CMD" \
-I"$PROJECT_ROOT" \
-std=c++20 \
-Xiwyu --verbose=3 \
-Xiwyu --quoted_includes_first \
-Xiwyu --cxx17ns \
-Xiwyu --mapping_file="$IWYU_MAPPING" \
"$file" \
2>&1 | tee "$output_file"; then
# Check if IWYU found issues
if grep -q "should add these lines:" "$output_file" || grep -q "should remove these lines:" "$output_file"; then
echo -e "${YELLOW}⚠️ Issues found in $relative_path${NC}"
return 2 # Issues found (not a script failure)
else
echo -e "${GREEN}$relative_path looks good${NC}"
return 0 # All good
fi
else
local iwyu_exit_code=$?
echo -e "${RED}❌ IWYU failed for $relative_path (exit code: $iwyu_exit_code)${NC}"
return 1 # IWYU execution failed
return 1
fi
}
# Find all C++ source files
echo -e "\n${BLUE}Finding C++ source files...${NC}"
cpp_files=()
while IFS= read -r -d '' file; do
cpp_files+=("$file")
done < <(find "$PROJECT_ROOT/webserv" -name "*.cpp" -print0 2>/dev/null)
if [ ${#cpp_files[@]} -eq 0 ]; then
echo -e "${RED}❌ No .cpp files found in webserv directory${NC}"
exit 1
fi
echo -e "${BLUE}Found ${#cpp_files[@]} C++ source files${NC}\n"
# Run IWYU on all files
issues_found=0
total_files=${#cpp_files[@]}
current_file=0
for file in "${cpp_files[@]}"; do
((current_file++))
echo -e "${BLUE}[$current_file/$total_files]${NC}"
run_iwyu_on_file "$file"
exit_code=$?
if [ $exit_code -eq 2 ]; then
# Issues found (normal)
((issues_found++))
elif [ $exit_code -eq 1 ]; then
# IWYU execution failed (error)
echo -e "${RED}⚠️ IWYU execution error for $(basename "$file")${NC}"
((issues_found++))
fi
# exit_code 0 means no issues found
echo ""
done
# Summary
echo -e "${BLUE}📊 IWYU Analysis Summary${NC}"
echo -e "Total files analyzed: $total_files"
echo -e "Files with issues: $issues_found"
echo -e "Results saved in: $RESULTS_DIR"
if [ $issues_found -eq 0 ]; then
echo -e "${GREEN}🎉 All files have proper includes!${NC}"
exit 0
else
echo -e "${YELLOW}⚠️ $issues_found files need attention${NC}"
echo -e "${BLUE}💡 Run './fix_iwyu.sh' to review suggested fixes${NC}"
exit 0 # Don't fail the script for include suggestions
fi