diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 000000000..6530f77cf --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,146 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +--- +Checks: > + clang-analyzer-*, + cert-*, + cppcoreguidelines-*, + hicpp-* + bugprone-*, + performance-*, + readability-*, + -clang-diagnostic-unknown-warning-option, + -clang-analyzer-security.ArrayBound, + -clang-analyzer-unix.Stream, + -clang-analyzer-cplusplus.StringChecker, + -clang-analyzer-optin.portability.UnixAPI, + -clang-analyzer-security.insecureAPI.rand, + -clang-analyzer-cplusplus.NewDeleteLeaks, + -clang-analyzer-core.UndefinedBinaryOperatorResult, + -clang-analyzer-core.NonNullParamChecker, + -clang-analyzer-unix.StdCLibraryFunctions, + -readability-identifier-naming, + -readability-magic-numbers, + -readability-else-after-return, + -readability-non-const-parameter, + -readability-identifier-length, + -readability-uppercase-literal-suffix, + -readability-redundant-declaration, + -readability-function-cognitive-complexity, + -readability-avoid-const-params-in-decls, + -readability-inconsistent-declaration-parameter-name, + -readability-avoid-unconditional-preprocessor-if, + -readability-named-parameter, + -readability-function-size, + -readability-avoid-nested-conditional-operator, + -readability-braces-around-statements, + -readability-implicit-bool-conversion, + -readability-redundant-member-init, + -readability-convert-member-functions-to-static, + -readability-isolate-declaration, + -readability-container-data-pointer, + -readability-redundant-inline-specifier, + -readability-suspicious-call-argument, + -readability-use-concise-preprocessor-directives, + -readability-make-member-function-const, + -readability-static-definition-in-anonymous-namespace, + -readability-qualified-auto, + -readability-qualified-auto, + -readability-duplicate-include, + -readability-redundant-casting, + -readability-simplify-boolean-expr, + -readability-redundant-control-flow, + -readability-misleading-indentation, + -readability-math-missing-parentheses, + -bugprone-narrowing-conversions, + -bugprone-easily-swappable-parameters, + -bugprone-macro-parentheses, + -bugprone-branch-clone, + -cppcoreguidelines-pro-type-union-access, + -cppcoreguidelines-avoid-magic-numbers, + -cppcoreguidelines-init-variables, + -cppcoreguidelines-narrowing-conversions, + -cppcoreguidelines-avoid-non-const-global-variables, + -cppcoreguidelines-macro-to-enum, + -cppcoreguidelines-macro-usage, + -cppcoreguidelines-pro-type-vararg, + -cppcoreguidelines-pro-type-union-access, + -cppcoreguidelines-owning-memory, + -cppcoreguidelines-no-malloc, + -cppcoreguidelines-prefer-member-initializer, + -cppcoreguidelines-non-private-member-variables-in-classes, + -cppcoreguidelines-pro-type-cstyle-cast, + -cppcoreguidelines-special-member-functions, + -cppcoreguidelines-pro-bounds-array-to-pointer-decay, + -cppcoreguidelines-avoid-c-arrays, + -cppcoreguidelines-avoid-do-while, + -cppcoreguidelines-avoid-goto, + -cppcoreguidelines-use-enum-class, + -cppcoreguidelines-pro-bounds-pointer-arithmetic, + -cppcoreguidelines-interfaces-global-init, + -cppcoreguidelines-pro-bounds-constant-array-index, + -cppcoreguidelines-pro-type-member-init, + -cppcoreguidelines-rvalue-reference-param-not-moved, + -cppcoreguidelines-missing-std-forward, + -cppcoreguidelines-use-default-member-init, + -cppcoreguidelines-virtual-class-destructor, + -cppcoreguidelines-avoid-const-or-ref-data-members, + -cppcoreguidelines-pro-type-const-cast, + -cppcoreguidelines-avoid-const-or-ref-data-members, + -cppcoreguidelines-explicit-virtual-functions, + -performance-type-promotion-in-math-fn, + -performance-unnecessary-value-param, + -performance-noexcept-move-constructor, + -performance-unnecessary-copy-initialization, + -performance-for-range-copy, + -performance-enum-size, + -performance-avoid-endl, + -performance-move-const-arg, + -performance-noexcept-move-constructor, + -performance-inefficient-vector-operation, + -performance-no-int-to-ptr, + -clang-analyzer-unix.Malloc, + -clang-analyzer-core.NullDereference, + -clang-analyzer-security.insecureAPI.strcpy, + -clang-analyzer-core.CallAndMessage, + -clang-analyzer-optin.core.EnumCastOutOfRange, + -clang-analyzer-deadcode.DeadStores, + -cert-dcl37-c, + -cert-dcl16-c, + -cert-err33-c, + -cert-err34-c, + -cert-exp42-c, + -cert-flp37-c, + -cert-msc24-c, + -cert-msc30-c, + -cert-msc32-c, + -cert-msc33-c, + -cert-env33-c, + -cert-str34-c, + -cert-dcl51-cpp, + -cert-dcl50-cpp, + -cert-msc50-cpp, + -cert-msc51-cpp +# TODO re-enable check suppression (disabled to trigger check results in the GitHub Sarif report) +# -cert-dcl59-cpp +WarningsAsErrors: "*" +FormatStyle: file +#Note SystemHeaders not supported on ubuntu 22.04 ci (clang-tidy version 14.0), using header filter regex instead +#HeaderFilterRegex: ".*" +#SystemHeaders: false +HeaderFilterRegex: "(bundles|libs|misc).*" +... diff --git a/.github/workflows/clang-tidy-scan.yml b/.github/workflows/clang-tidy-scan.yml new file mode 100644 index 000000000..79681e75d --- /dev/null +++ b/.github/workflows/clang-tidy-scan.yml @@ -0,0 +1,85 @@ +name: Celix clang-tidy Scan + +on: + push: + pull_request: + schedule: + - cron: '0 0 * * *' + +env: + CONAN_USER_HOME: "${{ github.workspace }}/release/" + CONAN_USER_HOME_SHORT: "${{ github.workspace }}/release/short" + CONAN_HOME: "${{ github.workspace }}/release/" + CC: gcc + CXX: g++ + +jobs: + + clang-tidy-scan: + runs-on: ubuntu-22.04 + timeout-minutes: 120 + steps: + - name: Checkout source code + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c #v3.3.0 + - name: Install build dependencies + run: | + sudo pip install -U conan + sudo apt-get install -yq --no-install-recommends ninja-build clang-tidy + - name: Setup Conan Profile + run: | + # build profile + conan profile detect -f --name release + sed -i 's/compiler.cppstd=gnu14/compiler.cppstd=gnu17/g' `conan profile path release` + echo "[tool_requires]" >> `conan profile path release` + echo "cmake/3.26.4" >> `conan profile path release` + + # host profile + conan profile detect -f + sed -i 's/build_type=Release/build_type=RelWithDebInfo/g' `conan profile path default` + sed -i 's/compiler.cppstd=gnu14/compiler.cppstd=gnu17/g' `conan profile path default` + echo "[tool_requires]" >> `conan profile path default` + echo "cmake/3.26.4" >> `conan profile path default` + - name: Conan Cache + id: cache-conan + uses: actions/cache@d4323d4df104b026a6aa633fdb11d772146be0bf #v4.2.2 + env: + cache-name: cache-conan2-modules + with: + path: ${{ env.CONAN_HOME }} + key: ${{ runner.os }}-test-builder-${{ env.cache-name }}-gcc-RelWithDebInfo-clang-tidy-${{ hashFiles('conanfile.py') }} + restore-keys: ${{ runner.os }}-test-builder-${{ env.cache-name }}-gcc-RelWithDebInfo- + - name: Install Dependencies and configure CMake + env: + CONAN_BUILD_OPTIONS: | + -o celix/*:enable_testing=True + -o celix/*:enable_benchmarking=True + -o celix/*:build_all=True + run: | + conan install . -c tools.cmake.cmaketoolchain:generator=Ninja -pr:b release -pr:h default -of build ${CONAN_BUILD_OPTIONS} -b missing + #CMake configure -> generate build/compile_commands.json + cmake --preset conan-relwithdebinfo +# Note action cargo-bins/cargo-binstall not allowed ("all actions must be from a repository owned by your enterprise, created by GitHub, verified in the GitHub Marketplace, or match one of the patterns:...") +# - name: Setup Rust Tools (binary install) +# uses: cargo-bins/cargo-binstall@ec80feb9e330418e014932e5982599255eff6dbb #v1.17.4 +# - name: Install SARIF Tools +# run: cargo binstall -y clang-tidy-sarif + - name: Install clang-tidy SARIF tool via Curl + run: | + VERSION="v0.8.0" + TARGET="x86_64-unknown-linux-gnu" + curl -sSL "https://github.com/psastras/sarif-rs/releases/download/clang-tidy-sarif-${VERSION}/clang-tidy-sarif-${TARGET}" -o clang-tidy-sarif + chmod +x clang-tidy-sarif + - name: Run clang-tidy + run: | + set -o pipefail + run-clang-tidy -p build -quiet | tee clang-tidy-report.txt + - name: Convert clang-tidy output to SARIF + if: always() +# run: cat clang-tidy-report.txt | clang-tidy-sarif > clang-tidy-report.sarif + run: cat clang-tidy-report.txt | ./clang-tidy-sarif > clang-tidy-report.sarif + - name: upload SARIF report + uses: github/codeql-action/upload-sarif@45cbd0c69e560cd9e7cd7f8c32362050c9b7ded2 #4.32.2 + if: always() + with: + sarif_file: clang-tidy-report.sarif + category: clang-tidy diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml index 640d34552..ed4f6c41c 100644 --- a/.github/workflows/ubuntu.yml +++ b/.github/workflows/ubuntu.yml @@ -151,7 +151,7 @@ jobs: mkdir build install cd build cmake ${BUILD_OPTIONS} -DCMAKE_INSTALL_PREFIX=../install .. - ninja -j8 + ninja -j8 ninja install - name: Test run: | diff --git a/cmake/celix_project/CelixProject.cmake b/cmake/celix_project/CelixProject.cmake index bd7e7f29d..221416fde 100644 --- a/cmake/celix_project/CelixProject.cmake +++ b/cmake/celix_project/CelixProject.cmake @@ -18,12 +18,17 @@ option(ENABLE_ADDRESS_SANITIZER "Enabled building with address sanitizer. Note for gcc libasan must be installed," OFF) option(ENABLE_UNDEFINED_SANITIZER "Enabled building with undefined behavior sanitizer." OFF) option(ENABLE_THREAD_SANITIZER "Enabled building with thread sanitizer." OFF) -option (ENABLE_GCC_ANALYZER "Enable building with GCC static analyzer." OFF ) +option(ENABLE_GCC_ANALYZER "Enable building with GCC static analyzer." OFF ) +option(ENABLE_CLANG_TIDY "Enable clang-tidy during build" OFF) + # Clear "Advanced" flag for sanitizer options mark_as_advanced(CLEAR ENABLE_ADDRESS_SANITIZER) mark_as_advanced(CLEAR ENABLE_UNDEFINED_SANITIZER) mark_as_advanced(CLEAR ENABLE_THREAD_SANITIZER) +# Enable generation of compile_commands.json +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + if (ENABLE_ADDRESS_SANITIZER) set(UBSAN_SAN "") if (ENABLE_UNDEFINED_SANITIZER) @@ -73,29 +78,39 @@ elseif (ENABLE_THREAD_SANITIZER) set(CMAKE_CXX_FLAGS "-fsanitize=thread ${CMAKE_CXX_FLAGS}") endif() -if (ENABLE_GCC_ANALYZER) - if("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU") - set(ANALYZER_FLAGS - "-fanalyzer" - "-Wno-analyzer-too-complex" - "-Wno-analyzer-double-fclose" +if (ENABLE_CLANG_TIDY) + find_program(CLANG_TIDY_EXE NAMES clang-tidy) + if (CLANG_TIDY_EXE) + set(CMAKE_C_CLANG_TIDY ${CLANG_TIDY_EXE}) + set(CMAKE_CXX_CLANG_TIDY ${CLANG_TIDY_EXE}) + else() + message(FATAL_ERROR "ENABLE_CLANG_TIDY is ON, but clang-tidy was not found.") + endif() +endif () + +if (ENABLE_GCC_ANALYZER) + if("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU") + set(ANALYZER_FLAGS + "-fanalyzer" + "-Wno-analyzer-too-complex" + "-Wno-analyzer-double-fclose" "-Wno-analyzer-double-free" - "-Wno-analyzer-deref-before-check" - "-Wno-analyzer-exposure-through-output-file" - "-Wno-analyzer-file-leak" - "-Wno-analyzer-free-of-non-heap" - "-Wno-analyzer-malloc-leak" - "-Wno-analyzer-possible-null-argument" - "-Wno-analyzer-possible-null-dereference" - "-Wno-analyzer-null-argument" - "-Wno-analyzer-null-dereference" - "-Wno-analyzer-stale-setjmp-buffer" - "-Wno-analyzer-tainted-array-index" - "-Wno-analyzer-unsafe-call-within-signal-handler" - "-Wno-analyzer-use-after-free" + "-Wno-analyzer-deref-before-check" + "-Wno-analyzer-exposure-through-output-file" + "-Wno-analyzer-file-leak" + "-Wno-analyzer-free-of-non-heap" + "-Wno-analyzer-malloc-leak" + "-Wno-analyzer-possible-null-argument" + "-Wno-analyzer-possible-null-dereference" + "-Wno-analyzer-null-argument" + "-Wno-analyzer-null-dereference" + "-Wno-analyzer-stale-setjmp-buffer" + "-Wno-analyzer-tainted-array-index" + "-Wno-analyzer-unsafe-call-within-signal-handler" + "-Wno-analyzer-use-after-free" "-Wno-analyzer-use-of-pointer-in-stale-stack-frame" - "-Wno-analyzer-use-of-uninitialized-value" - "-Wno-analyzer-fd-leak" + "-Wno-analyzer-use-of-uninitialized-value" + "-Wno-analyzer-fd-leak" "-Wno-analyzer-shift-count-negative" ) add_compile_options("$<$:${ANALYZER_FLAGS}>") diff --git a/conanfile.py b/conanfile.py index 104a9e52a..d8b87c6e5 100644 --- a/conanfile.py +++ b/conanfile.py @@ -47,6 +47,7 @@ class CelixConan(ConanFile): "enable_address_sanitizer": False, "enable_undefined_sanitizer": False, "enable_thread_sanitizer": False, + "enable_clang_tidy": False, "enable_fuzzing": False, "enable_benchmarking": False, "install_find_modules": False, @@ -94,8 +95,8 @@ class CelixConan(ConanFile): "framework_curlinit": True, "enable_ccache": False, "enable_deprecated_warnings": False, - "enable_gcc_analyzer": False , - + "enable_gcc_analyzer": False , + } options = { "celix_err_buffer_size": ["ANY"], @@ -157,6 +158,7 @@ def package_id(self): del self.info.options.enable_fuzzing del self.info.options.enable_code_coverage del self.info.options.enable_gcc_analyzer + del self.info.options.enable_clang_tidy def build_requirements(self): if self.options.enable_testing: diff --git a/examples/celix-examples/services_example_c/CMakeLists.txt b/examples/celix-examples/services_example_c/CMakeLists.txt index bf2ec605e..0ef7b088b 100644 --- a/examples/celix-examples/services_example_c/CMakeLists.txt +++ b/examples/celix-examples/services_example_c/CMakeLists.txt @@ -45,10 +45,6 @@ add_celix_bundle(dynamic_consumer_example ) target_link_libraries(dynamic_consumer_example PRIVATE services_example_c_api) -if ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU") - target_compile_definitions(dynamic_consumer_example PRIVATE USE_NESTED_FUNCTION_EXAMPLE) -endif() - add_celix_container(services_example_c GROUP c_examples BUNDLES diff --git a/libs/error_injector/api/celix_error_injector.h b/libs/error_injector/api/celix_error_injector.h index 092c47eb4..b1b39b7c8 100644 --- a/libs/error_injector/api/celix_error_injector.h +++ b/libs/error_injector/api/celix_error_injector.h @@ -29,6 +29,8 @@ extern "C" { #include #include +//NOLINTBEGIN + /** * @brief This macro find the address of target function's caller, or caller's caller. * The level argument is number of frames to scan up the call stack: 0 means caller, 1 means caller's caller. @@ -105,6 +107,7 @@ do { } \ } while(0) +//NOLINTEND #ifdef __cplusplus }