From f48a34942356f95968c5f2e7b9064784c0a99115 Mon Sep 17 00:00:00 2001 From: Balakrishna Avulapati Date: Mon, 23 Jun 2025 18:49:05 +0530 Subject: [PATCH 1/8] style(clang-tidy): modularize clang-tidy config Read blogs and played around with [CMAKE_CXX_CLANG_TIDY](https://cmake.org/cmake/help/latest/variable/CMAKE_LANG_CLANG_TIDY.html). Also read source code to understand the clang-tidy config of chromium, llvm and other projects. We can provide complete context including headers to the clang-tidy tool for static analyzer by running it while building the code. This also makes static analysis first-class citizen of the project, reporting errors before making commits. For example, `misc-internal-linkage` check was reporting mostly false positives prior to this. With this, it also considered the headers, where methods/functions were declared constant. Refer #1752 And we should also incrementally add the checks. Signed-off-by: Balakrishna Avulapati --- .clang-tidy | 4 + CMakeLists.txt | 17 ++-- cmake/common/targets/clang-tidy.cmake | 130 ------------------------- cmake/common/targets/clang-tidy.config | 22 ----- src/.clang-tidy | 6 ++ 5 files changed, 20 insertions(+), 159 deletions(-) create mode 100644 .clang-tidy delete mode 100644 cmake/common/targets/clang-tidy.cmake delete mode 100644 cmake/common/targets/clang-tidy.config create mode 100644 src/.clang-tidy diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 000000000..785cb2991 --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,4 @@ +--- +# See https://clang.llvm.org/extra/clang-tidy/index.html +# First disable all default checks (with -*) +Checks: '-*' diff --git a/CMakeLists.txt b/CMakeLists.txt index edc2346f4..868586c63 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,6 +22,16 @@ option(SOURCEMETA_CORE_CONTRIB_GOOGLEBENCHMARK "Build the GoogleBenchmark librar include(Sourcemeta) +if(PROJECT_IS_TOP_LEVEL) + sourcemeta_target_clang_format(SOURCES + src/*.h src/*.cc + benchmark/*.h benchmark/*.cc + test/*.h test/*.cc) + sourcemeta_find_clang_tidy() # Locates CLANG_TIDY program +endif() + +# Add clang-tidy to the targets. Clang-tidy uses the .clang-tidy file for configuration. +set(CMAKE_CXX_CLANG_TIDY "${CLANG_TIDY_BIN}" "--allow-no-checks") # Don't force downstream consumers on it if(PROJECT_IS_TOP_LEVEL) sourcemeta_enable_simd() @@ -91,13 +101,6 @@ if(SOURCEMETA_CORE_DOCS) OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/website") endif() -if(PROJECT_IS_TOP_LEVEL) - sourcemeta_target_clang_format(SOURCES - src/*.h src/*.cc - benchmark/*.h benchmark/*.cc - test/*.h test/*.cc) - sourcemeta_target_clang_tidy(SOURCES src/*.cc) -endif() # Testing diff --git a/cmake/common/targets/clang-tidy.cmake b/cmake/common/targets/clang-tidy.cmake deleted file mode 100644 index 47954d1d0..000000000 --- a/cmake/common/targets/clang-tidy.cmake +++ /dev/null @@ -1,130 +0,0 @@ -function(sourcemeta_target_clang_tidy_attempt_install) - cmake_parse_arguments(SOURCEMETA_TARGET_CLANG_TIDY_ATTEMPT_INSTALL "" "OUTPUT_DIRECTORY" "" ${ARGN}) - if(NOT SOURCEMETA_TARGET_CLANG_TIDY_ATTEMPT_INSTALL_OUTPUT_DIRECTORY) - message(FATAL_ERROR "You must pass the output directory in the OUTPUT_DIRECTORY option") - endif() - - # See https://pypi.org/project/clang-tidy/ - set(CLANG_TIDY_BINARY_VERSION "20.1.0") - set(CLANG_TIDY_BINARY_Windows_AMD64 "clang_tidy-${CLANG_TIDY_BINARY_VERSION}-py2.py3-none-win_amd64.whl") - set(CLANG_TIDY_BINARY_MSYS_x86_64 "clang_tidy-${CLANG_TIDY_BINARY_VERSION}-py2.py3-none-win_amd64.whl") - set(CLANG_TIDY_BINARY_Darwin_arm64 "clang_tidy-${CLANG_TIDY_BINARY_VERSION}-py2.py3-none-macosx_11_0_arm64.whl") - set(CLANG_TIDY_BINARY_Darwin_x86_64 "clang_tidy-${CLANG_TIDY_BINARY_VERSION}-py2.py3-none-macosx_10_9_x86_64.whl") - set(CLANG_TIDY_BINARY_Linux_aarch64 "clang_tidy-${CLANG_TIDY_BINARY_VERSION}-py2.py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl") - set(CLANG_TIDY_BINARY_Linux_x86_64 "clang_tidy-${CLANG_TIDY_BINARY_VERSION}-py2.py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl") - set(CLANG_TIDY_BINARY_CHECKSUM_Windows_AMD64 "02/f0/dd985d9d9b76f8c39f1995aa475d8d5aabbea0d3e0cf498df44dc7bf1cb0") - set(CLANG_TIDY_BINARY_CHECKSUM_MSYS_x86_64 "02/f0/dd985d9d9b76f8c39f1995aa475d8d5aabbea0d3e0cf498df44dc7bf1cb0") - set(CLANG_TIDY_BINARY_CHECKSUM_Darwin_arm64 "95/02/838baf08764b08327322096bda55e8d1e2344e4a13b9308e5642cfaafd8e") - set(CLANG_TIDY_BINARY_CHECKSUM_Darwin_x86_64 "6d/5b/dcfc84b895d8544e00186738ca85132bbd14db4d11dbe39502630ece5391") - set(CLANG_TIDY_BINARY_CHECKSUM_Linux_aarch64 "be/61/9e1a0797639e81c41d38d7b8b2508a9be4b05b9a23baa9d64e7284d07238") - set(CLANG_TIDY_BINARY_CHECKSUM_Linux_x86_64 "52/76/42c61be1c1fdf8bacdbb265f0cd3e11321fee7362f91fa840717a6a41ad6") - set(CLANG_TIDY_BINARY_NAME_Windows_AMD64 "clang-tidy.exe") - set(CLANG_TIDY_BINARY_NAME_MSYS_x86_64 "clang-tidy.exe") - set(CLANG_TIDY_BINARY_NAME_Darwin_arm64 "clang-tidy") - set(CLANG_TIDY_BINARY_NAME_Darwin_x86_64 "clang-tidy") - set(CLANG_TIDY_BINARY_NAME_Linux_aarch64 "clang-tidy") - set(CLANG_TIDY_BINARY_NAME_Linux_x86_64 "clang-tidy") - - # Determine the pre-built binary URL - string(REPLACE "." "_" CLANG_TIDY_BINARY_SYSTEM "${CMAKE_SYSTEM_NAME}") - string(REPLACE "." "_" CLANG_TIDY_BINARY_ARCH "${CMAKE_SYSTEM_PROCESSOR}") - set(CLANG_TIDY_BINARY_URL_VAR "CLANG_TIDY_BINARY_${CLANG_TIDY_BINARY_SYSTEM}_${CLANG_TIDY_BINARY_ARCH}") - set(CLANG_TIDY_BINARY_CHECKSUM_VAR "CLANG_TIDY_BINARY_CHECKSUM_${CLANG_TIDY_BINARY_SYSTEM}_${CLANG_TIDY_BINARY_ARCH}") - set(CLANG_TIDY_BINARY_NAME_VAR "CLANG_TIDY_BINARY_NAME_${CLANG_TIDY_BINARY_SYSTEM}_${CLANG_TIDY_BINARY_ARCH}") - if(NOT DEFINED ${CLANG_TIDY_BINARY_URL_VAR} OR "${${CLANG_TIDY_BINARY_URL_VAR}}" STREQUAL "") - message(WARNING "Skipping `clang-tidy` download. No known pre-build binary URL") - return() - elseif(NOT DEFINED ${CLANG_TIDY_BINARY_CHECKSUM_VAR} OR "${${CLANG_TIDY_BINARY_CHECKSUM_VAR}}" STREQUAL "") - message(FATAL_ERROR "No known `clang-tidy` pre-build binary checksum") - elseif(NOT DEFINED ${CLANG_TIDY_BINARY_NAME_VAR} OR "${${CLANG_TIDY_BINARY_NAME_VAR}}" STREQUAL "") - message(FATAL_ERROR "No known `clang-tidy` pre-build binary name") - endif() - set(CLANG_TIDY_BINARY_URL "https://files.pythonhosted.org/packages/${${CLANG_TIDY_BINARY_CHECKSUM_VAR}}/${${CLANG_TIDY_BINARY_URL_VAR}}") - - # Download and extract the pre-built binary ZIP if needed - set(CLANG_TIDY_BINARY_NAME "${${CLANG_TIDY_BINARY_NAME_VAR}}") - set(CLANG_TIDY_BINARY_OUTPUT "${SOURCEMETA_TARGET_CLANG_TIDY_ATTEMPT_INSTALL_OUTPUT_DIRECTORY}/${CLANG_TIDY_BINARY_NAME}") - if(EXISTS "${CLANG_TIDY_BINARY_OUTPUT}") - message(STATUS "Found existing `clang-tidy` pre-built binary at ${CLANG_TIDY_BINARY_OUTPUT}") - return() - endif() - set(CLANG_TIDY_BINARY_DOWNLOAD_DIR "${CMAKE_CURRENT_BINARY_DIR}/clang-tidy") - file(REMOVE_RECURSE "${CLANG_TIDY_BINARY_DOWNLOAD_DIR}") - file(MAKE_DIRECTORY "${CLANG_TIDY_BINARY_DOWNLOAD_DIR}") - set(CLANG_TIDY_BINARY_WHEEL "${CLANG_TIDY_BINARY_DOWNLOAD_DIR}/clang-tidy.whl") - message(STATUS "Downloading `clang-tidy` pre-built binary from ${CLANG_TIDY_BINARY_URL}") - file(DOWNLOAD "${CLANG_TIDY_BINARY_URL}" "${CLANG_TIDY_BINARY_WHEEL}" - STATUS CLANG_TIDY_BINARY_DOWNLOAD_STATUS SHOW_PROGRESS TLS_VERIFY ON - LOG CLANG_TIDY_BINARY_DOWNLOAD_LOG) - list(GET CLANG_TIDY_BINARY_DOWNLOAD_STATUS 0 _code) - if(NOT _code EQUAL 0) - message(WARNING "Failed to download the `clang-tidy` pre-built binary") - message(WARNING "${CLANG_TIDY_BINARY_DOWNLOAD_LOG}") - file(REMOVE_RECURSE "${CLANG_TIDY_BINARY_DOWNLOAD_DIR}") - return() - endif() - set(CLANG_TIDY_BINARY_EXTRACT_DIR "${CLANG_TIDY_BINARY_DOWNLOAD_DIR}/extracted") - file(MAKE_DIRECTORY "${CLANG_TIDY_BINARY_EXTRACT_DIR}") - file(ARCHIVE_EXTRACT INPUT "${CLANG_TIDY_BINARY_WHEEL}" DESTINATION "${CLANG_TIDY_BINARY_EXTRACT_DIR}") - - # Install the binary - file(MAKE_DIRECTORY "${SOURCEMETA_TARGET_CLANG_TIDY_ATTEMPT_INSTALL_OUTPUT_DIRECTORY}") - file(COPY "${CLANG_TIDY_BINARY_EXTRACT_DIR}/clang_tidy/data/bin/${CLANG_TIDY_BINARY_NAME}" - DESTINATION "${SOURCEMETA_TARGET_CLANG_TIDY_ATTEMPT_INSTALL_OUTPUT_DIRECTORY}") - file(CHMOD "${CLANG_TIDY_BINARY_OUTPUT}" PERMISSIONS - OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) - message(STATUS "Installed `clang-tidy` pre-built binary to ${CLANG_TIDY_BINARY_OUTPUT}") -endfunction() - -function(sourcemeta_target_clang_tidy) - cmake_parse_arguments(SOURCEMETA_TARGET_CLANG_TIDY "REQUIRED" "" "SOURCES" ${ARGN}) - sourcemeta_target_clang_tidy_attempt_install(OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin") - - if(SOURCEMETA_TARGET_CLANG_TIDY_REQUIRED) - find_program(CLANG_TIDY_BIN NAMES clang-tidy NO_DEFAULT_PATH - PATHS "${CMAKE_CURRENT_BINARY_DIR}/bin") - if(NOT CLANG_TIDY_BIN) - find_program(CLANG_TIDY_BIN NAMES clang-tidy REQUIRED) - endif() - else() - find_program(CLANG_TIDY_BIN NAMES clang-tidy NO_DEFAULT_PATH - PATHS "${CMAKE_CURRENT_BINARY_DIR}/bin") - if(NOT CLANG_TIDY_BIN) - find_program(CLANG_TIDY_BIN NAMES clang-tidy) - endif() - endif() - - - # This covers the empty list too - if(NOT SOURCEMETA_TARGET_CLANG_TIDY_SOURCES) - message(FATAL_ERROR "You must pass file globs to analyze in the SOURCES option") - endif() - file(GLOB_RECURSE SOURCEMETA_TARGET_CLANG_TIDY_FILES - ${SOURCEMETA_TARGET_CLANG_TIDY_SOURCES}) - - set(CLANG_TIDY_CONFIG "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/clang-tidy.config") - - if(CMAKE_SYSTEM_NAME STREQUAL "MSYS") - # Because `clang-tidy` is typically a Windows `.exe`, transform the path accordingly - execute_process(COMMAND cygpath -w "${CLANG_TIDY_CONFIG}" - OUTPUT_VARIABLE CLANG_TIDY_CONFIG OUTPUT_STRIP_TRAILING_WHITESPACE) - endif() - - if(CLANG_TIDY_BIN) - add_custom_target(clang_tidy - WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}" - VERBATIM - COMMAND "${CLANG_TIDY_BIN}" -p "${PROJECT_BINARY_DIR}" - --config-file "${CLANG_TIDY_CONFIG}" - ${SOURCEMETA_TARGET_CLANG_TIDY_FILES} - COMMENT "Analyzing sources using ClangTidy") - else() - add_custom_target(clang_tidy - WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}" - VERBATIM - COMMAND "${CMAKE_COMMAND}" -E echo "Could not locate ClangTidy" - COMMAND "${CMAKE_COMMAND}" -E false) - endif() - - set_target_properties(clang_tidy PROPERTIES FOLDER "Linting") -endfunction() diff --git a/cmake/common/targets/clang-tidy.config b/cmake/common/targets/clang-tidy.config deleted file mode 100644 index a7de0a47b..000000000 --- a/cmake/common/targets/clang-tidy.config +++ /dev/null @@ -1,22 +0,0 @@ ---- -# See https://clang.llvm.org/extra/clang-tidy/index.html -# First disable all default checks (with -*) -Checks: '-*, - bugprone-*,-bugprone-branch-clone,-bugprone-easily-swappable-parameters,-bugprone-empty-catch, - clang-analyzer-*, - clang-diagnostic-*, - modernize-*, - concurrency-*, - cppcoreguidelines-*,-cppcoreguidelines-rvalue-reference-param-not-moved, - performance-*,-performance-enum-size, - portability-*, - objc-*, - misc-*,-misc-no-recursion,-misc-unused-parameters,-misc-const-correctness' -WarningsAsErrors: '*' -HeaderFilterRegex: '' -FormatStyle: none -CheckOptions: - # See https://clang.llvm.org/extra/clang-tidy/checks/misc/include-cleaner.html - # Otherwise ClangTidy wants us to directly include private headers from our modules - - key: misc-include-cleaner.IgnoreHeaders - value: 'src\/core\/.*;uriparser\/.*' diff --git a/src/.clang-tidy b/src/.clang-tidy new file mode 100644 index 000000000..bb9904cc8 --- /dev/null +++ b/src/.clang-tidy @@ -0,0 +1,6 @@ +--- +# See https://clang.llvm.org/extra/clang-tidy/index.html +Checks: 'concurrency-*' +InheritParentConfig: true +WarningsAsErrors: '*' +FormatStyle: none From 1bfa644ab8e097e4a0fb5077b0866b9a254405dd Mon Sep 17 00:00:00 2001 From: Balakrishna Avulapati Date: Fri, 27 Jun 2025 10:22:54 +0530 Subject: [PATCH 2/8] Enable performance-* clang-tidy checks Signed-off-by: Balakrishna Avulapati --- CMakeLists.txt | 2 +- cmake/Sourcemeta.cmake | 2 +- src/.clang-tidy | 5 ++++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 868586c63..3bb4ea2ec 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,7 +27,7 @@ if(PROJECT_IS_TOP_LEVEL) src/*.h src/*.cc benchmark/*.h benchmark/*.cc test/*.h test/*.cc) - sourcemeta_find_clang_tidy() # Locates CLANG_TIDY program + sourcemeta_enable_clang_tidy() # Locates and enables CLANG_TIDY endif() # Add clang-tidy to the targets. Clang-tidy uses the .clang-tidy file for configuration. diff --git a/cmake/Sourcemeta.cmake b/cmake/Sourcemeta.cmake index b75c969c1..f9377319b 100644 --- a/cmake/Sourcemeta.cmake +++ b/cmake/Sourcemeta.cmake @@ -10,7 +10,7 @@ include("${SOURCEMETA_UTILITIES_DIRECTORY}/commands/copy-file.cmake") include("${SOURCEMETA_UTILITIES_DIRECTORY}/targets/library.cmake") include("${SOURCEMETA_UTILITIES_DIRECTORY}/targets/executable.cmake") include("${SOURCEMETA_UTILITIES_DIRECTORY}/targets/clang-format.cmake") -include("${SOURCEMETA_UTILITIES_DIRECTORY}/targets/clang-tidy.cmake") +include("${SOURCEMETA_UTILITIES_DIRECTORY}/commands/clang-tidy.cmake") include("${SOURCEMETA_UTILITIES_DIRECTORY}/targets/shellcheck.cmake") include("${SOURCEMETA_UTILITIES_DIRECTORY}/targets/doxygen.cmake") include("${SOURCEMETA_UTILITIES_DIRECTORY}/targets/googletest.cmake") diff --git a/src/.clang-tidy b/src/.clang-tidy index bb9904cc8..076e26a66 100644 --- a/src/.clang-tidy +++ b/src/.clang-tidy @@ -1,6 +1,9 @@ --- # See https://clang.llvm.org/extra/clang-tidy/index.html -Checks: 'concurrency-*' +Checks: ' + concurrency-*, + performance-*, + ' InheritParentConfig: true WarningsAsErrors: '*' FormatStyle: none From 852043e13b3455d4278e0f179b52be0e2614d88c Mon Sep 17 00:00:00 2001 From: Balakrishna Avulapati Date: Fri, 27 Jun 2025 10:37:05 +0530 Subject: [PATCH 3/8] remove redundant variable Signed-off-by: Balakrishna Avulapati --- CMakeLists.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3bb4ea2ec..b8be8616c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,8 +30,6 @@ if(PROJECT_IS_TOP_LEVEL) sourcemeta_enable_clang_tidy() # Locates and enables CLANG_TIDY endif() -# Add clang-tidy to the targets. Clang-tidy uses the .clang-tidy file for configuration. -set(CMAKE_CXX_CLANG_TIDY "${CLANG_TIDY_BIN}" "--allow-no-checks") # Don't force downstream consumers on it if(PROJECT_IS_TOP_LEVEL) sourcemeta_enable_simd() From dc407765939bda5ac448d193a7d083e193d91718 Mon Sep 17 00:00:00 2001 From: Balakrishna Avulapati Date: Fri, 27 Jun 2025 10:56:10 +0530 Subject: [PATCH 4/8] fix a lint issue Signed-off-by: Balakrishna Avulapati --- src/.clang-tidy | 3 ++- src/core/jsonschema/frame.cc | 16 ++++++---------- src/core/uri/uri.cc | 2 -- 3 files changed, 8 insertions(+), 13 deletions(-) diff --git a/src/.clang-tidy b/src/.clang-tidy index 076e26a66..b8118c1c5 100644 --- a/src/.clang-tidy +++ b/src/.clang-tidy @@ -2,7 +2,8 @@ # See https://clang.llvm.org/extra/clang-tidy/index.html Checks: ' concurrency-*, - performance-*, + bugprone-*, + -bugprone-easily-swappable-parameters, ' InheritParentConfig: true WarningsAsErrors: '*' diff --git a/src/core/jsonschema/frame.cc b/src/core/jsonschema/frame.cc index 3a9635aac..fa1e642f3 100644 --- a/src/core/jsonschema/frame.cc +++ b/src/core/jsonschema/frame.cc @@ -76,11 +76,9 @@ auto find_anchors(const sourcemeta::core::JSON &schema, const sourcemeta::core::URI identifier(schema.at("$id").to_string()); if (identifier.is_fragment_only()) { result.insert( - {sourcemeta::core::JSON::String{ - identifier.fragment() - .value()}, // NOLINT(bugprone-unchecked-optional-access): - // Check for optional is happening - // inside is_fragment_only() + // Check for optional is happening inside is_fragment_only() + // NOLINTNEXTLINE(bugprone-unchecked-optional-access) + {sourcemeta::core::JSON::String{identifier.fragment().value()}, AnchorType::Static}); } } @@ -95,11 +93,9 @@ auto find_anchors(const sourcemeta::core::JSON &schema, const sourcemeta::core::URI identifier(schema.at("id").to_string()); if (identifier.is_fragment_only()) { result.insert( - {sourcemeta::core::JSON::String{ - identifier.fragment() - .value()}, // NOLINT(bugprone-unchecked-optional-access): - // Check for optional is happening - // inside is_fragment_only() + // Check for optional is happening inside is_fragment_only() + // NOLINTNEXTLINE(bugprone-unchecked-optional-access) + {sourcemeta::core::JSON::String{identifier.fragment().value()}, AnchorType::Static}); } } diff --git a/src/core/uri/uri.cc b/src/core/uri/uri.cc index 76842ec2e..be0e13e65 100644 --- a/src/core/uri/uri.cc +++ b/src/core/uri/uri.cc @@ -681,8 +681,6 @@ auto URI::try_resolve_from(const URI &base) -> URI & { this->scheme_ = base.scheme_; this->query_ = base.query_; return *this; - } else if (base.path().has_value() && base.path().value().starts_with("..")) { - return *this; } else if (base.is_relative() && this->is_relative() && base.path_.has_value() && this->path_.has_value() && this->path_.value().find('/') == std::string::npos && From 95ef54c1b448a703f86c2012ac1181eb9303b60b Mon Sep 17 00:00:00 2001 From: Balakrishna Avulapati Date: Fri, 27 Jun 2025 11:16:09 +0530 Subject: [PATCH 5/8] add missing clang-tidy.cmake Signed-off-by: Balakrishna Avulapati --- cmake/common/commands/clang-tidy.cmake | 83 ++++++++++++++++++++++++++ src/.clang-tidy | 6 +- 2 files changed, 84 insertions(+), 5 deletions(-) create mode 100644 cmake/common/commands/clang-tidy.cmake diff --git a/cmake/common/commands/clang-tidy.cmake b/cmake/common/commands/clang-tidy.cmake new file mode 100644 index 000000000..9c8c97467 --- /dev/null +++ b/cmake/common/commands/clang-tidy.cmake @@ -0,0 +1,83 @@ +function(sourcemeta_target_clang_tidy_attempt_install) + cmake_parse_arguments(SOURCEMETA_TARGET_CLANG_TIDY_ATTEMPT_INSTALL "" "OUTPUT_DIRECTORY" "" ${ARGN}) + if(NOT SOURCEMETA_TARGET_CLANG_TIDY_ATTEMPT_INSTALL_OUTPUT_DIRECTORY) + message(FATAL_ERROR "You must pass the output directory in the OUTPUT_DIRECTORY option") + endif() + + # See https://pypi.org/project/clang-tidy/ + set(CLANG_TIDY_BINARY_VERSION "20.1.0") + set(CLANG_TIDY_BINARY_Windows_AMD64 "clang_tidy-${CLANG_TIDY_BINARY_VERSION}-py2.py3-none-win_amd64.whl") + set(CLANG_TIDY_BINARY_MSYS_x86_64 "clang_tidy-${CLANG_TIDY_BINARY_VERSION}-py2.py3-none-win_amd64.whl") + set(CLANG_TIDY_BINARY_Darwin_arm64 "clang_tidy-${CLANG_TIDY_BINARY_VERSION}-py2.py3-none-macosx_11_0_arm64.whl") + set(CLANG_TIDY_BINARY_Darwin_x86_64 "clang_tidy-${CLANG_TIDY_BINARY_VERSION}-py2.py3-none-macosx_10_9_x86_64.whl") + set(CLANG_TIDY_BINARY_Linux_aarch64 "clang_tidy-${CLANG_TIDY_BINARY_VERSION}-py2.py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl") + set(CLANG_TIDY_BINARY_Linux_x86_64 "clang_tidy-${CLANG_TIDY_BINARY_VERSION}-py2.py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl") + set(CLANG_TIDY_BINARY_CHECKSUM_Windows_AMD64 "02/f0/dd985d9d9b76f8c39f1995aa475d8d5aabbea0d3e0cf498df44dc7bf1cb0") + set(CLANG_TIDY_BINARY_CHECKSUM_MSYS_x86_64 "02/f0/dd985d9d9b76f8c39f1995aa475d8d5aabbea0d3e0cf498df44dc7bf1cb0") + set(CLANG_TIDY_BINARY_CHECKSUM_Darwin_arm64 "95/02/838baf08764b08327322096bda55e8d1e2344e4a13b9308e5642cfaafd8e") + set(CLANG_TIDY_BINARY_CHECKSUM_Darwin_x86_64 "6d/5b/dcfc84b895d8544e00186738ca85132bbd14db4d11dbe39502630ece5391") + set(CLANG_TIDY_BINARY_CHECKSUM_Linux_aarch64 "be/61/9e1a0797639e81c41d38d7b8b2508a9be4b05b9a23baa9d64e7284d07238") + set(CLANG_TIDY_BINARY_CHECKSUM_Linux_x86_64 "52/76/42c61be1c1fdf8bacdbb265f0cd3e11321fee7362f91fa840717a6a41ad6") + set(CLANG_TIDY_BINARY_NAME_Windows_AMD64 "clang-tidy.exe") + set(CLANG_TIDY_BINARY_NAME_MSYS_x86_64 "clang-tidy.exe") + set(CLANG_TIDY_BINARY_NAME_Darwin_arm64 "clang-tidy") + set(CLANG_TIDY_BINARY_NAME_Darwin_x86_64 "clang-tidy") + set(CLANG_TIDY_BINARY_NAME_Linux_aarch64 "clang-tidy") + set(CLANG_TIDY_BINARY_NAME_Linux_x86_64 "clang-tidy") + + # Determine the pre-built binary URL + string(REPLACE "." "_" CLANG_TIDY_BINARY_SYSTEM "${CMAKE_SYSTEM_NAME}") + string(REPLACE "." "_" CLANG_TIDY_BINARY_ARCH "${CMAKE_SYSTEM_PROCESSOR}") + set(CLANG_TIDY_BINARY_URL_VAR "CLANG_TIDY_BINARY_${CLANG_TIDY_BINARY_SYSTEM}_${CLANG_TIDY_BINARY_ARCH}") + set(CLANG_TIDY_BINARY_CHECKSUM_VAR "CLANG_TIDY_BINARY_CHECKSUM_${CLANG_TIDY_BINARY_SYSTEM}_${CLANG_TIDY_BINARY_ARCH}") + set(CLANG_TIDY_BINARY_NAME_VAR "CLANG_TIDY_BINARY_NAME_${CLANG_TIDY_BINARY_SYSTEM}_${CLANG_TIDY_BINARY_ARCH}") + if(NOT DEFINED ${CLANG_TIDY_BINARY_URL_VAR} OR "${${CLANG_TIDY_BINARY_URL_VAR}}" STREQUAL "") + message(WARNING "Skipping `clang-tidy` download. No known pre-build binary URL") + return() + elseif(NOT DEFINED ${CLANG_TIDY_BINARY_CHECKSUM_VAR} OR "${${CLANG_TIDY_BINARY_CHECKSUM_VAR}}" STREQUAL "") + message(FATAL_ERROR "No known `clang-tidy` pre-build binary checksum") + elseif(NOT DEFINED ${CLANG_TIDY_BINARY_NAME_VAR} OR "${${CLANG_TIDY_BINARY_NAME_VAR}}" STREQUAL "") + message(FATAL_ERROR "No known `clang-tidy` pre-build binary name") + endif() + set(CLANG_TIDY_BINARY_URL "https://files.pythonhosted.org/packages/${${CLANG_TIDY_BINARY_CHECKSUM_VAR}}/${${CLANG_TIDY_BINARY_URL_VAR}}") + + # Download and extract the pre-built binary ZIP if needed + set(CLANG_TIDY_BINARY_NAME "${${CLANG_TIDY_BINARY_NAME_VAR}}") + set(CLANG_TIDY_BINARY_OUTPUT "${SOURCEMETA_TARGET_CLANG_TIDY_ATTEMPT_INSTALL_OUTPUT_DIRECTORY}/${CLANG_TIDY_BINARY_NAME}") + if(EXISTS "${CLANG_TIDY_BINARY_OUTPUT}") + message(STATUS "Found existing `clang-tidy` pre-built binary at ${CLANG_TIDY_BINARY_OUTPUT}") + return() + endif() + set(CLANG_TIDY_BINARY_DOWNLOAD_DIR "${CMAKE_CURRENT_BINARY_DIR}/clang-tidy") + file(REMOVE_RECURSE "${CLANG_TIDY_BINARY_DOWNLOAD_DIR}") + file(MAKE_DIRECTORY "${CLANG_TIDY_BINARY_DOWNLOAD_DIR}") + set(CLANG_TIDY_BINARY_WHEEL "${CLANG_TIDY_BINARY_DOWNLOAD_DIR}/clang-tidy.whl") + message(STATUS "Downloading `clang-tidy` pre-built binary from ${CLANG_TIDY_BINARY_URL}") + file(DOWNLOAD "${CLANG_TIDY_BINARY_URL}" "${CLANG_TIDY_BINARY_WHEEL}" + STATUS CLANG_TIDY_BINARY_DOWNLOAD_STATUS SHOW_PROGRESS TLS_VERIFY ON + LOG CLANG_TIDY_BINARY_DOWNLOAD_LOG) + list(GET CLANG_TIDY_BINARY_DOWNLOAD_STATUS 0 _code) + if(NOT _code EQUAL 0) + message(WARNING "Failed to download the `clang-tidy` pre-built binary") + message(WARNING "${CLANG_TIDY_BINARY_DOWNLOAD_LOG}") + file(REMOVE_RECURSE "${CLANG_TIDY_BINARY_DOWNLOAD_DIR}") + return() + endif() + set(CLANG_TIDY_BINARY_EXTRACT_DIR "${CLANG_TIDY_BINARY_DOWNLOAD_DIR}/extracted") + file(MAKE_DIRECTORY "${CLANG_TIDY_BINARY_EXTRACT_DIR}") + file(ARCHIVE_EXTRACT INPUT "${CLANG_TIDY_BINARY_WHEEL}" DESTINATION "${CLANG_TIDY_BINARY_EXTRACT_DIR}") + + # Install the binary + file(MAKE_DIRECTORY "${SOURCEMETA_TARGET_CLANG_TIDY_ATTEMPT_INSTALL_OUTPUT_DIRECTORY}") + file(COPY "${CLANG_TIDY_BINARY_EXTRACT_DIR}/clang_tidy/data/bin/${CLANG_TIDY_BINARY_NAME}" + DESTINATION "${SOURCEMETA_TARGET_CLANG_TIDY_ATTEMPT_INSTALL_OUTPUT_DIRECTORY}") + file(CHMOD "${CLANG_TIDY_BINARY_OUTPUT}" PERMISSIONS + OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) + message(STATUS "Installed `clang-tidy` pre-built binary to ${CLANG_TIDY_BINARY_OUTPUT}") +endfunction() + +function(sourcemeta_enable_clang_tidy) + sourcemeta_target_clang_tidy_attempt_install(OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin") + find_program(CLANG_TIDY_BIN NAMES clang-tidy NO_DEFAULT_PATH + PATHS "${CMAKE_CURRENT_BINARY_DIR}/bin") +endfunction() diff --git a/src/.clang-tidy b/src/.clang-tidy index b8118c1c5..bb9904cc8 100644 --- a/src/.clang-tidy +++ b/src/.clang-tidy @@ -1,10 +1,6 @@ --- # See https://clang.llvm.org/extra/clang-tidy/index.html -Checks: ' - concurrency-*, - bugprone-*, - -bugprone-easily-swappable-parameters, - ' +Checks: 'concurrency-*' InheritParentConfig: true WarningsAsErrors: '*' FormatStyle: none From 3f5d0f07b7dcd9e5702bf8a9068089ca24a2f08b Mon Sep 17 00:00:00 2001 From: Balakrishna Avulapati Date: Fri, 27 Jun 2025 16:36:31 +0530 Subject: [PATCH 6/8] add missing set Signed-off-by: Balakrishna Avulapati --- cmake/common/commands/clang-tidy.cmake | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cmake/common/commands/clang-tidy.cmake b/cmake/common/commands/clang-tidy.cmake index 9c8c97467..8ef3af10c 100644 --- a/cmake/common/commands/clang-tidy.cmake +++ b/cmake/common/commands/clang-tidy.cmake @@ -80,4 +80,6 @@ function(sourcemeta_enable_clang_tidy) sourcemeta_target_clang_tidy_attempt_install(OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin") find_program(CLANG_TIDY_BIN NAMES clang-tidy NO_DEFAULT_PATH PATHS "${CMAKE_CURRENT_BINARY_DIR}/bin") + # Add clang-tidy to the targets. Clang-tidy uses the .clang-tidy file for configuration. + set(CMAKE_CXX_CLANG_TIDY "${CLANG_TIDY_BIN};--allow-no-checks;--quiet" PARENT_SCOPE) endfunction() From 32e4aca6599b6f22e2613df1b7bb4010e4fd45a1 Mon Sep 17 00:00:00 2001 From: Balakrishna Avulapati Date: Fri, 27 Jun 2025 21:04:03 +0530 Subject: [PATCH 7/8] enable cppcoreguidelines Signed-off-by: Balakrishna Avulapati --- cmake/common/commands/clang-tidy.cmake | 2 +- src/.clang-tidy | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/cmake/common/commands/clang-tidy.cmake b/cmake/common/commands/clang-tidy.cmake index 8ef3af10c..1dfa54e52 100644 --- a/cmake/common/commands/clang-tidy.cmake +++ b/cmake/common/commands/clang-tidy.cmake @@ -81,5 +81,5 @@ function(sourcemeta_enable_clang_tidy) find_program(CLANG_TIDY_BIN NAMES clang-tidy NO_DEFAULT_PATH PATHS "${CMAKE_CURRENT_BINARY_DIR}/bin") # Add clang-tidy to the targets. Clang-tidy uses the .clang-tidy file for configuration. - set(CMAKE_CXX_CLANG_TIDY "${CLANG_TIDY_BIN};--allow-no-checks;--quiet" PARENT_SCOPE) + set(CMAKE_CXX_CLANG_TIDY "${CLANG_TIDY_BIN};--allow-no-checks;" PARENT_SCOPE) endfunction() diff --git a/src/.clang-tidy b/src/.clang-tidy index bb9904cc8..75a190d5a 100644 --- a/src/.clang-tidy +++ b/src/.clang-tidy @@ -1,6 +1,9 @@ --- # See https://clang.llvm.org/extra/clang-tidy/index.html -Checks: 'concurrency-*' +Checks: ' + concurrency-*, + cppcoreguidelines-*, + ' InheritParentConfig: true WarningsAsErrors: '*' FormatStyle: none From 3c33bf62ae3a9c3550c31400a3db47d22a50a3bd Mon Sep 17 00:00:00 2001 From: Balakrishna Avulapati Date: Tue, 1 Jul 2025 19:22:55 +0530 Subject: [PATCH 8/8] have a single .clang-tidy file Signed-off-by: Balakrishna Avulapati --- .clang-tidy | 10 ++++++++-- CMakeLists.txt | 5 ++++- cmake/common/commands/clang-tidy.cmake | 7 ++++++- src/.clang-tidy | 9 --------- 4 files changed, 18 insertions(+), 13 deletions(-) delete mode 100644 src/.clang-tidy diff --git a/.clang-tidy b/.clang-tidy index 785cb2991..6a6abc7a5 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,4 +1,10 @@ --- # See https://clang.llvm.org/extra/clang-tidy/index.html -# First disable all default checks (with -*) -Checks: '-*' +Checks: ' + -*, + concurrency-*, + ' +WarningsAsErrors: '*' +SystemHeaders: false +UseColor: true +FormatStyle: none diff --git a/CMakeLists.txt b/CMakeLists.txt index b8be8616c..7156e2830 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,9 +27,10 @@ if(PROJECT_IS_TOP_LEVEL) src/*.h src/*.cc benchmark/*.h benchmark/*.cc test/*.h test/*.cc) - sourcemeta_enable_clang_tidy() # Locates and enables CLANG_TIDY endif() +sourcemeta_enable_clang_tidy() # Locates and enables CLANG_TIDY + # Don't force downstream consumers on it if(PROJECT_IS_TOP_LEVEL) sourcemeta_enable_simd() @@ -88,6 +89,8 @@ if(SOURCEMETA_CORE_EXTENSION_ALTERSCHEMA) add_subdirectory(src/extension/alterschema) endif() +sourcemeta_disable_clang_tidy() + if(SOURCEMETA_CORE_ADDRESS_SANITIZER) sourcemeta_sanitizer(TYPE address) elseif(SOURCEMETA_CORE_UNDEFINED_SANITIZER) diff --git a/cmake/common/commands/clang-tidy.cmake b/cmake/common/commands/clang-tidy.cmake index 1dfa54e52..d7b7f637d 100644 --- a/cmake/common/commands/clang-tidy.cmake +++ b/cmake/common/commands/clang-tidy.cmake @@ -80,6 +80,11 @@ function(sourcemeta_enable_clang_tidy) sourcemeta_target_clang_tidy_attempt_install(OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin") find_program(CLANG_TIDY_BIN NAMES clang-tidy NO_DEFAULT_PATH PATHS "${CMAKE_CURRENT_BINARY_DIR}/bin") + set(CLANG_TIDY_CONFIG_PATH "${CMAKE_CURRENT_SOURCE_DIR}/.clang-tidy") # Add clang-tidy to the targets. Clang-tidy uses the .clang-tidy file for configuration. - set(CMAKE_CXX_CLANG_TIDY "${CLANG_TIDY_BIN};--allow-no-checks;" PARENT_SCOPE) + set(CMAKE_CXX_CLANG_TIDY "${CLANG_TIDY_BIN};--config-file=${CLANG_TIDY_CONFIG_PATH};-header-filter=${CMAKE_CURRENT_SOURCE_DIR}/src/*" PARENT_SCOPE) +endfunction() + +function(sourcemeta_disable_clang_tidy) + unset(CMAKE_CXX_CLANG_TIDY PARENT_SCOPE) endfunction() diff --git a/src/.clang-tidy b/src/.clang-tidy deleted file mode 100644 index 75a190d5a..000000000 --- a/src/.clang-tidy +++ /dev/null @@ -1,9 +0,0 @@ ---- -# See https://clang.llvm.org/extra/clang-tidy/index.html -Checks: ' - concurrency-*, - cppcoreguidelines-*, - ' -InheritParentConfig: true -WarningsAsErrors: '*' -FormatStyle: none