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}/tools/common") 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 ECHO_OUTPUT_VARIABLE 80 OUTPUT_STRIP_TRAILING_WHITESPACE 81 ) 82 83 # checkspdx failed for this file. Collect no.of errors 84 if(${checkspdx_rc} GREATER 0) 85 checkspdx_get_stats("${checkspdx_output}" errors) 86 endif() 87 88 set(${errors_ret} ${errors} PARENT_SCOPE) 89endfunction() 90 91# 92# Run checkspdx on entire codebase. This verifies all files in this repository 93# except the files listed in "glob_excludes". 94# 95# Exits with FATAL_ERROR upon errors. Warnings are ignored (temporary) 96# 97if(CHECKSPDX_CODEBASE) 98 set(source_files "") 99 100 if (GIT_FOUND AND IS_DIRECTORY .git) 101 Git_Get_All_Files(source_files) 102 else() 103 file(GLOB_RECURSE source_files RELATIVE ${CMAKE_SOURCE_DIR} "*") 104 endif() 105 106 # Filter out 'glob_excludes' 107 foreach(exclude IN LISTS glob_excludes) 108 list(FILTER source_files EXCLUDE REGEX "${exclude}") 109 endforeach() 110 111 if(NOT source_files) 112 message(STATUS "check-spdx-codebase: No files to check") 113 return() 114 endif() 115 116 run_checkspdx("${source_files}" total_errors) 117 print_stats_and_exit("checkspdx-codebase" ${total_errors}) 118endif() 119 120# 121# Check SPDX complaiance on pending commits. 122# 123# Exits with FATAL_ERROR upon errors. 124# 125if(CHECKSPDX_PATCH) 126 if(GIT_NOT_FOUND OR NOT IS_DIRECTORY .git) 127 message(FATAL_ERROR "Required dependencies Git not found") 128 endif() 129 130 # Get list of commits to check 131 Git_Get_Pending_Commits(pending_commits) 132 133 # Iterate throuth list of commit ids 134 set(total_errors 0) 135 foreach(commit IN LISTS pending_commits) 136 message(STATUS "Checking commit: ${commit}") 137 138 Git_Get_Files_In_Commit("${commit}" source_files) 139 140 foreach(exclude IN LISTS glob_excludes) 141 list(FILTER source_files EXCLUDE REGEX "${exclude}") 142 endforeach() 143 144 run_checkspdx("${source_files}" errors) 145 MATH(EXPR total_errors "${total_errors}+${errors}") 146 endforeach() 147 148 print_stats_and_exit("checkspdx-patch" ${total_errors}) 149endif() 150