#!/bin/bash # ============================================================================ # CONFIGURACIÓN - Editar estas constantes para personalizar el script # ============================================================================ # Detectar la ubicación del script y la raíz del proyecto SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" # Rutas del proyecto DEFAULT_ANALYSIS_PATH="$PROJECT_ROOT/source" INCLUDE_PATH="$PROJECT_ROOT/source" SUPPRESSIONS_FILE="$SCRIPT_DIR/cppcheck_suppressions" OUTPUT_DIR="$SCRIPT_DIR" BUILD_DIR="$PROJECT_ROOT/build" COMPILE_COMMANDS="$BUILD_DIR/compile_commands.json" # Parámetros de compilación comunes (fallback para análisis de archivos específicos) CPPCHECK_STD="--std=c++20" # Calcular número de threads (cores - 1, mínimo 1) THREADS=$(($(nproc) - 1)) [[ $THREADS -lt 1 ]] && THREADS=1 # ============================================================================ # Función para asegurar que compile_commands.json existe ensure_compile_commands() { if [[ ! -f "$COMPILE_COMMANDS" ]]; then echo "⚠ compile_commands.json no encontrado en $BUILD_DIR" echo "Generando compile_commands.json con CMake..." # Crear directorio build si no existe mkdir -p "$BUILD_DIR" # Ejecutar CMake para generar compile_commands.json (cd "$BUILD_DIR" && cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON .. > /dev/null 2>&1) if [[ ! -f "$COMPILE_COMMANDS" ]]; then echo "❌ Error: No se pudo generar compile_commands.json" echo "Por favor, ejecuta manualmente:" echo " cd $BUILD_DIR && cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON .." exit 1 fi echo "✓ compile_commands.json generado exitosamente" else echo "✓ Usando compile_commands.json existente: $COMPILE_COMMANDS" fi } # Función para mostrar el uso del script mostrar_uso() { echo "Uso: $0 [OPCIÓN] [RUTA]" echo "" echo "Opciones de análisis:" echo " -w, --warning Ejecutar cppcheck con warning, style, performance" echo " -a, --all Ejecutar cppcheck con todas las opciones habilitadas" echo " -u, --unused Ejecutar cppcheck para unusedFunction" echo "" echo "Opciones de ruta:" echo " -p, --path Especificar ruta a analizar (default: PROJECT_ROOT/source)" echo " [RUTA] Ruta como último argumento posicional" echo "" echo "Ejemplos:" echo " $0 --warning" echo " $0 -w --path ../src/" echo " $0 --all /path/to/code/" echo " $0 -u ../source/" } # Inicializar las variables opcion="" ruta="$DEFAULT_ANALYSIS_PATH" # Procesar las opciones while [[ $# -gt 0 ]]; do case $1 in -w|--warning) opcion="warning" shift ;; -a|--all) opcion="all" shift ;; -u|--unused) opcion="unused" shift ;; -p|--path) if [[ -n "$2" && "$2" != -* ]]; then ruta="$2" shift 2 else echo "Error: --path requiere un argumento" mostrar_uso exit 1 fi ;; -h|--help) mostrar_uso exit 0 ;; -*) echo "Error: Opción desconocida: $1" mostrar_uso exit 1 ;; *) # Argumento posicional (asumimos que es la ruta) ruta="$1" shift ;; esac done # Verificar que se haya especificado una opción de análisis if [[ -z "$opcion" ]]; then echo "Error: Debe especificar una opción de análisis (-w, -a, o -u)" mostrar_uso exit 1 fi # Ejecutar según la opción seleccionada case $opcion in warning) ensure_compile_commands if [[ "$ruta" == "$DEFAULT_ANALYSIS_PATH" ]]; then echo "Ejecutando cppcheck con warning, style, performance en proyecto completo (usando $THREADS threads)" cppcheck --force --enable=warning,style,performance \ --check-level=exhaustive \ -j$THREADS \ --project="$COMPILE_COMMANDS" \ --suppressions-list="$SUPPRESSIONS_FILE" \ 2>"$OUTPUT_DIR/cppcheck-result-warning-style-performance.txt" else echo "Ejecutando cppcheck con warning, style, performance en: $ruta (usando $THREADS threads)" cppcheck --force --enable=warning,style,performance $CPPCHECK_STD \ --check-level=exhaustive \ -j$THREADS \ -I "$INCLUDE_PATH" \ --suppressions-list="$SUPPRESSIONS_FILE" \ "$ruta" \ 2>"$OUTPUT_DIR/cppcheck-result-warning-style-performance.txt" fi echo "Resultados guardados en: $OUTPUT_DIR/cppcheck-result-warning-style-performance.txt" ;; all) ensure_compile_commands if [[ "$ruta" == "$DEFAULT_ANALYSIS_PATH" ]]; then echo "Ejecutando cppcheck con todas las opciones en proyecto completo (usando $THREADS threads)" cppcheck --force --enable=all \ -j$THREADS \ --project="$COMPILE_COMMANDS" \ --suppress=missingIncludeSystem \ --suppressions-list="$SUPPRESSIONS_FILE" \ 2>"$OUTPUT_DIR/cppcheck-result-all.txt" else echo "Ejecutando cppcheck con todas las opciones en: $ruta (usando $THREADS threads)" cppcheck --force --enable=all -I /usr/include -I "$INCLUDE_PATH" $CPPCHECK_STD \ -j$THREADS \ --suppress=missingIncludeSystem \ --suppressions-list="$SUPPRESSIONS_FILE" \ "$ruta" \ 2>"$OUTPUT_DIR/cppcheck-result-all.txt" fi echo "Resultados guardados en: $OUTPUT_DIR/cppcheck-result-all.txt" ;; unused) ensure_compile_commands if [[ "$ruta" == "$DEFAULT_ANALYSIS_PATH" ]]; then echo "Ejecutando cppcheck para unusedFunction en proyecto completo (usando $THREADS threads)" cppcheck --enable=style \ -j$THREADS \ --project="$COMPILE_COMMANDS" \ --suppressions-list="$SUPPRESSIONS_FILE" \ 2>"$OUTPUT_DIR/cppcheck-result-unusedFunction.txt" else echo "Ejecutando cppcheck para unusedFunction en: $ruta (usando $THREADS threads)" cppcheck --enable=style $CPPCHECK_STD \ -j$THREADS \ -I "$INCLUDE_PATH" \ --suppressions-list="$SUPPRESSIONS_FILE" \ "$ruta" \ 2>"$OUTPUT_DIR/cppcheck-result-unusedFunction.txt" fi echo "Resultados guardados en: $OUTPUT_DIR/cppcheck-result-unusedFunction.txt" ;; *) echo "Error: Opción inválida" mostrar_uso exit 1 ;; esac