From 8edd03928be398ff93778bf02077af09183da867 Mon Sep 17 00:00:00 2001 From: Fabian Ruffy <5960321+fruffy@users.noreply.github.com> Date: Fri, 10 May 2024 17:32:33 +0200 Subject: [PATCH] Add support for a clang-tidy linter. Add a files utility function. (#4254) --- .clang-tidy | 1 + CMakeLists.txt | 2 +- cmake/Linters.cmake | 59 ++++++++++++++++++++++++++++++------ cmake/P4CUtils.cmake | 72 ++++++++++++++------------------------------ 4 files changed, 73 insertions(+), 61 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index fa751c7ccd..b5b1e7ed2e 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -13,6 +13,7 @@ misc-*, llvm-*, google-*, -modernize-use-trailing-return-type, +-misc-confusable-identifiers, -readability-identifier-length, -cppcoreguidelines-owning-memory, -bugprone-easily-swappable-parameters, diff --git a/CMakeLists.txt b/CMakeLists.txt index 7337ee2cba..01451f6c97 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -367,9 +367,9 @@ else() endif() include_directories ( - ${P4C_SOURCE_DIR}/extensions ${P4C_SOURCE_DIR} ${P4C_BINARY_DIR} + ${P4C_SOURCE_DIR}/extensions ) add_definitions (-DCONFIG_PREFIX="${CMAKE_INSTALL_PREFIX}") add_definitions (-DCONFIG_PKGDATADIR="${CMAKE_INSTALL_PREFIX}/${P4C_ARTIFACTS_OUTPUT_DIRECTORY}") diff --git a/cmake/Linters.cmake b/cmake/Linters.cmake index 7382f0c766..e0268b48d9 100644 --- a/cmake/Linters.cmake +++ b/cmake/Linters.cmake @@ -18,7 +18,6 @@ file( tools/*.h ) # Filter some folders from the CI checks. -list(FILTER P4C_LINT_LIST EXCLUDE REGEX "backends/p4tools/submodules") list(FILTER P4C_LINT_LIST EXCLUDE REGEX "backends/ebpf/runtime") list(FILTER P4C_LINT_LIST EXCLUDE REGEX "backends/ubpf/runtime") list(FILTER P4C_LINT_LIST EXCLUDE REGEX "control-plane/p4runtime") @@ -29,7 +28,7 @@ list(FILTER P4C_LINT_LIST EXCLUDE REGEX "test/frameworks") add_cpplint_files(${P4C_SOURCE_DIR} "${P4C_LINT_LIST}") # Retrieve the global cpplint property. -get_property(CPPLINT_FILES GLOBAL PROPERTY cpplint-files) +get_property(CPPLINT_FILES GLOBAL PROPERTY CPPLINT-files) if(DEFINED CPPLINT_FILES) # Write the list to a file. We need to do this as too many files will reach @@ -58,17 +57,15 @@ endif() add_clang_format_files(${P4C_SOURCE_DIR} "${P4C_LINT_LIST}") find_program(CLANG_FORMAT_CMD clang-format) - -if(NOT ${CLANG_FORMAT_CMD}) +if(CLANG_FORMAT_CMD) # Retrieve the global clang-format property. - get_property(CLANG_FORMAT_FILES GLOBAL PROPERTY clang-format-files) + get_property(CLANG_FORMAT_FILES GLOBAL PROPERTY CLANG_FORMAT-files) if(DEFINED CLANG_FORMAT_FILES) # Write the list to a file. # We need to do this as too many files will reach the shell argument limit. set(CLANG_FORMAT_TXT_FILE ${P4C_BINARY_DIR}/clang_format_files.txt) list(SORT CLANG_FORMAT_FILES) file(WRITE ${CLANG_FORMAT_TXT_FILE} "${CLANG_FORMAT_FILES}") - set(CLANG_FORMAT_CMD clang-format) add_custom_target( clang-format COMMAND xargs -a ${CLANG_FORMAT_TXT_FILE} -r -d '\;' ${CLANG_FORMAT_CMD} --verbose --Werror --dry-run -i -- || (echo ${RED}clang-format failed. Run \"make clang-format-fix-errors\" to fix the complaints.${COLOURRESET} && false) @@ -83,7 +80,49 @@ if(NOT ${CLANG_FORMAT_CMD}) ) endif() else() - message(WARNING "clang-format executable not found. Disabling clang-format checks. clang-format can be installed with \"pip3 install --user --upgrade clang-format\"") + message(WARNING "clang-format executable not found. Disabling clang-format checks. clang-format can be installed with \"pip3 install --user --upgrade clang-format\" or your distribution's package manager.") +endif() + + +#################### CLANG-TIDY + +# TODO: Add files here once clang-tidy is fast enough. +# file( +# GLOB_RECURSE P4C_CLANG_TIDY_LINT_LIST FOLLOW_SYMLINKS +# ) +# add_clang_tidy_files(${P4C_SOURCE_DIR} "${P4C_CLANG_TIDY_LINT_LIST}") + +find_program(CLANG_TIDY_CMD clang-tidy) + +if(CLANG_TIDY_CMD) + if (NOT CMAKE_EXPORT_COMPILE_COMMANDS) + message(WARNING "CMAKE_EXPORT_COMPILE_COMMANDS is not set ON, clang-tidy remains disabled.") + endif() + + # Retrieve the global clang-tidy property. + get_property(CLANG_TIDY_FILES GLOBAL PROPERTY CLANG_TIDY-files) + if(DEFINED CLANG_TIDY_FILES AND CMAKE_EXPORT_COMPILE_COMMANDS) + + # Write the list to a file. + # We need to do this as too many files will reach the shell argument limit. + set(CLANG_TIDY_TXT_FILE ${P4C_BINARY_DIR}/clang_tidy_files.txt) + list(SORT CLANG_TIDY_FILES) + file(WRITE ${CLANG_TIDY_TXT_FILE} "${CLANG_TIDY_FILES}") + add_custom_target( + clang-tidy + COMMAND xargs -a ${CLANG_TIDY_TXT_FILE} -r -d '\;' ${CLANG_TIDY_CMD} -p ${CMAKE_BINARY_DIR} + WORKING_DIRECTORY ${P4C_SOURCE_DIR} + COMMENT "Applying clang-tidy analysis." + ) + add_custom_target( + clang-tidy-apply-fix-its + COMMAND xargs -a ${CLANG_TIDY_TXT_FILE} -r -d '\;' ${CLANG_TIDY_CMD} -p ${CMAKE_BINARY_DIR} --fix + WORKING_DIRECTORY ${P4C_SOURCE_DIR} + COMMENT "Applying clang-tidy fix-its." + ) + endif() +else() + message(WARNING "clang-tidy executable not found. Disabling clang-tidy checks. clang-tidy can be installed with \"pip3 install --user --upgrade clang-tidy\" or your distribution's package manager.") endif() @@ -105,9 +144,9 @@ find_program(BLACK_CMD black) find_program(ISORT_CMD isort) # Black and isort share the same files and should be run together. -if(NOT ${BLACK_CMD} OR NOT (NOT ${ISORT_CMD})) +if(BLACK_CMD AND ISORT_CMD) # Retrieve the global black property. - get_property(BLACK_FILES GLOBAL PROPERTY black-files) + get_property(BLACK_FILES GLOBAL PROPERTY BLACK-files) if(DEFINED BLACK_FILES) # Write the list to a file. # We need to do this as too many files will reach the shell argument limit. @@ -141,7 +180,7 @@ if(NOT ${BLACK_CMD} OR NOT (NOT ${ISORT_CMD})) ) endif() else() - message(WARNING "black or isort executable not found. Disabling black/isort checks. black/isort can be installed with \"pip3 install --user --upgrade black\" and \"pip3 install --user --upgrade isort\" ") + message(WARNING "black or isort executable not found. Disabling black/isort checks. black/isort can be installed with \"pip3 install --user --upgrade black\" and \"pip3 install --user --upgrade isort\" or your distribution's package manager. ") endif() #################### IWYU diff --git a/cmake/P4CUtils.cmake b/cmake/P4CUtils.cmake index 0029d94554..509c90f7b1 100644 --- a/cmake/P4CUtils.cmake +++ b/cmake/P4CUtils.cmake @@ -67,76 +67,48 @@ macro (p4c_add_library name symbol var) endif() endmacro(p4c_add_library) -# Add files with the appropriate path to the list of cpplint-linted files. -function(add_cpplint_files dir filelist) +# Utility function which adds @param filelist to a global list of ${label}-files +function(add_files dir filelist label) if (NOT filelist) message(WARNING "Input file list is empty. Returning.") return() endif() # Initialize an empty list. - set (__cpplintFileList "") + set (__FileList "") foreach(__f ${filelist}) string(REGEX MATCH "^/.*" abs_path "${__f}") if (NOT ${abs_path} EQUAL "") - list (APPEND __cpplintFileList "${__f}") + list (APPEND __FileList "${__f}") else() - list (APPEND __cpplintFileList "${dir}/${__f}") + list (APPEND __FileList "${dir}/${__f}") endif() endforeach(__f) - # Get the global cpplint property and append to it. - get_property(CPPLINT_FILES GLOBAL PROPERTY cpplint-files) - list (APPEND CPPLINT_FILES "${__cpplintFileList}") - list(REMOVE_DUPLICATES CPPLINT_FILES) - set_property(GLOBAL PROPERTY cpplint-files "${CPPLINT_FILES}") + # Get the global label property and append to it. + get_property(${label}_FILES GLOBAL PROPERTY ${label}-files) + list (APPEND ${label}_FILES "${__FileList}") + list(REMOVE_DUPLICATES ${label}_FILES) + set_property(GLOBAL PROPERTY ${label}-files "${${label}_FILES}") +endfunction(add_files) + +# Add files with the appropriate path to the list of cpplint-linted files. +function(add_cpplint_files dir filelist) + add_files(${dir} "${filelist}" CPPLINT) endfunction(add_cpplint_files) # Add files with the appropriate path to the list of clang-format-linted files. function(add_clang_format_files dir filelist) - if (NOT filelist) - message(WARNING "Input file list is empty. Returning.") - return() - endif() - # Initialize an empty list. - set (__clangFormatFileList "") - foreach(__f ${filelist}) - string(REGEX MATCH "^/.*" abs_path "${__f}") - if (NOT ${abs_path} EQUAL "") - list (APPEND __clangFormatFileList "${__f}") - else() - list (APPEND __clangFormatFileList "${dir}/${__f}") - endif() - endforeach(__f) - - # Get the global clang-format property and append to it. - get_property(CLANG_FORMAT_FILES GLOBAL PROPERTY clang-format-files) - list (APPEND CLANG_FORMAT_FILES "${__clangFormatFileList}") - list(REMOVE_DUPLICATES CLANG_FORMAT_FILES) - set_property(GLOBAL PROPERTY clang-format-files "${CLANG_FORMAT_FILES}") + add_files(${dir} "${filelist}" CLANG_FORMAT) endfunction(add_clang_format_files) +# Add files with the appropriate path to the list of clang-tidy-linted files. +function(add_clang_tidy_files dir filelist) + add_files(${dir} "${filelist}" CLANG_TIDY) +endfunction(add_clang_tidy_files) + # Add files with the appropriate path to the list of black-linted files. function(add_black_files dir filelist) - if (NOT filelist) - message(WARNING "Input file list is empty. Returning.") - return() - endif() - # Initialize an empty list. - set (__blackFileList "") - foreach(__f ${filelist}) - string(REGEX MATCH "^/.*" abs_path "${__f}") - if (NOT ${abs_path} EQUAL "") - list (APPEND __blackFileList "${__f}") - else() - list (APPEND __blackFileList "${dir}/${__f}") - endif() - endforeach(__f) - - # Get the global clang-format property and append to it. - get_property(BLACK_FILES GLOBAL PROPERTY black-files) - list (APPEND BLACK_FILES "${__blackFileList}") - list(REMOVE_DUPLICATES BLACK_FILES) - set_property(GLOBAL PROPERTY black-files "${BLACK_FILES}") + add_files(${dir} "${filelist}" BLACK) endfunction(add_black_files) macro(p4c_test_set_name name tag alias)