#!/usr/bin/env sh # C++ 模板验证脚本 set -eu echo "========================================" echo "⚙️ C++ 模板验证" echo "========================================" SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" PLAYBOOK_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" TEMPLATES_DIR="$PLAYBOOK_ROOT/templates/cpp" VALIDATION_PASSED=0 VALIDATION_FAILED=0 ERRORS_FILE="/tmp/cpp_template_validation_errors.txt" REPORT_FILE="$SCRIPT_DIR/cpp_validation_report.txt" > "$ERRORS_FILE" > "$REPORT_FILE" echo "📁 模板目录: $TEMPLATES_DIR" echo "" # ============================================ # 辅助函数 # ============================================ validate_file_exists() { local file="$1" local description="$2" if [ -f "$file" ]; then echo " ✅ $description: $(basename "$file")" VALIDATION_PASSED=$((VALIDATION_PASSED + 1)) return 0 else echo " ❌ $description: $(basename "$file") - 文件不存在" echo "文件不存在: $file" >> "$ERRORS_FILE" VALIDATION_FAILED=$((VALIDATION_FAILED + 1)) return 1 fi } validate_cmake_syntax() { local file="$1" local description="$2" # 基础语法检查 if [ ! -s "$file" ]; then echo " ❌ $description: 文件为空" VALIDATION_FAILED=$((VALIDATION_FAILED + 1)) return 1 fi # 检查必要的 CMake 命令 local has_errors=0 if ! grep -q "cmake_minimum_required" "$file"; then echo " ✗ 缺少 cmake_minimum_required" has_errors=1 fi if ! grep -q "project(" "$file"; then echo " ✗ 缺少 project()" has_errors=1 fi if [ $has_errors -eq 0 ]; then echo " ✅ $description: CMake 基础语法正确" VALIDATION_PASSED=$((VALIDATION_PASSED + 1)) return 0 else echo " ❌ $description: CMake 语法检查失败" echo "CMake 语法错误: $file" >> "$ERRORS_FILE" VALIDATION_FAILED=$((VALIDATION_FAILED + 1)) return 1 fi } # ============================================ # 验证 CMakeLists.txt # ============================================ echo "🔍 验证 CMakeLists.txt" CMAKE_FILE="$TEMPLATES_DIR/CMakeLists.txt" if validate_file_exists "$CMAKE_FILE" "CMakeLists.txt"; then # 验证 CMake 语法 validate_cmake_syntax "$CMAKE_FILE" "CMakeLists.txt" echo " 📋 检查 C++23 配置:" # 检查 C++23 标准 if grep -q "CMAKE_CXX_STANDARD 23" "$CMAKE_FILE"; then echo " ✓ 配置了 C++23 标准" VALIDATION_PASSED=$((VALIDATION_PASSED + 1)) else echo " ✗ 未配置 C++23 标准" echo "未配置 C++23: $CMAKE_FILE" >> "$ERRORS_FILE" VALIDATION_FAILED=$((VALIDATION_FAILED + 1)) fi # 检查 Modules 支持 if grep -q "CMAKE_CXX_SCAN_FOR_MODULES" "$CMAKE_FILE"; then echo " ✓ 启用了 C++ Modules 扫描" VALIDATION_PASSED=$((VALIDATION_PASSED + 1)) else echo " ⚠️ 未启用 C++ Modules 扫描(可选)" fi # 检查 import std; 支持 if grep -q "CMAKE_EXPERIMENTAL_CXX_IMPORT_STD" "$CMAKE_FILE"; then echo " ✓ 启用了 import std; 支持" VALIDATION_PASSED=$((VALIDATION_PASSED + 1)) else echo " ⚠️ 未启用 import std; 支持(可选)" fi # 检查编译命令导出 if grep -q "CMAKE_EXPORT_COMPILE_COMMANDS" "$CMAKE_FILE"; then echo " ✓ 启用了编译命令导出(用于 clangd)" VALIDATION_PASSED=$((VALIDATION_PASSED + 1)) else echo " ⚠️ 未启用编译命令导出" fi fi echo "" # ============================================ # 验证 .clang-format # ============================================ echo "🔍 验证 .clang-format" CLANG_FORMAT="$TEMPLATES_DIR/.clang-format" if validate_file_exists "$CLANG_FORMAT" ".clang-format"; then # 验证 YAML 语法 if command -v yamllint >/dev/null 2>&1; then if yamllint -d relaxed "$CLANG_FORMAT" >/dev/null 2>&1; then echo " ✓ YAML 语法正确" VALIDATION_PASSED=$((VALIDATION_PASSED + 1)) else echo " ✗ YAML 语法错误" VALIDATION_FAILED=$((VALIDATION_FAILED + 1)) fi fi # 验证关键配置 echo " 📋 检查格式化配置:" if grep -q "^Language:" "$CLANG_FORMAT" && grep -q "Cpp" "$CLANG_FORMAT"; then echo " ✓ 配置了 Language: Cpp" VALIDATION_PASSED=$((VALIDATION_PASSED + 1)) fi if grep -q "^BasedOnStyle:" "$CLANG_FORMAT"; then style=$(grep "^BasedOnStyle:" "$CLANG_FORMAT" | awk '{print $2}') echo " ✓ 基于风格: $style" VALIDATION_PASSED=$((VALIDATION_PASSED + 1)) fi if grep -q "^Standard:" "$CLANG_FORMAT"; then std=$(grep "^Standard:" "$CLANG_FORMAT" | awk '{print $2}') echo " ✓ C++ 标准: $std" VALIDATION_PASSED=$((VALIDATION_PASSED + 1)) fi # 检查缩进配置 if grep -q "^IndentWidth:" "$CLANG_FORMAT"; then echo " ✓ 配置了缩进宽度" VALIDATION_PASSED=$((VALIDATION_PASSED + 1)) fi fi echo "" # ============================================ # 验证 .clangd # ============================================ echo "🔍 验证 .clangd" CLANGD="$TEMPLATES_DIR/.clangd" if validate_file_exists "$CLANGD" ".clangd"; then # 验证 YAML 语法 if command -v yamllint >/dev/null 2>&1; then if yamllint -d relaxed "$CLANGD" >/dev/null 2>&1; then echo " ✓ YAML 语法正确" VALIDATION_PASSED=$((VALIDATION_PASSED + 1)) else echo " ✗ YAML 语法错误" VALIDATION_FAILED=$((VALIDATION_FAILED + 1)) fi fi # 验证 CompileFlags echo " 📋 检查 clangd 配置:" if grep -q "CompileFlags:" "$CLANGD"; then echo " ✓ 包含 CompileFlags 配置" VALIDATION_PASSED=$((VALIDATION_PASSED + 1)) # 检查 C++23 标准 if grep -q "std=c++23" "$CLANGD"; then echo " ✓ 配置了 -std=c++23" VALIDATION_PASSED=$((VALIDATION_PASSED + 1)) fi fi # 验证 CompilationDatabase if grep -q "CompilationDatabase:" "$CLANGD"; then echo " ✓ 配置了 CompilationDatabase 路径" VALIDATION_PASSED=$((VALIDATION_PASSED + 1)) fi # 验证 Index 配置 if grep -q "Index:" "$CLANGD"; then echo " ✓ 配置了索引选项" VALIDATION_PASSED=$((VALIDATION_PASSED + 1)) fi fi echo "" # ============================================ # 验证 conanfile.txt # ============================================ echo "🔍 验证 conanfile.txt" CONANFILE="$TEMPLATES_DIR/conanfile.txt" if validate_file_exists "$CONANFILE" "conanfile.txt"; then echo " 📋 检查 Conan 配置:" # 验证必要的节 if grep -q "^\[requires\]" "$CONANFILE"; then echo " ✓ 包含 [requires] 配置" VALIDATION_PASSED=$((VALIDATION_PASSED + 1)) else echo " ⚠️ 缺少 [requires] 配置(可选)" fi if grep -q "^\[generators\]" "$CONANFILE"; then echo " ✓ 包含 [generators] 配置" VALIDATION_PASSED=$((VALIDATION_PASSED + 1)) # 检查 CMakeDeps 和 CMakeToolchain if grep -q "CMakeDeps" "$CONANFILE"; then echo " ✓ 配置了 CMakeDeps 生成器" VALIDATION_PASSED=$((VALIDATION_PASSED + 1)) fi if grep -q "CMakeToolchain" "$CONANFILE"; then echo " ✓ 配置了 CMakeToolchain 生成器" VALIDATION_PASSED=$((VALIDATION_PASSED + 1)) fi fi if grep -q "^\[options\]" "$CONANFILE"; then echo " ✓ 包含 [options] 配置" VALIDATION_PASSED=$((VALIDATION_PASSED + 1)) fi fi echo "" # ============================================ # 验证 CMakeUserPresets.json # ============================================ echo "🔍 验证 CMakeUserPresets.json" CMAKE_PRESETS="$TEMPLATES_DIR/CMakeUserPresets.json" if validate_file_exists "$CMAKE_PRESETS" "CMakeUserPresets.json"; then # 验证 JSON 语法 if command -v python3 >/dev/null 2>&1; then if python3 -m json.tool "$CMAKE_PRESETS" >/dev/null 2>&1; then echo " ✓ JSON 语法正确" VALIDATION_PASSED=$((VALIDATION_PASSED + 1)) else echo " ✗ JSON 语法错误" VALIDATION_FAILED=$((VALIDATION_FAILED + 1)) fi fi # 验证配置项 echo " 📋 检查 CMake Presets:" if grep -q "\"version\"" "$CMAKE_PRESETS"; then echo " ✓ 包含 version 字段" VALIDATION_PASSED=$((VALIDATION_PASSED + 1)) fi if grep -q "\"configurePresets\"" "$CMAKE_PRESETS"; then echo " ✓ 包含 configurePresets" VALIDATION_PASSED=$((VALIDATION_PASSED + 1)) fi if grep -q "\"buildPresets\"" "$CMAKE_PRESETS"; then echo " ✓ 包含 buildPresets" VALIDATION_PASSED=$((VALIDATION_PASSED + 1)) fi fi echo "" # ============================================ # 生成验证报告 # ============================================ echo "========================================" echo "📊 验证结果统计" echo "========================================" echo "✅ 通过: $VALIDATION_PASSED" echo "❌ 失败: $VALIDATION_FAILED" echo "📈 通过率: $(awk "BEGIN {printf \"%.1f\", ($VALIDATION_PASSED * 100.0) / ($VALIDATION_PASSED + $VALIDATION_FAILED)}")%" echo "" # 写入报告文件 { echo "C++ 模板验证报告" echo "====================" echo "" echo "验证时间: $(date '+%Y-%m-%d %H:%M:%S')" echo "模板目录: $TEMPLATES_DIR" echo "" echo "统计结果:" echo " 通过: $VALIDATION_PASSED" echo " 失败: $VALIDATION_FAILED" echo " 通过率: $(awk "BEGIN {printf \"%.1f\", ($VALIDATION_PASSED * 100.0) / ($VALIDATION_PASSED + $VALIDATION_FAILED)}")%" echo "" if [ -s "$ERRORS_FILE" ]; then echo "错误详情:" cat "$ERRORS_FILE" fi } > "$REPORT_FILE" echo "📄 详细报告: $REPORT_FILE" echo "========================================" # 清理临时文件 rm -f "$ERRORS_FILE" # 返回结果 if [ "$VALIDATION_FAILED" -eq 0 ]; then echo "✅ 所有 C++ 模板验证通过" exit 0 else echo "❌ C++ 模板验证失败 ($VALIDATION_FAILED 个错误)" exit 1 fi