vtk-m/CMake/VTKmCheckCopyright.cmake
Kenneth Moreland 898115a410 Add copyright notice to scipts and configuration files
There are numerous scripts and configuration files defined in the CI setup
and elsewhere that were missing the copyright statement. Add more types
of files to check in the CopyrightStatement test, and update the files
with the appropriate statement.
2023-07-25 11:05:40 -06:00

239 lines
7.7 KiB
CMake

##============================================================================
## Copyright (c) Kitware, Inc.
## All rights reserved.
## See LICENSE.txt for details.
##
## This software is distributed WITHOUT ANY WARRANTY; without even
## the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
## PURPOSE. See the above copyright notice for more information.
##============================================================================
## This CMake script checks source files for the appropriate VTKM copyright
## statement, which is stored in VTKm_SOURCE_DIR/CMake/VTKmCopyrightStatement.txt.
## To run this script, execute CMake as follows:
##
## cmake -DVTKm_SOURCE_DIR=<VTKm_SOURCE_DIR> -P <VTKm_SOURCE_DIR>/CMake/VTKMCheckCopyright.cmake
##
cmake_minimum_required(VERSION 3.12)
set(FILES_TO_CHECK
*.txt
*.cmake
*.h
*.h.in
*.hxx
*.cxx
*.cu
*.py
*.sh
*.ps1
Dockerfile
*.yaml
*.yml
)
set(EXCEPTIONS
LICENSE.txt
README.txt
)
if (NOT VTKm_SOURCE_DIR)
message(SEND_ERROR "VTKm_SOURCE_DIR not defined.")
endif (NOT VTKm_SOURCE_DIR)
set(copyright_file ${VTKm_SOURCE_DIR}/CMake/VTKmCopyrightStatement.txt)
if (NOT EXISTS ${copyright_file})
message(SEND_ERROR "Cannot find VTKMCopyrightStatement.txt.")
endif (NOT EXISTS ${copyright_file})
set(license_file ${VTKm_SOURCE_DIR}/LICENSE.txt)
if (NOT EXISTS ${license_file})
message(SEND_ERROR "Cannot find LICENSE.txt.")
endif (NOT EXISTS ${license_file})
# Get a list of third party files (with different copyrights) from the
# license file.
file(STRINGS ${license_file} license_lines)
list(FIND
license_lines
"- - - - - - - - - - - - - - - - - - - - - - - - do not remove this line"
separator_index
)
math(EXPR begin_index "${separator_index} + 1")
list(LENGTH license_lines license_file_length)
math(EXPR end_index "${license_file_length} - 1")
foreach (index RANGE ${begin_index} ${end_index})
list(GET license_lines ${index} tpl_file)
set(EXCEPTIONS ${EXCEPTIONS} ${tpl_file})
endforeach(index)
# if the build directory is in the source directory, exclude generated build
# files
find_path(BUILD_DIR CMakeCache.txt .)
get_filename_component(abs_build_dir ${BUILD_DIR} ABSOLUTE)
get_filename_component(build_dir_name ${abs_build_dir} NAME)
set(EXCEPTIONS ${EXCEPTIONS} ${build_dir_name}/*)
message("Copyright Check Exceptions: ${EXCEPTIONS}")
# Gets the current year (if possible).
function (get_year var)
string(TIMESTAMP result "%Y")
set(${var} "${result}" PARENT_SCOPE)
endfunction (get_year)
set(copyright_file_year 2014)
get_year(current_year)
# Escapes ';' characters (list delimiters) and splits the given string into
# a list of its lines without newlines.
function (list_of_lines var string)
string(REGEX REPLACE ";" "\\\\;" conditioned_string "${string}")
string(REGEX REPLACE "\n" ";" conditioned_string "${conditioned_string}")
set(${var} "${conditioned_string}" PARENT_SCOPE)
endfunction (list_of_lines)
# Read in copyright statement file.
file(READ ${copyright_file} COPYRIGHT_STATEMENT)
# Remove trailing whitespace and ending lines. They are sometimes hard to
# see or remove in editors.
string(REGEX REPLACE "[ \t]*\n" "\n" COPYRIGHT_STATEMENT "${COPYRIGHT_STATEMENT}")
string(REGEX REPLACE "\n+$" "" COPYRIGHT_STATEMENT "${COPYRIGHT_STATEMENT}")
# Get a list of lines in the copyright statement.
list_of_lines(COPYRIGHT_LINE_LIST "${COPYRIGHT_STATEMENT}")
# Comment regular expression characters that we want to match literally.
string(REPLACE "." "\\." COPYRIGHT_LINE_LIST "${COPYRIGHT_LINE_LIST}")
string(REPLACE "(" "\\(" COPYRIGHT_LINE_LIST "${COPYRIGHT_LINE_LIST}")
string(REPLACE ")" "\\)" COPYRIGHT_LINE_LIST "${COPYRIGHT_LINE_LIST}")
# Introduce regular expression for years we want to be generic.
string(REPLACE
"${copyright_file_year}"
"20[0-9][0-9]"
COPYRIGHT_LINE_LIST
"${COPYRIGHT_LINE_LIST}"
)
# Replace year in COPYRIGHT_STATEMENT with current year.
string(REPLACE
"${copyright_file_year}"
"${current_year}"
COPYRIGHT_STATEMENT
"${COPYRIGHT_STATEMENT}"
)
# Print an error concerning the missing copyright in the given file.
function(missing_copyright filename comment_prefix)
message("${filename} does not have the appropriate copyright statement:\n")
# Condition the copyright statement
string(REPLACE
"\n"
"\n${comment_prefix} "
comment_copyright
"${COPYRIGHT_STATEMENT}"
)
set(comment_copyright "${comment_prefix} ${comment_copyright}")
string(REPLACE
"\n${comment_prefix} \n"
"\n${comment_prefix}\n"
comment_copyright
"${comment_copyright}"
)
message("${comment_prefix}=============================================================================")
message("${comment_prefix}")
message("${comment_copyright}")
message("${comment_prefix}")
message("${comment_prefix}=============================================================================\n")
message(SEND_ERROR
"Please add the previous statement to the beginning of ${filename}"
)
endfunction(missing_copyright)
# Get an appropriate beginning line comment for the given filename.
function(get_comment_prefix var filename)
get_filename_component(name "${filename}" NAME)
if(name MATCHES "\\.(cmake|py|sh|ps1|yaml|yml)$"
OR name STREQUAL "CMakeLists.txt"
OR name STREQUAL "Dockerfile"
)
set(${var} "##" PARENT_SCOPE)
elseif (name MATCHES "\\.(h|h\\.in|hxx|cxx|cu)$")
set(${var} "//" PARENT_SCOPE)
elseif (name MATCHES "\\.txt$")
set(${var} "" PARENT_SCOPE)
else ()
message(FATAL_ERROR "Could not identify file type of `${name}`.")
endif ()
endfunction(get_comment_prefix)
# Check the given file for the appropriate copyright statement.
function(check_copyright filename)
get_comment_prefix(comment_prefix "${filename}")
# Read in the first 2000 characters of the file and split into lines.
# This is roughly equivalent to the file STRINGS command except that we
# also escape semicolons (list separators) in the input, which the file
# STRINGS command does not currently do.
file(READ "${filename}" header_contents LIMIT 2000)
list_of_lines(header_lines "${header_contents}")
set(printed)
# Check each copyright line.
foreach (copyright_line IN LISTS COPYRIGHT_LINE_LIST)
set(match)
# My original algorithm tried to check the order by removing items from
# header_lines as they were encountered. Unfortunately, CMake 2.8's
# list REMOVE_AT command removed the escaping on the ; in one of the
# header_line's items and cause the compare to fail.
foreach (header_line IN LISTS header_lines)
if (copyright_line)
string(REGEX MATCH
"^${comment_prefix}[ \t]*${copyright_line}[ \t]*$"
match
"${header_line}"
)
else (copyright_line)
if (NOT header_line)
set(match TRUE)
endif (NOT header_line)
endif (copyright_line)
if (match)
break()
endif (match)
endforeach (header_line)
if (NOT match AND NOT printed)
message(STATUS "Could not find match for `${copyright_line}'")
missing_copyright("${filename}" "${comment_prefix}")
set(printed TRUE)
endif (NOT match AND NOT printed)
endforeach (copyright_line)
endfunction(check_copyright)
foreach (glob_expression ${FILES_TO_CHECK})
file(GLOB_RECURSE file_list
RELATIVE "${VTKm_SOURCE_DIR}"
"${VTKm_SOURCE_DIR}/${glob_expression}"
)
foreach (file ${file_list})
set(skip)
foreach(exception ${EXCEPTIONS})
if(file MATCHES "^${exception}(/.*)?$")
# This file is an exception
set(skip TRUE)
endif(file MATCHES "^${exception}(/.*)?$")
endforeach(exception)
if (NOT skip)
check_copyright("${VTKm_SOURCE_DIR}/${file}")
endif (NOT skip)
endforeach (file)
endforeach (glob_expression)