blob: 51830cb7e65111f0467297146c28ff66bbc8c5f5 [file] [log] [blame]
#
# SPDX-License-Identifier: BSD-3-Clause
# SPDX-FileCopyrightText: Copyright TF-RMM Contributors.
#
#
# This script is called from main CMakeLists.txt to determine if code complies
# to coding standards as mentioned in docs/getting_started/coding-standard.rst
#
# Runs checkpatch.pl on entire codebase if variable CHECKCODEBASE_RUN is defined.
#
# Runs checkpatch.pl on new commits if variable CHECKCODEBASE_RUN is defined.
#
find_package(Git REQUIRED)
find_package(Perl REQUIRED)
find_program(CHECKPATCH_EXECUTABLE "checkpatch.pl"
PATHS ${CMAKE_SOURCE_DIR}
PATH_SUFFIXES tools/checkpatch
DOC "Path to checkpatch.pl"
)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/tools/common")
include(GitUtils)
#
# List of directories and files to exclude from checking for target checkcodebase
#
list(APPEND glob_excludes "^.git")
list(APPEND glob_excludes "^out")
list(APPEND glob_excludes "^build")
list(APPEND glob_excludes "^ext")
list(APPEND glob_excludes "^tools")
list(APPEND glob_excludes ".patch$")
list(APPEND glob_excludes ".md$")
list(APPEND glob_excludes "~$")
list(APPEND glob_excludes ".swp$")
list(APPEND glob_excludes "^cscope.")
set(total_errors "0")
set(total_warnings "0")
# Check if pre-reqs met
if(PERL_NOT_FOUND OR NOT EXISTS ${CHECKPATCH_EXECUTABLE})
message(FATAL_ERROR "required dependencies not found")
endif()
#
# checkpatch_get_stats: Parse and returns number of errors and warnings
#
function(checkpatch_get_stats stats_arg errors_ret warnings_ret)
string(FIND "${stats_arg}" "total:" idx REVERSE)
string(LENGTH "${stats_arg}" len)
string(SUBSTRING "${stats_arg}" ${idx} ${len} last_line)
string(REPLACE " " ";" last_line_list ${last_line})
list(GET last_line_list 1 errors)
list(GET last_line_list 3 warnings)
set(${errors_ret} ${errors} PARENT_SCOPE)
set(${warnings_ret} ${warnings} PARENT_SCOPE)
endfunction()
#
# print_stats_and_exit: Print summary of all errors and warnings.
# If there are errors call message(FATAL_ERROR)
#
function(print_stats_and_exit check_type total_errors total_warnings)
message(STATUS "${check_type}: total errors: ${total_errors} "
"warnings: ${total_warnings}")
if(${total_errors} GREATER 0)
message(FATAL_ERROR "${check_type}: FAILED")
endif()
message(STATUS "${check_type}: PASSED")
endfunction()
#
# Run checkpatch on entire codebase. This verifies all files in this repository
# except the files listed in "glob_excludes".
#
# Exits with FATAL_ERROR upon errors. Warnings are ignored (temporary)
#
if(CHECKCODEBASE_RUN)
set(source_files "")
if (GIT_FOUND AND IS_DIRECTORY .git)
Git_Get_All_Files(source_files)
else()
file(GLOB_RECURSE source_files RELATIVE ${CMAKE_SOURCE_DIR} "*")
endif()
# Filter out 'glob_excludes'
foreach(exclude IN LISTS glob_excludes)
list(FILTER source_files EXCLUDE REGEX "${exclude}")
endforeach()
if(NOT source_files)
message(STATUS "checkcodebase: No files to check")
return()
endif()
foreach(source_file ${source_files})
execute_process(
COMMAND ${CMAKE_COMMAND} -E echo "Checking file ${source_file}"
)
execute_process(
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
COMMAND ${CHECKPATCH_EXECUTABLE} -f ${source_file}
OUTPUT_VARIABLE checkpatch_output
RESULT_VARIABLE checkpatch_rc
ECHO_OUTPUT_VARIABLE
OUTPUT_STRIP_TRAILING_WHITESPACE
)
# checkpatch.pl failed for this file. Collect no.of errors and warnings
if(${checkpatch_rc})
checkpatch_get_stats("${checkpatch_output}" errors warnings)
MATH(EXPR total_errors "${total_errors}+${errors}")
MATH(EXPR total_warnings "${total_warnings}+${warnings}")
endif()
endforeach()
print_stats_and_exit("checkcodebase" ${total_errors}, ${total_warnings})
endif()
#
# Run checkpatch on pending commits.
#
# Exits with FATAL_ERROR upon errors.
#
if(CHECKPATCH_RUN)
if(GIT_NOT_FOUND OR NOT IS_DIRECTORY .git)
message(FATAL_ERROR "Required dependencies Git not found")
endif()
# Get list of commits to check
Git_Get_Pending_Commits(pending_commits)
foreach(commit IN LISTS pending_commits)
message(STATUS "Checking commit: ${commit}")
execute_process(
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
COMMAND ${GIT_EXECUTABLE} diff --format=email "${commit}~..${commit}"
COMMAND ${CHECKPATCH_EXECUTABLE} -
OUTPUT_VARIABLE checkpatch_output
RESULT_VARIABLE checkpatch_rc
ECHO_OUTPUT_VARIABLE
)
# checkpatch.pl failed for this commit. Collect no.of errors and warnings
if(${checkpatch_rc})
checkpatch_get_stats("${checkpatch_output}" errors warnings)
MATH(EXPR total_errors "${total_errors}+${errors}")
MATH(EXPR total_warnings "${total_warnings}+${warnings}")
endif()
endforeach()
print_stats_and_exit("checkpatch" ${total_errors}, ${total_warnings})
endif()