From 33162236293efaaa659f74310772d8d75e8f1590 Mon Sep 17 00:00:00 2001 From: Chris Thrasher Date: Sun, 25 Aug 2024 12:47:43 -0600 Subject: [PATCH] Add `tidy` target for running clang-tidy --- .clang-tidy | 10 ++++++++++ .github/workflows/ci.yml | 35 +++++++++++++++++++++++++++++++++++ CMakeLists.txt | 10 ++++++++++ cmake/Tidy.cmake | 34 ++++++++++++++++++++++++++++++++++ src/CSFML/Internal.hpp | 26 +++++++++++++------------- 5 files changed, 102 insertions(+), 13 deletions(-) create mode 100644 .clang-tidy create mode 100644 cmake/Tidy.cmake diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 0000000..f167698 --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,10 @@ +Checks: > + bugprone-*, + clang-analyzer-*, + -bugprone-easily-swappable-parameters, + -bugprone-narrowing-conversions, + -clang-analyzer-core.NonNullParamChecker, + -clang-analyzer-security.insecureAPI.strcpy, +HeaderFilterRegex: '.*' +WarningsAsErrors: '*' +UseColor: true diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 72ae0d8..a8abb65 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -68,3 +68,38 @@ jobs: - name: Test run: ctest --test-dir CSFML/build -C ${{matrix.type.name}} --output-on-failure + + tidy: + name: Analyze + runs-on: macos-14 + + steps: + - name: Install Dependencies + run: | + brew update + brew install llvm ninja + echo /opt/homebrew/opt/llvm/bin >> $GITHUB_PATH + + - name: Checkout SFML + uses: actions/checkout@v4 + with: + repository: SFML/SFML + ref: master + path: SFML + + - name: Configure SFML CMake + run: cmake -S SFML -B SFML/build -GNinja -DCMAKE_INSTALL_PREFIX=SFML/install -DBUILD_SHARED_LIBS=TRUE -DCMAKE_BUILD_TYPE=Debug + + - name: Build SFML + run: cmake --build SFML/build --target install + + - name: Checkout CSFML + uses: actions/checkout@v4 + with: + path: CSFML + + - name: Configure CSFML CMake + run: cmake -S CSFML -B CSFML/build -DBUILD_SHARED_LIBS=TRUE -DCSFML_BUILD_EXAMPLES=TRUE -DCSFML_BUILD_TEST_SUITE=TRUE -DSFML_DIR=$GITHUB_WORKSPACE/SFML/install/lib/cmake/SFML -DCMAKE_BUILD_TYPE=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS=TRUE + + - name: Tidy + run: cmake --build CSFML/build --target tidy diff --git a/CMakeLists.txt b/CMakeLists.txt index 601d73b..248d9df 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -95,6 +95,11 @@ install(DIRECTORY include/ install(FILES license.md DESTINATION ${INSTALL_MISC_DIR}) install(FILES readme.md DESTINATION ${INSTALL_MISC_DIR}) +# stop configuration if consuming CSFML as a subdirectory +if(NOT PROJECT_IS_TOP_LEVEL) + return() +endif() + # add an option for building the examples csfml_set_option(CSFML_BUILD_EXAMPLES FALSE BOOL "TRUE to build the CSFML examples, FALSE to ignore them") if(CSFML_BUILD_EXAMPLES) @@ -107,3 +112,8 @@ if(CSFML_BUILD_TEST_SUITE) enable_testing() add_subdirectory(test) endif() + +csfml_set_option(CLANG_TIDY_EXECUTABLE clang-tidy STRING "Override clang-tidy executable, requires minimum version 14") +add_custom_target(tidy + COMMAND ${CMAKE_COMMAND} -DCLANG_TIDY_EXECUTABLE=${CLANG_TIDY_EXECUTABLE} -DPROJECT_BINARY_DIR=${PROJECT_BINARY_DIR} -P ./cmake/Tidy.cmake + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} VERBATIM) diff --git a/cmake/Tidy.cmake b/cmake/Tidy.cmake new file mode 100644 index 0000000..31b509f --- /dev/null +++ b/cmake/Tidy.cmake @@ -0,0 +1,34 @@ +# Check executable exists +if(NOT EXISTS ${CLANG_TIDY_EXECUTABLE}) + find_program(CLANG_TIDY_EXEC_TEMP ${CLANG_TIDY_EXECUTABLE}) + if(CLANG_TIDY_EXEC_TEMP) + set(CLANG_TIDY_EXECUTABLE ${CLANG_TIDY_EXEC_TEMP}) + unset(CLANG_TIDY_EXEC_TEMP) + else() + message(FATAL_ERROR "Unable to find clang-tidy executable: \"${CLANG_TIDY_EXECUTABLE}\"") + endif() +endif() + +# Check executable version +execute_process(COMMAND ${CLANG_TIDY_EXECUTABLE} --version OUTPUT_VARIABLE CLANG_TIDY_VERSION) +string(REGEX MATCH "version ([0-9]+)" CLANG_TIDY_VERSION ${CLANG_TIDY_VERSION}) +unset(CLANG_TIDY_VERSION) +if(CMAKE_MATCH_1 GREATER_EQUAL 14) + message(STATUS "Using clang-tidy version ${CMAKE_MATCH_1}") +else() + message(FATAL_ERROR "clang-tidy version ${CMAKE_MATCH_1} is too low") +endif() + +# Find Python and run-clang-tidy script +find_package(Python 3 REQUIRED) + +find_program(RUN_CLANG_TIDY run-clang-tidy) +if(NOT RUN_CLANG_TIDY) + message(FATAL_ERROR "Failed to find run-clang-tidy script") +endif() + +# Run +execute_process(COMMAND ${Python_EXECUTABLE} ${RUN_CLANG_TIDY} -clang-tidy-binary ${CLANG_TIDY_EXECUTABLE} -quiet -p ${PROJECT_BINARY_DIR} RESULTS_VARIABLE EXIT_CODE) +if(NOT EXIT_CODE STREQUAL 0) + message(FATAL_ERROR "Analysis failed") +endif() diff --git a/src/CSFML/Internal.hpp b/src/CSFML/Internal.hpp index 97b51c0..7384463 100644 --- a/src/CSFML/Internal.hpp +++ b/src/CSFML/Internal.hpp @@ -36,7 +36,7 @@ #define CSFML_CHECK(object_) \ do \ { \ - if (object_ == nullptr) \ + if ((object_) == nullptr) \ { \ sf::err() << "SFML warning: trying to use a null " #object_ " object\n"; \ return; \ @@ -49,7 +49,7 @@ { \ if (object_) \ { \ - (object_->This.function_); \ + ((object_)->This.function_); \ } \ else \ { \ @@ -63,7 +63,7 @@ { \ if (object_) \ { \ - (object_->This->function_); \ + ((object_)->This->function_); \ } \ else \ { \ @@ -75,7 +75,7 @@ #define CSFML_CHECK_RETURN(object_, default_) \ do \ { \ - if (object_ == nullptr) \ + if ((object_) == nullptr) \ { \ sf::err() << "SFML warning: trying to use a null " #object_ " object\n"; \ return default_; \ @@ -86,7 +86,7 @@ #define CSFML_CALL_RETURN(object_, function_, default_) \ if (object_) \ { \ - return (object_->This.function_); \ + return ((object_)->This.function_); \ } \ else \ { \ @@ -97,7 +97,7 @@ #define CSFML_CALL_PTR_RETURN(object_, function_, default_) \ if (object_) \ { \ - return (object_->This->function_); \ + return ((object_)->This->function_); \ } \ else \ { \ @@ -110,24 +110,24 @@ #define CSFML_CHECK(object_) #define CSFML_CALL(object_, function_) \ - (object_->This.function_) + ((object_)->This.function_) #define CSFML_CALL_PTR(object_, function_) \ - (object_->This->function_) + ((object_)->This->function_) #define CSFML_CHECK_RETURN(object_, default_) \ - (void)default_; + (void)(default_); #define CSFML_CALL_RETURN(object_, function_, default_) \ { \ - (void)default_; \ - return (object_->This.function_); \ + (void)(default_); \ + return ((object_)->This.function_); \ } #define CSFML_CALL_PTR_RETURN(object_, function_, default_) \ { \ - (void)default_; \ - return (object_->This->function_); \ + (void)(default_); \ + return ((object_)->This->function_); \ } #endif