1# 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 SPDX headers 8# are in proper format 9# 10find_package(Git REQUIRED) 11find_package(Python3 REQUIRED) 12find_program(CHECKSPDX_EXECUTABLE "checkspdx.py" 13 PATHS ${CMAKE_SOURCE_DIR} 14 PATH_SUFFIXES tools/checkspdx 15 DOC "Path to checkspdx.py" 16 ) 17 18list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/Modules") 19include(GitUtils) 20 21# List of directories and files to exclude from checking for target 22list(APPEND glob_excludes "^.git") 23list(APPEND glob_excludes "^out") 24list(APPEND glob_excludes "^build") 25list(APPEND glob_excludes "^ext") 26list(APPEND glob_excludes "^tools") 27list(APPEND glob_excludes ".patch$") 28list(APPEND glob_excludes ".md$") 29list(APPEND glob_excludes "~$") 30list(APPEND glob_excludes ".swp$") 31list(APPEND glob_excludes "^cscope.") 32list(APPEND glob_excludes ".png$") 33list(APPEND glob_excludes "LICENSE") 34list(APPEND glob_excludes "DCO") 35list(APPEND glob_excludes "docs/global_substitutions.txt") 36 37# checkspdx_get_stats: Parse and returns number of errors and warnings 38function(checkspdx_get_stats stats_arg errors_ret) 39 string(FIND "${stats_arg}" "total:" idx REVERSE) 40 if(NOT ${idx} EQUAL -1) 41 string(LENGTH "${stats_arg}" len) 42 string(SUBSTRING "${stats_arg}" ${idx} ${len} last_line) 43 44 string(REPLACE " " ";" last_line_list ${last_line}) 45 list(GET last_line_list 1 errors) 46 else() 47 set(errors 1) 48 endif() 49 50 set(${errors_ret} ${errors} PARENT_SCOPE) 51endfunction() 52 53# 54# print_stats_and_exit: Print summary of all errors and warnings. 55# If there are errors call message(FATAL_ERROR) 56# 57function(print_stats_and_exit check_type total_errors) 58 message(STATUS "${check_type}: total errors: ${total_errors}") 59 60 if(${total_errors} GREATER 0) 61 message(FATAL_ERROR "${check_type}: FAILED") 62 endif() 63 64 message(STATUS "${check_type}: PASSED") 65endfunction() 66 67# Run checkspdx.py on the list of files. 68function(run_checkspdx source_files errors_ret) 69 set(errors 0) 70 71 string(REPLACE ";" " " source_files "${source_files}") 72 separate_arguments(source_files NATIVE_COMMAND "${source_files}") 73 74 execute_process( 75 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} 76 COMMAND ${CHECKSPDX_EXECUTABLE} -r docs/readme.rst ${source_files} 77 OUTPUT_VARIABLE checkspdx_output 78 RESULT_VARIABLE checkspdx_rc 79 OUTPUT_STRIP_TRAILING_WHITESPACE 80 ) 81 82 if(checkspdx_output) 83 message(${checkspdx_output}) 84 endif() 85 86 # checkspdx failed for this file. Collect no.of errors 87 if(${checkspdx_rc} GREATER 0) 88 checkspdx_get_stats("${checkspdx_output}" errors) 89 endif() 90 91 set(${errors_ret} ${errors} PARENT_SCOPE) 92endfunction() 93 94# 95# Run checkspdx on entire codebase. This verifies all files in this repository 96# except the files listed in "glob_excludes". 97# 98# Exits with FATAL_ERROR upon errors. Warnings are ignored (temporary) 99# 100if(CHECKSPDX_CODEBASE) 101 set(source_files "") 102 103 if (GIT_FOUND AND IS_DIRECTORY .git) 104 Git_Get_All_Files(source_files) 105 else() 106 file(GLOB_RECURSE source_files RELATIVE ${CMAKE_SOURCE_DIR} "*") 107 endif() 108 109 # Filter out 'glob_excludes' 110 foreach(exclude IN LISTS glob_excludes) 111 list(FILTER source_files EXCLUDE REGEX "${exclude}") 112 endforeach() 113 114 if(NOT source_files) 115 message(STATUS "check-spdx-codebase: No files to check") 116 return() 117 endif() 118 119 run_checkspdx("${source_files}" total_errors) 120 print_stats_and_exit("checkspdx-codebase" ${total_errors}) 121endif() 122 123# 124# Check SPDX complaiance on pending commits. 125# 126# Exits with FATAL_ERROR upon errors. 127# 128if(CHECKSPDX_PATCH) 129 if(GIT_NOT_FOUND OR NOT IS_DIRECTORY .git) 130 message(FATAL_ERROR "Required dependencies Git not found") 131 endif() 132 133 # Get list of commits to check 134 Git_Get_Pending_Commits(pending_commits) 135 136 # Iterate throuth list of commit ids 137 set(total_errors 0) 138 foreach(commit IN LISTS pending_commits) 139 message(STATUS "Checking commit: ${commit}") 140 141 Git_Get_Files_In_Commit("${commit}" source_files) 142 143 foreach(exclude IN LISTS glob_excludes) 144 list(FILTER source_files EXCLUDE REGEX "${exclude}") 145 endforeach() 146 147 # run check if the list is not empty 148 if(source_files) 149 run_checkspdx("${source_files}" errors) 150 MATH(EXPR total_errors "${total_errors}+${errors}") 151 endif() 152 endforeach() 153 154 print_stats_and_exit("checkspdx-patch" ${total_errors}) 155endif() 156