diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..caf5d52 --- /dev/null +++ b/.clang-format @@ -0,0 +1,22 @@ +BasedOnStyle: LLVM + +IndentWidth: 4 +TabWidth: 4 +UseTab: Never + +ColumnLimit: 100 + +BreakBeforeBraces: Allman + +AllowShortFunctionsOnASingleLine: Empty +AllowShortBlocksOnASingleLine: Never + +NamespaceIndentation: All + +PointerAlignment: Left +ReferenceAlignment: Left + +SpaceBeforeParens: ControlStatements + +SortIncludes: true +IncludeBlocks: Regroup \ No newline at end of file diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 0000000..475130e --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,75 @@ +# .clang-tidy +Checks: > + -*, + + # High-value bug detection + bugprone-*, + clang-analyzer-*, + + # Performance improvements + performance-*, + + # Modern C++ suggestions + modernize-*, + + # Selected core guidelines + cppcoreguidelines-avoid-magic-numbers, + cppcoreguidelines-init-variables, + cppcoreguidelines-narrowing-conversions, + cppcoreguidelines-slicing, + cppcoreguidelines-special-member-functions, + + # Useful readability checks (not noisy ones) + readability-braces-around-statements, + readability-const-return-type, + readability-implicit-bool-conversion, + readability-redundant-control-flow, + readability-simplify-boolean-expr, + + # Disabled noisy checks + -modernize-use-trailing-return-type, + -modernize-use-auto, + -modernize-use-nodiscard, + -cppcoreguidelines-pro-bounds-array-to-pointer-decay, + -cppcoreguidelines-pro-type-vararg, + -cppcoreguidelines-owning-memory, + -cppcoreguidelines-avoid-c-arrays, + -readability-magic-numbers + +WarningsAsErrors: > + bugprone-*, + clang-analyzer-* + +HeaderFilterRegex: 'src/.*|include/.*' + +CheckOptions: + + # Identifier naming + - key: readability-identifier-naming.NamespaceCase + value: lower_case + + - key: readability-identifier-naming.ClassCase + value: CamelCase + + - key: readability-identifier-naming.StructCase + value: CamelCase + + - key: readability-identifier-naming.FunctionCase + value: lower_case + + - key: readability-identifier-naming.MethodCase + value: lower_case + + - key: readability-identifier-naming.VariableCase + value: lower_case + + - key: readability-identifier-naming.PrivateMemberSuffix + value: _ + + # Magic numbers ignored in common cases + - key: readability-magic-numbers.IgnoredIntegerValues + value: '0;1;2;-1' + + # Allow short functions to skip braces rule + - key: readability-braces-around-statements.ShortStatementLines + value: '1' \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 51c38a2..5bf6f9b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,9 +2,9 @@ name: CI on: push: - branches: [main, develop] + branches: [master, develop] pull_request: - branches: [main] + branches: [master] workflow_dispatch: jobs: @@ -30,45 +30,79 @@ jobs: with: submodules: true + - name: Set up MSVC (Windows) + if: runner.os == 'Windows' + uses: ilammy/msvc-dev-cmd@v1 + with: + arch: x64 + - name: Setup vcpkg uses: lukka/run-vcpkg@v11 with: vcpkgJsonGlob: 'vcpkg.json' - - name: Install Ninja & Tools (Linux) + - name: Install Ninja (Linux) if: runner.os == 'Linux' - run: sudo apt-get update && sudo apt-get install -y ninja-build + run: | + sudo apt-get update + sudo apt-get install -y ninja-build - name: Configure CMake - run: cmake --preset ${{ matrix.preset }} + shell: bash + run: | + cmake --preset ${{ matrix.preset }} \ + -DCMAKE_TOOLCHAIN_FILE="${VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" - - name: Build - run: cmake --build --preset ${{ matrix.preset }} --parallel + - name: Build (Linux) + if: runner.os == 'Linux' + shell: bash + run: | + # Split by the last hyphen to handle names like linux-clang-release + PRESET="${{ matrix.preset }}" + BASE_PRESET="${PRESET%-*}" + CONFIG="${PRESET##*-}" + bash ./scripts/build.sh "$BASE_PRESET" "$CONFIG" - - name: Test - run: ctest --preset ${{ matrix.preset }} --output-on-failure + - name: Build (Windows) + if: runner.os == 'Windows' + shell: cmd + run: | + @echo off + for /f "tokens=1,2,3 delims=-" %%a in ("${{ matrix.preset }}") do ( + if "%%c"=="" ( + call scripts\build.bat %%a %%b + ) else ( + call scripts\build.bat %%a-%%b %%c + ) + ) - # --- Code Quality & Sanitizers --- analysis: name: Analysis (Clang-Tidy & ASan) runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - - name: Setup vcpkg # Use vcpkg here too for consistency! + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup vcpkg uses: lukka/run-vcpkg@v11 with: vcpkgJsonGlob: 'vcpkg.json' + - name: Install Tools - run: sudo apt-get update && sudo apt-get install -y ninja-build clang clang-tidy - # ... rest of your cmake commands - + run: | + sudo apt-get update + sudo apt-get install -y ninja-build clang clang-tidy + - name: Configure & Build + shell: bash run: | cmake -B build -G Ninja \ -DCMAKE_CXX_COMPILER=clang++ \ -DENABLE_SANITIZERS=ON \ - -DENABLE_CLANG_TIDY=ON + -DENABLE_CLANG_TIDY=OFF \ + -DCMAKE_TOOLCHAIN_FILE="${VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" cmake --build build --parallel - name: Run Tests + shell: bash run: ctest --test-dir build --output-on-failure \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index c11595f..d3efe7a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,12 +9,12 @@ set(MY_LIB_NAME "${MY_PROJECT_NAME}Core") project( ${MY_PROJECT_NAME} VERSION 1.0.0 - DESCRIPTION "Universal C++23 Template" + DESCRIPTION "Universal C++20 Template" LANGUAGES C CXX ) # Set global C++ standard -set(CMAKE_CXX_STANDARD 23) +set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) @@ -24,17 +24,20 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # ----------------------------------------------------------------------------- # 2. Global Options & Modules # ----------------------------------------------------------------------------- -option(BUILD_BENCHMARKS "Build performance benchmarks" OFF) -option(BUILD_TESTS "Build unit tests" ON) -option(BUILD_SHARED_LIBS "Build libraries as shared" OFF) +# option(BUILD_BENCHMARKS "Build performance benchmarks" OFF) +# option(BUILD_TESTS "Build unit tests" ON) +# option(BUILD_SHARED_LIBS "Build libraries as shared" OFF) +# option(ENABLE_CLANG_TIDY "Enable clang-tidy static analysis" ON) # Extend module path to find custom scripts in /cmake list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake") # Include Professional Tooling Modules -include(CompilerWarnings) # Sets strict warnings per compiler -include(Sanitizers) # Configures ASan/UBSan -include(StaticAnalyzers) # Configures Clang-Tidy/IWYU +include(ProjectOptions) # Global options and feature toggles +include(ProjectWarnings) # Sets strict warnings per compiler +include(StaticAnalyzers) # Configures Clang-Tidy/IWYU +include(Sanitizers) # Configures ASan/UBSan +include(ClangFormat) # Configures clang-format targets # ----------------------------------------------------------------------------- # 3. Target Orchestration @@ -70,4 +73,5 @@ message(STATUS " Compiler: ${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VER message(STATUS " Build Type: ${CMAKE_BUILD_TYPE}") message(STATUS " Benchmarks: ${BUILD_BENCHMARKS}") message(STATUS " Tests: ${BUILD_TESTS}") +message(STATUS " Clang Tidy: ${ENABLE_CLANG_TIDY}") message(STATUS "-----------------------------------------------------------") \ No newline at end of file diff --git a/CMakePresets.json b/CMakePresets.json index c02c0cb..5ce4857 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -26,7 +26,7 @@ "name": "msvc-base", "displayName": "MSVC", "hidden": true, - "generator": "Visual Studio 18 2026", + "generator": "Visual Studio 17 2022", "inherits": "vcpkg-base", "toolchainFile": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" }, @@ -39,7 +39,7 @@ "cacheVariables": { "CMAKE_C_COMPILER": "clang-cl", "CMAKE_CXX_COMPILER": "clang-cl", - "CMAKE_LINKER": "link.exe", + "CMAKE_LINKER": "lld-link.exe", "CMAKE_AR": "llvm-lib.exe" }, "environment": { @@ -86,7 +86,10 @@ }, { "name": "msvc-release", - "inherits": ["msvc-base", "benchmark-base"], + "inherits": [ + "msvc-base", + "benchmark-base" + ], "binaryDir": "${sourceDir}/build/msvc/release", "cacheVariables": { "CMAKE_BUILD_TYPE": "Release" @@ -102,7 +105,10 @@ }, { "name": "clang-cl-release", - "inherits": ["clang-cl-base", "benchmark-base"], + "inherits": [ + "clang-cl-base", + "benchmark-base" + ], "binaryDir": "${sourceDir}/build/clang-cl/release", "cacheVariables": { "CMAKE_BUILD_TYPE": "Release" @@ -118,7 +124,10 @@ }, { "name": "mingw-gcc-release", - "inherits": ["mingw-gcc", "benchmark-base"], + "inherits": [ + "mingw-gcc", + "benchmark-base" + ], "binaryDir": "${sourceDir}/build/mingw-gcc/release", "cacheVariables": { "CMAKE_BUILD_TYPE": "Release" @@ -134,7 +143,10 @@ }, { "name": "mingw-clang-release", - "inherits": ["mingw-clang", "benchmark-base"], + "inherits": [ + "mingw-clang", + "benchmark-base" + ], "binaryDir": "${sourceDir}/build/mingw-clang/release", "cacheVariables": { "CMAKE_BUILD_TYPE": "Release" @@ -150,7 +162,10 @@ }, { "name": "linux-gcc-release", - "inherits": ["linux-gcc", "benchmark-base"], + "inherits": [ + "linux-gcc", + "benchmark-base" + ], "binaryDir": "${sourceDir}/build/linux-gcc/release", "cacheVariables": { "CMAKE_BUILD_TYPE": "Release" @@ -166,7 +181,10 @@ }, { "name": "linux-clang-release", - "inherits": ["linux-clang", "benchmark-base"], + "inherits": [ + "linux-clang", + "benchmark-base" + ], "binaryDir": "${sourceDir}/build/linux-clang/release", "cacheVariables": { "CMAKE_BUILD_TYPE": "Release" diff --git a/apps/app/CMakeLists.txt b/apps/app/CMakeLists.txt index 82d534b..82bf005 100644 --- a/apps/app/CMakeLists.txt +++ b/apps/app/CMakeLists.txt @@ -8,8 +8,15 @@ add_executable(${APP_TARGET} main.cpp) target_link_libraries(${APP_TARGET} PRIVATE ${PROJECT_NAME}::Core + project_options + project_warnings + project_sanitizers ) +if(COMMAND enable_clang_tidy) + enable_clang_tidy(${MY_LIB_NAME}) +endif() + # 4. Enforce the "Flat Binary" Output Contract set_target_properties(${APP_TARGET} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin" @@ -19,5 +26,10 @@ set_target_properties(${APP_TARGET} PROPERTIES OUTPUT_NAME "app" ) -# 5. Apply your template's strict warning configuration -set_project_warnings(${APP_TARGET}) \ No newline at end of file +# 5. Auto-format before build (if enabled) +if(DEFINED AUTO_FORMAT_DEP) + add_dependencies(${APP_TARGET} ${AUTO_FORMAT_DEP}) +endif() + +# 6. Apply your template's strict warning configuration +#set_project_warnings(${APP_TARGET}) \ No newline at end of file diff --git a/apps/app/main.cpp b/apps/app/main.cpp index f37a4da..4037b7c 100644 --- a/apps/app/main.cpp +++ b/apps/app/main.cpp @@ -1,7 +1,9 @@ -#include #include "core/hello.hpp" +#include int main() { - std::cout << core::hello() << std::endl; + std::cout << core::hello() << '\n'; + return 0; + } \ No newline at end of file diff --git a/benchmarks/CMakeLists.txt b/benchmarks/CMakeLists.txt index 11c5a35..5023c83 100644 --- a/benchmarks/CMakeLists.txt +++ b/benchmarks/CMakeLists.txt @@ -10,6 +10,8 @@ add_executable(${BENCH_TARGET} bench_hello.cpp) target_link_libraries(${BENCH_TARGET} PRIVATE ${PROJECT_NAME}::Core # Use the Alias for consistency + project_options + project_warnings benchmark::benchmark ) @@ -20,4 +22,9 @@ set_target_properties(${BENCH_TARGET} PROPERTIES RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}/bin" RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_BINARY_DIR}/bin" OUTPUT_NAME "bench" -) \ No newline at end of file +) + +# 5. Auto-format before build (if enabled) +if(DEFINED AUTO_FORMAT_DEP) + add_dependencies(${BENCH_TARGET} ${AUTO_FORMAT_DEP}) +endif() \ No newline at end of file diff --git a/cmake/ClangFormat.cmake b/cmake/ClangFormat.cmake new file mode 100644 index 0000000..9305684 --- /dev/null +++ b/cmake/ClangFormat.cmake @@ -0,0 +1,40 @@ +include_guard(GLOBAL) + +option(ENABLE_AUTO_FORMAT "Run clang-format automatically before build" OFF) + +find_program(CLANG_FORMAT_EXE NAMES clang-format) + +if(CLANG_FORMAT_EXE) + +file(GLOB_RECURSE ALL_SOURCE_FILES + ${PROJECT_SOURCE_DIR}/libs/**/*.cpp + ${PROJECT_SOURCE_DIR}/libs/**/*.hpp + ${PROJECT_SOURCE_DIR}/apps/**/*.cpp + ${PROJECT_SOURCE_DIR}/apps/**/*.hpp + ${PROJECT_SOURCE_DIR}/tests/**/*.cpp + ${PROJECT_SOURCE_DIR}/tests/**/*.hpp + ${PROJECT_SOURCE_DIR}/benchmarks/**/*.cpp +) + +add_custom_target(format + COMMAND ${CLANG_FORMAT_EXE} + -i + ${ALL_SOURCE_FILES} + COMMENT "Formatting source files with clang-format" +) + +# Auto-format before build if enabled +# This sets a variable that subdirectories can use to add dependencies +if(ENABLE_AUTO_FORMAT AND CLANG_FORMAT_EXE) + # Create format-all target that depends on format + add_custom_target(format-all + COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target format + COMMENT "Running clang-format before build..." + ) + add_dependencies(format-all format) + + set(AUTO_FORMAT_DEP "format-all") + message(STATUS "Auto-format enabled: clang-format will run before build") +endif() + +endif() \ No newline at end of file diff --git a/cmake/ProjectOptions.cmake b/cmake/ProjectOptions.cmake new file mode 100644 index 0000000..a790bf1 --- /dev/null +++ b/cmake/ProjectOptions.cmake @@ -0,0 +1,36 @@ +include_guard(GLOBAL) + +option(BUILD_BENCHMARKS "Build performance benchmarks" OFF) +option(BUILD_TESTS "Build unit tests" ON) +option(BUILD_SHARED_LIBS "Build libraries as shared" OFF) +option(ENABLE_CLANG_TIDY "Enable clang-tidy static analysis" OFF) +option(ENABLE_IPO "Enable Interprocedural Optimization (LTO)" OFF) +option(ENABLE_WARNINGS_AS_ERRORS "Treat warnings as errors" OFF) +option(ENABLE_SANITIZERS "Enable sanitizers (ASan/UBSan)" OFF) + +add_library(project_options INTERFACE) + +# Require modern C++ +target_compile_features(project_options INTERFACE cxx_std_20) + +# Allow users to opt-in to C++23 features if desired +# target_compile_features(project_options INTERFACE cxx_std_23) + +# LTO / IPO +include(CheckIPOSupported) + +if(ENABLE_IPO) + check_ipo_supported(RESULT ipo_supported OUTPUT error) + + if(ipo_supported) + set_property(TARGET project_options PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) + endif() +endif() + +# warnings as errors +if(ENABLE_WARNINGS_AS_ERRORS) + target_compile_options(project_options INTERFACE + $<$:-Werror> + $<$:/WX> + ) +endif() \ No newline at end of file diff --git a/cmake/ProjectWarnings.cmake b/cmake/ProjectWarnings.cmake new file mode 100644 index 0000000..8b2bcb4 --- /dev/null +++ b/cmake/ProjectWarnings.cmake @@ -0,0 +1,25 @@ +include_guard(GLOBAL) + +add_library(project_warnings INTERFACE) + +target_compile_options(project_warnings INTERFACE + $<$: + -Wall + -Wextra + -Wpedantic + -Wconversion + -Wshadow + > + + $<$: + -Wall + -Wextra + -Wpedantic + -Wconversion + -Wshadow + > + + $<$: + /W4 + > +) \ No newline at end of file diff --git a/cmake/Sanitizers.cmake b/cmake/Sanitizers.cmake index 749f85c..f7e99bd 100644 --- a/cmake/Sanitizers.cmake +++ b/cmake/Sanitizers.cmake @@ -1,15 +1,28 @@ -option(ENABLE_SANITIZERS "Enable sanitizers" OFF) +include_guard(GLOBAL) -if(ENABLE_SANITIZERS AND NOT MSVC) +add_library(project_sanitizers INTERFACE) -add_compile_options( - -fsanitize=address - -fsanitize=undefined -) +option(ENABLE_ADDRESS_SANITIZER "Enable AddressSanitizer (ASan)" OFF) +option(ENABLE_UNDEFINED_SANITIZER "Enable UndefinedBehaviorSanitizer (UBSan)" OFF) -add_link_options( - -fsanitize=address - -fsanitize=undefined -) +# Sanitizers only work on Clang/GCC, not MSVC +if(CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU") + + if(ENABLE_ADDRESS_SANITIZER) + target_compile_options(project_sanitizers INTERFACE -fsanitize=address) + target_link_options(project_sanitizers INTERFACE -fsanitize=address) + endif() + + if(ENABLE_UNDEFINED_SANITIZER) + target_compile_options(project_sanitizers INTERFACE -fsanitize=undefined) + target_link_options(project_sanitizers INTERFACE -fsanitize=undefined) + endif() + +elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") + # MSVC has no built-in sanitizer support via command line + # Use /fsanitize=address with Clang-CL or external tools + if(ENABLE_ADDRESS_SANITIZER OR ENABLE_UNDEFINED_SANITIZER) + message(STATUS "Sanitizers not supported on MSVC. Use Clang-CL or external tooling.") + endif() endif() \ No newline at end of file diff --git a/cmake/StaticAnalyzers.cmake b/cmake/StaticAnalyzers.cmake index 3c7ee27..c0ae29d 100644 --- a/cmake/StaticAnalyzers.cmake +++ b/cmake/StaticAnalyzers.cmake @@ -1,11 +1,20 @@ -option(ENABLE_CLANG_TIDY "Enable clang-tidy" OFF) +include_guard(GLOBAL) -if(ENABLE_CLANG_TIDY) +# Note: ENABLE_CLANG_TIDY option is defined in ProjectOptions.cmake -set(CMAKE_CXX_CLANG_TIDY - clang-tidy; - -checks=*; - -warnings-as-errors=* -) +function(enable_clang_tidy target) -endif() \ No newline at end of file + if(NOT ENABLE_CLANG_TIDY) + return() + endif() + + find_program(CLANG_TIDY_EXE NAMES clang-tidy) + + if(CLANG_TIDY_EXE) + set_target_properties(${target} PROPERTIES + CXX_CLANG_TIDY + "${CLANG_TIDY_EXE};-checks=*;-warnings-as-errors=*" + ) + endif() + +endfunction() \ No newline at end of file diff --git a/libs/core/CMakeLists.txt b/libs/core/CMakeLists.txt index c37b818..9332c22 100644 --- a/libs/core/CMakeLists.txt +++ b/libs/core/CMakeLists.txt @@ -2,6 +2,19 @@ add_library(${MY_LIB_NAME} src/hello.cpp) add_library(${PROJECT_NAME}::Core ALIAS ${MY_LIB_NAME}) +# --- Link to Global Options, Warnings, and Sanitizers --- +target_link_libraries(${MY_LIB_NAME} + PRIVATE + project_options + project_warnings + project_sanitizers +) + +# --- Clang-Tidy Integration --- +if(COMMAND enable_clang_tidy) + enable_clang_tidy(${MY_LIB_NAME}) +endif() + # --- Include Directories --- target_include_directories(${MY_LIB_NAME} PUBLIC @@ -9,6 +22,11 @@ target_include_directories(${MY_LIB_NAME} $ ) +# --- Auto-format before build (if enabled) --- +if(DEFINED AUTO_FORMAT_DEP) + add_dependencies(${MY_LIB_NAME} ${AUTO_FORMAT_DEP}) +endif() + # --- Compiler Tooling --- # Assuming your include(CompilerWarnings) defines this function -set_project_warnings(${MY_LIB_NAME}) \ No newline at end of file +#set_project_warnings(${MY_LIB_NAME}) \ No newline at end of file diff --git a/libs/core/include/core/hello.hpp b/libs/core/include/core/hello.hpp index ea9ba94..e2bf9f7 100644 --- a/libs/core/include/core/hello.hpp +++ b/libs/core/include/core/hello.hpp @@ -4,4 +4,4 @@ namespace core { std::string hello(); -} \ No newline at end of file +} // namespace core \ No newline at end of file diff --git a/libs/core/src/hello.cpp b/libs/core/src/hello.cpp index b45d470..cd24b98 100644 --- a/libs/core/src/hello.cpp +++ b/libs/core/src/hello.cpp @@ -1,11 +1,10 @@ -#include "core/hello.hpp" +#include +#include -namespace core -{ +namespace core { -std::string hello() -{ +std::string hello() { return "Hello from core library"; } -} \ No newline at end of file +} // namespace core \ No newline at end of file diff --git a/scripts/build.bat b/scripts/build.bat index b4359e2..eb6bfe5 100644 --- a/scripts/build.bat +++ b/scripts/build.bat @@ -8,8 +8,15 @@ if /i "%~2"=="Release" set "CONFIG=Release" set "BASE_PRESET=msvc" if not "%~1"=="" set "BASE_PRESET=%~1" +:: Enable auto-format if requested (3rd argument) +set "AUTO_FORMAT=OFF" +if /i "%~3"=="ON" set "AUTO_FORMAT=ON" + +:: Only msvc and clang-cl are supported in this script (native Windows tools) +:: For mingw presets, use ucrt64 shell environment if /i "%BASE_PRESET%" neq "msvc" if /i "%BASE_PRESET%" neq "clang-cl" ( echo [ERROR] "%BASE_PRESET%" is not a native Windows preset. + echo Use ucrt64 shell for mingw-gcc/mingw-clang presets. exit /b 1 ) @@ -45,7 +52,7 @@ echo [BUILD] %TARGET_PRESET% ^(%CONFIG%^) echo ────────────────────────────────────────────── :: Using the 'Flat Binary' contract for the bench check -cmake --preset "%TARGET_PRESET%" || exit /b !ERRORLEVEL! +cmake --preset "%TARGET_PRESET%" -DENABLE_AUTO_FORMAT=%AUTO_FORMAT% || exit /b !ERRORLEVEL! cmake --build "%BUILD_DIR%" --config %CONFIG% --parallel || exit /b !ERRORLEVEL! ctest --test-dir "%BUILD_DIR%" -C %CONFIG% --output-on-failure diff --git a/scripts/build.sh b/scripts/build.sh index 0ec4003..f06fb61 100644 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -11,6 +11,7 @@ fi BASE_PRESET="${1:-$DEFAULT_PRESET}" CONFIG="${2:-Debug}" +AUTO_FORMAT="${3:-OFF}" # Normalize to lowercase for directory and preset matching CONFIG_LOWER=$(echo "$CONFIG" | tr '[:upper:]' '[:lower:]') @@ -39,7 +40,7 @@ echo "──────────────────────── # 3. Configure echo "[STEP 1/3] Configuring preset: $TARGET_PRESET" -cmake --preset "$TARGET_PRESET" +cmake --preset "$TARGET_PRESET" -DENABLE_AUTO_FORMAT=$AUTO_FORMAT # 4. Build echo "[STEP 2/3] Building $CONFIG..." diff --git a/scripts/build_all.bat b/scripts/build_all.bat index ffd82ea..1fdb839 100644 --- a/scripts/build_all.bat +++ b/scripts/build_all.bat @@ -1,12 +1,18 @@ @echo off setlocal EnableDelayedExpansion -:: 1. Define the Windows Matrix +:: 1. Define the Windows Matrix (native tools only - msvc/clang-cl) +:: For mingw builds, use ucrt64 shell with build.sh set "COMPILERS=msvc clang-cl" set "CONFIGS=Debug Release" +:: Auto-format support (pass as argument, e.g., build_all.bat ON) +set "AUTO_FORMAT=OFF" +if /i "%~1"=="ON" set "AUTO_FORMAT=ON" + echo ================================================= echo [MASTER BUILD] Testing all Windows Configurations +echo [AUTO_FORMAT=%AUTO_FORMAT%] echo ================================================= :: 2. Execution Loop @@ -20,7 +26,7 @@ for %%c in (%COMPILERS%) do ( :: %~dp0 is the directory of THIS script. :: We wrap it in quotes to handle spaces in folder names. if exist "%~dp0build.bat" ( - call "%~dp0build.bat" %%c %%g + call "%~dp0build.bat" %%c %%g %AUTO_FORMAT% ) else ( echo [ERROR] Could not find build.bat in %~dp0 exit /b 1 diff --git a/scripts/build_all.sh b/scripts/build_all.sh index 4674806..74e7ec2 100644 --- a/scripts/build_all.sh +++ b/scripts/build_all.sh @@ -16,6 +16,9 @@ fi # 2. Define the Matrix CONFIGS=("Debug" "Release") +# Auto-format support (pass as argument, e.g., ./build_all.sh ON) +AUTO_FORMAT="${1:-OFF}" + if [ "$IS_MSYS" = true ]; then PRESETS=("mingw-gcc" "mingw-clang") else @@ -36,7 +39,7 @@ for preset in "${PRESETS[@]}"; do echo "⚒️ Building Node: $preset | $config" # Use SCRIPT_DIR to find build.sh reliably - bash "$SCRIPT_DIR/build.sh" "$preset" "$config" + bash "$SCRIPT_DIR/build.sh" "$preset" "$config" "$AUTO_FORMAT" echo "✅ Finished: $preset-$config" done diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index d479740..6fb069f 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -10,6 +10,9 @@ add_executable(${TEST_TARGET} test_hello.cpp) target_link_libraries(${TEST_TARGET} PRIVATE ${PROJECT_NAME}::Core # <--- Project-agnostic Alias + project_options + project_warnings + project_sanitizers GTest::gtest_main ) @@ -33,5 +36,7 @@ gtest_discover_tests(${TEST_TARGET} EXTRA_ARGS --gtest_color=yes ) -# 6. Apply Template Warnings -set_project_warnings(${TEST_TARGET}) \ No newline at end of file +# 6. Auto-format before build (if enabled) +if(DEFINED AUTO_FORMAT_DEP) + add_dependencies(${TEST_TARGET} ${AUTO_FORMAT_DEP}) +endif() diff --git a/tests/test_hello.cpp b/tests/test_hello.cpp index 22fb402..a99f5b6 100644 --- a/tests/test_hello.cpp +++ b/tests/test_hello.cpp @@ -1,7 +1,8 @@ -#include #include "core/hello.hpp" +#include +#include TEST(CoreTest, Hello) { - EXPECT_EQ(core::hello(), "Hello from core library"); + EXPECT_EQ(core::hello(), std::string("Hello from core library")); } \ No newline at end of file diff --git a/vcpkg.json b/vcpkg.json index e10d5da..c37e8db 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -4,6 +4,6 @@ "builtin-baseline": "1e199d32ad53aab1defda61ce41c380302e3f95c", "dependencies": [ "gtest", - "google-benchmark" + "benchmark" ] } \ No newline at end of file