Skip to content
Snippets Groups Projects
Commit 6eadbda9 authored by Administrator's avatar Administrator
Browse files

Add new CMake target to run clang-tidy

The target will run clang-tidy on all changed source and header files
The target is only created if the used clang-tidy supports all required
checks. The required checks will be extracted from the clang-tidy configuration
file, so the list should be alwyas correct.

Instead of having a hardcoded list of required checks the list is extracted
from the clang-tidy config file such that the list is always up to date.

Add CMake script to execute the TidyCheck in our CI

Download and install external packages needed when running clang-tidy.
To speed up things execute clang-tidy in parallel on differnt files if more
cores are available.

Add shell script used by the CMake target

Check changed header files only if there is a corresponding source file in the
compile_commands database. Currently there is no way to test header files
without corresponding source file (compilation unit).
Create missing but expected output directories.
Remove clang-tidy command line option
The option was moved to the config file.

The script find_files.sh is now used from two places so pass the required
information as parameters. Remove one unneded parameter
parent 3f568c6d
No related branches found
No related tags found
1 merge request!1340Add new CMake target to run clang-tidy
...@@ -26,7 +26,7 @@ macro(define_additional_targets) ...@@ -26,7 +26,7 @@ macro(define_additional_targets)
# Create a list C, C++ and header files which have been changed in the # Create a list C, C++ and header files which have been changed in the
# current commit # current commit
execute_process(COMMAND ${CMAKE_SOURCE_DIR}/cmake/scripts/find_files.sh execute_process(COMMAND ${CMAKE_SOURCE_DIR}/cmake/scripts/find_files.sh ${BASE_COMMIT}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE FileList OUTPUT_VARIABLE FileList
OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_STRIP_TRAILING_WHITESPACE
...@@ -58,6 +58,50 @@ macro(define_additional_targets) ...@@ -58,6 +58,50 @@ macro(define_additional_targets)
endif() endif()
find_package2(PRIVATE ClangTidy)
if(ClangTidy_FOUND AND EXISTS ${CMAKE_SOURCE_DIR}/.git)
if (FAIRROOT_TIDY_BASE)
set(BASE_COMMIT ${FAIRROOT_TIDY_BASE})
else()
set(BASE_COMMIT upstream/master)
endif()
# Create a list C, C++ and header files which have been changed in the
# current commit
execute_process(COMMAND ${CMAKE_SOURCE_DIR}/cmake/scripts/find_files.sh ${BASE_COMMIT}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE FileList
OUTPUT_STRIP_TRAILING_WHITESPACE
)
string(REGEX REPLACE " " ";" FileList "${FileList}")
# Loop over the files and create the code whch is executed when running
# "make FormatCheck".
# The produced code will run clang-format on one of the files. If
# clang-format finds code which are not satisfying our code rules a
# detailed error message is created. This error message can be checked on
# our CDash web page.
foreach(file ${FileList})
set(file1 ${CMAKE_BINARY_DIR}/${file}.ct_out)
list(APPEND myfilelist1 ${file1})
add_custom_command(OUTPUT ${file1}
COMMAND ${CMAKE_SOURCE_DIR}/cmake/scripts/check-tidy.sh ${file} ${file1} ${CMAKE_BINARY_DIR}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
)
endforeach()
# Create the target FormatCheck which only depends on the files creted in
# previous step. When running "make FormatCheck" clang-format is executed
# for all C, C++ and header files which have changed in the commit.
add_custom_target(TidyCheck
DEPENDS ${myfilelist1}
)
endif()
# TODO: check if still needed # TODO: check if still needed
# if(RULE_CHECKER_FOUND) # if(RULE_CHECKER_FOUND)
# ADD_CUSTOM_TARGET(RULES # ADD_CUSTOM_TARGET(RULES
......
# Defines the following variables:
#
# ClangTidy_FOUND - Found clang-tidy
# CLANG_TIDY_BIN - clang-tidy executable
find_program(CLANG_TIDY_BIN
NAMES clang-tidy
clang-tidy-16
clang-tidy-15
clang-tidy-14
clang-tidy-13
clang-tidy-12
clang-tidy-11
)
Message("CLANG_TIDY_BIN: ${CLANG_TIDY_BIN}")
#list(APPEND required_tidy_checks
# modernize-deprecated-headers
# modernize-use-nullptr
#)
# Extract the list of checks from the clang-tidy configuration
# The line looks like: "Checks: '-*,modernize-deprecated-headers'"
# Remove everything beside the part between the quotes and convert the
# string to a list
# The checks must not contain any wildcards
# IDEA: Check if one can extract the same information from clang-tidy --dump-version
file(STRINGS ${CMAKE_SOURCE_DIR}/.clang-tidy required_tidy_checks_from_file REGEX "Checks.*")
string(LENGTH ${required_tidy_checks_from_file} _length)
string(FIND ${required_tidy_checks_from_file} "'" _pos_first_quote)
math(EXPR _pos_first_quote ${_pos_first_quote}+1)
string(SUBSTRING ${required_tidy_checks_from_file} ${_pos_first_quote} ${_length} required_tidy_checks_from_file)
string(FIND ${required_tidy_checks_from_file} "'" _pos_last_quote)
string(SUBSTRING ${required_tidy_checks_from_file} 0 ${_pos_last_quote} required_tidy_checks_from_file)
string(REPLACE "," ";" required_tidy_checks ${required_tidy_checks_from_file})
message(VERBOSE "required_tidy_checks: ${required_tidy_checks}")
if (CLANG_TIDY_BIN)
# Loop over list of required checks
# Succeed if all required checks are supported by the clang version
execute_process(COMMAND ${CLANG_TIDY_BIN} -checks=-*,modernize-* --list-checks
OUTPUT_VARIABLE available_tidy_checks
)
message(VERBOSE "Available clang-tidy checks: ${available_tidy_checks}")
set(CLANG_TIDY_CHECKS_SUPPORTED TRUE)
foreach(check IN LISTS required_tidy_checks)
# Skip all checks which contain wildcards
string(REGEX MATCH "\\*" _wildcard ${check})
if(_wildcard)
message("The checker doesn't support wildcards in the check")
string(REGEX MATCH "^-\\*" _wildcard ${check})
if(_wildcard)
message("The check ${check} is droped.")
continue()
else()
message("The check ${check} violates this. clang-tidy support is disabled.")
set(CLANG_TIDY_CHECKS_SUPPORTED FALSE)
break()
endif()
endif()
string(FIND "${available_tidy_checks}" "${check}" check_avail)
if(${check_avail} EQUAL -1)
message("clang-tidy doesn't support the needed Check ${check}. clang-tidy support is disabled.")
set(CLANG_TIDY_CHECKS_SUPPORTED FALSE)
break()
endif()
message("Used check: ${check}")
endforeach()
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(ClangTidy
REQUIRED_VARS CLANG_TIDY_BIN CLANG_TIDY_CHECKS_SUPPORTED
)
if(ClangTidy_FOUND)
message("The found clang tidy supports all requested checks.")
endif()
#!/bin/bash
# Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
# SPDX-License-Identifier: GPL-3.0-only
# First commited by Florian Uhlig
infile=$1
outfile=$2
builddir=$3
CLANG_TIDY_BIN=${CLANG_TIDY_BIN:-clang-tidy}
# special case when a file was deleted
# don't run the test in such a case
if [ ! -e $infile ]; then
exit 0
fi
extension=${infile##*.}
# Only check source or header files
if [ "$extension" == "h" -o "$extension" == "cxx" ]; then
echo "Checking file $infile"
else
exit 0
fi
# Don't do anythink for LinkDef files
if [[ $infile =~ "LinkDef" ]]; then
exit 0
fi
# Check if the file is a target in the compilation database or a header file
# for which the corresponding source file is in the compilation database
if [[ "$extension" == "h" ]]; then
checkfile=${infile%.*}.cxx
else
checkfile=$infile
fi
file=$(grep '"file"' $builddir/compile_commands.json | grep "$checkfile" | cut -d: -f2 | cut -d\" -f2)
if [[ "$file" != "" ]]; then
# create directory if it not yet exist
dir="$(dirname $outfile)"
mkdir -p $dir
OUTPUT=$($CLANG_TIDY_BIN -p $builddir $file 2> $outfile)
else
OUTPUT=""
fi
if [ "$OUTPUT" == "" ]; then
exit 0
else
echo "ERROR: clang-tidy check failed for file $infile. Suggested changes:" > $outfile
echo >> $outfile
echo "$OUTPUT" >> $outfile
echo "ERROR: clang-tidy check failed for file $infile. Suggested changes:"
echo
echo "$OUTPUT"
exit 1
fi
cmake_host_system_information(RESULT fqdn QUERY FQDN)
Set(CTEST_SOURCE_DIRECTORY $ENV{SOURCEDIR})
Set(CTEST_BINARY_DIRECTORY $ENV{BUILDDIR})
Set(CTEST_PROJECT_NAME "CbmRoot")
set(CTEST_CMAKE_GENERATOR "Unix Makefiles")
set(CTEST_USE_LAUNCHERS ON)
Set(CTEST_CONFIGURE_COMMAND " \"${CMAKE_EXECUTABLE_NAME}\" \"-G${CTEST_CMAKE_GENERATOR}\" \"-DCTEST_USE_LAUNCHERS=${CTEST_USE_LAUNCHERS}\" \"-DBUILD_FOR_TIDY=ON\" \"${CTEST_SOURCE_DIRECTORY}\" ")
if ("$ENV{CTEST_SITE}" STREQUAL "")
set(CTEST_SITE "${fqdn}")
else()
set(CTEST_SITE $ENV{CTEST_SITE})
endif()
if ("$ENV{LABEL}" STREQUAL "")
set(CTEST_BUILD_NAME "tidy-check")
else()
set(CTEST_BUILD_NAME $ENV{LABEL})
endif()
ctest_start(Experimental)
ctest_configure(BUILD "${CTEST_BINARY_DIRECTORY}")
ctest_build(TARGET KFPARTICLE PARALLEL_LEVEL $ENV{NCPU})
ctest_build(TARGET ANALYSISTREE PARALLEL_LEVEL $ENV{NCPU})
ctest_build(TARGET GTEST PARALLEL_LEVEL $ENV{NCPU})
ctest_build(TARGET NICAFEMTO PARALLEL_LEVEL $ENV{NCPU})
ctest_build(TARGET TidyCheck PARALLEL_LEVEL $ENV{NCPU})
ctest_submit()
...@@ -3,9 +3,7 @@ ...@@ -3,9 +3,7 @@
# SPDX-License-Identifier: GPL-3.0-only # SPDX-License-Identifier: GPL-3.0-only
# First commited by Florian Uhlig # First commited by Florian Uhlig
BASE_COMMIT=${1:-HEAD}
BASE_COMMIT=${FAIRROOT_FORMAT_BASE:-HEAD}
GIT_CLANG_FORMAT_BIN=${FAIRROOT_GIT_CLANG_FORMAT_BIN:-git-clang-format}
FILES=$(git diff --name-only $BASE_COMMIT | grep -E '.*\.(h|hpp|c|C|cpp|cxx|tpl)$' | grep -viE '.*LinkDef.h$') FILES=$(git diff --name-only $BASE_COMMIT | grep -E '.*\.(h|hpp|c|C|cpp|cxx|tpl)$' | grep -viE '.*LinkDef.h$')
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment