This is an automated email from the ASF dual-hosted git repository. pnoltes pushed a commit to branch feature/566-introduce-clang-tidy-setup in repository https://gitbox.apache.org/repos/asf/celix.git
commit 003b66f2e032b8f35a843053f236be20b95213d8 Author: Pepijn Noltes <[email protected]> AuthorDate: Tue Feb 10 08:41:36 2026 +0100 gh-566: Introduce clang-tidy setup Also remove gcc nested functione example --- .clang-tidy | 144 +++++++++++++++++++++ .github/workflows/ubuntu.yml | 2 + cmake/celix_project/CelixProject.cmake | 67 ++++++---- conanfile.py | 8 +- .../services_example_c/CMakeLists.txt | 4 - libs/error_injector/api/celix_error_injector.h | 3 + 6 files changed, 196 insertions(+), 32 deletions(-) diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 000000000..f7e376801 --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,144 @@ +# 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, + -cert-dcl59-cpp +WarningsAsErrors: '*' +HeaderFilterRegex: '.*' +#HeaderFilterRegex: '(bundles|libs|misc)/.*' +FormatStyle: file +SystemHeaders: false +... diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml index 640d34552..1b8e5ae8e 100644 --- a/.github/workflows/ubuntu.yml +++ b/.github/workflows/ubuntu.yml @@ -81,6 +81,7 @@ jobs: -o celix/*:enable_testing_on_ci=True -o celix/*:framework_curlinit=False -o celix/*:enable_ccache=True + -o celix/*:enable_clang_tidy=${{ (matrix.type == 'RelWithDebInfo' && matrix.compiler[0] == 'clang') && 'True' || 'False' }} run: | conan build . -c tools.cmake.cmaketoolchain:generator=Ninja -pr:b release -pr:h default -of build ${CONAN_BUILD_OPTIONS} -b missing - name: Test @@ -106,6 +107,7 @@ jobs: sudo apt-get install -yq --no-install-recommends \ build-essential \ ninja-build \ + clang-tidy \ curl \ uuid-dev \ libzip-dev \ diff --git a/cmake/celix_project/CelixProject.cmake b/cmake/celix_project/CelixProject.cmake index cec2ec133..e3ebc7cc4 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,35 +78,45 @@ 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}) - else() - message(WARNING "ENABLE_GCC_ANALYZER is only supported with GCC ") - endif() + else() + message(WARNING "ENABLE_GCC_ANALYZER is only supported with GCC ") + endif() endif() diff --git a/conanfile.py b/conanfile.py index 104a9e52a..099a77c2e 100644 --- a/conanfile.py +++ b/conanfile.py @@ -47,6 +47,8 @@ class CelixConan(ConanFile): "enable_address_sanitizer": False, "enable_undefined_sanitizer": False, "enable_thread_sanitizer": False, + "enable_clang_tidy": False, + "clang_tidy_warnings_as_errors": True, "enable_fuzzing": False, "enable_benchmarking": False, "install_find_modules": False, @@ -94,8 +96,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 +159,8 @@ class CelixConan(ConanFile): 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 + del self.info.options.clang_tidy_warnings_as_errors 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 <dlfcn.h> #include <stddef.h> +//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 }
