blob: 51830cb7e65111f0467297146c28ff66bbc8c5f5 [file] [log] [blame]
Soby Mathewb4c6df42022-11-09 11:13:29 +00001#
2# SPDX-License-Identifier: BSD-3-Clause
3# SPDX-FileCopyrightText: Copyright TF-RMM Contributors.
4#
5
6#
7# This script is called from main CMakeLists.txt to determine if code complies
8# to coding standards as mentioned in docs/getting_started/coding-standard.rst
9#
10# Runs checkpatch.pl on entire codebase if variable CHECKCODEBASE_RUN is defined.
11#
12# Runs checkpatch.pl on new commits if variable CHECKCODEBASE_RUN is defined.
13#
14find_package(Git REQUIRED)
15find_package(Perl REQUIRED)
16find_program(CHECKPATCH_EXECUTABLE "checkpatch.pl"
17 PATHS ${CMAKE_SOURCE_DIR}
18 PATH_SUFFIXES tools/checkpatch
19 DOC "Path to checkpatch.pl"
20 )
21
22list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/tools/common")
23include(GitUtils)
24
25#
26# List of directories and files to exclude from checking for target checkcodebase
27#
28list(APPEND glob_excludes "^.git")
29list(APPEND glob_excludes "^out")
30list(APPEND glob_excludes "^build")
31list(APPEND glob_excludes "^ext")
32list(APPEND glob_excludes "^tools")
33list(APPEND glob_excludes ".patch$")
34list(APPEND glob_excludes ".md$")
35list(APPEND glob_excludes "~$")
36list(APPEND glob_excludes ".swp$")
37list(APPEND glob_excludes "^cscope.")
38
39set(total_errors "0")
40set(total_warnings "0")
41
42# Check if pre-reqs met
43if(PERL_NOT_FOUND OR NOT EXISTS ${CHECKPATCH_EXECUTABLE})
44 message(FATAL_ERROR "required dependencies not found")
45endif()
46
47#
48# checkpatch_get_stats: Parse and returns number of errors and warnings
49#
50function(checkpatch_get_stats stats_arg errors_ret warnings_ret)
51 string(FIND "${stats_arg}" "total:" idx REVERSE)
52 string(LENGTH "${stats_arg}" len)
53 string(SUBSTRING "${stats_arg}" ${idx} ${len} last_line)
54
55 string(REPLACE " " ";" last_line_list ${last_line})
56 list(GET last_line_list 1 errors)
57 list(GET last_line_list 3 warnings)
58
59 set(${errors_ret} ${errors} PARENT_SCOPE)
60 set(${warnings_ret} ${warnings} PARENT_SCOPE)
61endfunction()
62
63#
64# print_stats_and_exit: Print summary of all errors and warnings.
65# If there are errors call message(FATAL_ERROR)
66#
67function(print_stats_and_exit check_type total_errors total_warnings)
68 message(STATUS "${check_type}: total errors: ${total_errors} "
69 "warnings: ${total_warnings}")
70
71 if(${total_errors} GREATER 0)
72 message(FATAL_ERROR "${check_type}: FAILED")
73 endif()
74
75 message(STATUS "${check_type}: PASSED")
76endfunction()
77
78#
79# Run checkpatch on entire codebase. This verifies all files in this repository
80# except the files listed in "glob_excludes".
81#
82# Exits with FATAL_ERROR upon errors. Warnings are ignored (temporary)
83#
84if(CHECKCODEBASE_RUN)
85 set(source_files "")
86
87 if (GIT_FOUND AND IS_DIRECTORY .git)
88 Git_Get_All_Files(source_files)
89 else()
90 file(GLOB_RECURSE source_files RELATIVE ${CMAKE_SOURCE_DIR} "*")
91 endif()
92
93 # Filter out 'glob_excludes'
94 foreach(exclude IN LISTS glob_excludes)
95 list(FILTER source_files EXCLUDE REGEX "${exclude}")
96 endforeach()
97
98 if(NOT source_files)
99 message(STATUS "checkcodebase: No files to check")
100 return()
101 endif()
102
103 foreach(source_file ${source_files})
104 execute_process(
105 COMMAND ${CMAKE_COMMAND} -E echo "Checking file ${source_file}"
106 )
107
108 execute_process(
109 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
110 COMMAND ${CHECKPATCH_EXECUTABLE} -f ${source_file}
111 OUTPUT_VARIABLE checkpatch_output
112 RESULT_VARIABLE checkpatch_rc
113 ECHO_OUTPUT_VARIABLE
114 OUTPUT_STRIP_TRAILING_WHITESPACE
115 )
116
117 # checkpatch.pl failed for this file. Collect no.of errors and warnings
118 if(${checkpatch_rc})
119 checkpatch_get_stats("${checkpatch_output}" errors warnings)
120 MATH(EXPR total_errors "${total_errors}+${errors}")
121 MATH(EXPR total_warnings "${total_warnings}+${warnings}")
122 endif()
123 endforeach()
124
125 print_stats_and_exit("checkcodebase" ${total_errors}, ${total_warnings})
126endif()
127
128#
129# Run checkpatch on pending commits.
130#
131# Exits with FATAL_ERROR upon errors.
132#
133if(CHECKPATCH_RUN)
134 if(GIT_NOT_FOUND OR NOT IS_DIRECTORY .git)
135 message(FATAL_ERROR "Required dependencies Git not found")
136 endif()
137
138 # Get list of commits to check
139 Git_Get_Pending_Commits(pending_commits)
140
141 foreach(commit IN LISTS pending_commits)
142 message(STATUS "Checking commit: ${commit}")
143
144 execute_process(
145 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
146 COMMAND ${GIT_EXECUTABLE} diff --format=email "${commit}~..${commit}"
147 COMMAND ${CHECKPATCH_EXECUTABLE} -
148 OUTPUT_VARIABLE checkpatch_output
149 RESULT_VARIABLE checkpatch_rc
150 ECHO_OUTPUT_VARIABLE
151 )
152
153 # checkpatch.pl failed for this commit. Collect no.of errors and warnings
154 if(${checkpatch_rc})
155 checkpatch_get_stats("${checkpatch_output}" errors warnings)
156 MATH(EXPR total_errors "${total_errors}+${errors}")
157 MATH(EXPR total_warnings "${total_warnings}+${warnings}")
158 endif()
159 endforeach()
160
161 print_stats_and_exit("checkpatch" ${total_errors}, ${total_warnings})
162endif()