diff options
Diffstat (limited to 'modules/ECMCheckOutboundLicense.cmake')
-rw-r--r-- | modules/ECMCheckOutboundLicense.cmake | 153 |
1 files changed, 153 insertions, 0 deletions
diff --git a/modules/ECMCheckOutboundLicense.cmake b/modules/ECMCheckOutboundLicense.cmake new file mode 100644 index 00000000..63e7ca01 --- /dev/null +++ b/modules/ECMCheckOutboundLicense.cmake @@ -0,0 +1,153 @@ +#.rst: +# ECMCheckOutboundLicense +# ----------------------- +# +# Assert that source file licenses are compatible with a desired outbound license +# of a compiled binary artifact (e.g., library, plugin or application). +# +# This module provides the ``ecm_check_outbound_license`` function that +# generates unit tests for checking the compatibility of license statements. +# The license statements in all tested files are required to be added by using +# the SPDX marker ``SPDX-License-Identifier``. +# +# During the CMake configuration of the project, a temporary license bill of +# materials (BOM) in SPDX format is generated by calling the REUSE tool +# (see <https://reuse.software>). That BOM is parsed and license computations +# based on an internal compatibility matrix are performed. +# +# Preconditions for using this module: +# * All tested input source files must contain the SPDX-License-Identifier tag. +# * Python3 must be available. +# * The REUSE tool must be available, which generates the bill-of-materials +# by running ``reuse spdx`` on the tested directory. +# +# When this module is included, a ``SKIP_LICENSE_TESTS`` option is added (default +# OFF). Turning this option on skips the generation of license tests, which might +# be convenient if licenses shall not be tested in all build configurations. +# +# :: +# +# ecm_check_outbound_license(LICENSES <outbound-licenses> +# FILES <source-files> +# [TEST_NAME <name>] +# [WILL_FAIL]) +# +# This method adds a custom unit test to ensure the specified outbound license to be +# compatible with the specified license headers. Note that a convenient way is to use +# the CMake GLOB command of the FILE function. +# +# ``LICENSES`` : List of one or multiple outbound license regarding which the compatibility +# of the source code files shall be tested. Currently, the following values +# are supported (values are SPDX registry identifiers): +# * MIT +# * BSD-2-Clause +# * BSD-3-Clause +# * LGPL-2.0-only +# * LGPL-2.1-only +# * LGPL-3.0-only +# * GPL-2.0-only +# * GPL-3.0-only +# +# ``FILES:`` : List of source files that contain valid SPDX-License-Identifier markers. +# The paths can be relative to the CMake file that generates the test case +# or be absolute paths. +# +# ``TEST_NAME`` : Optional parameter that defines the name of the generated test case. +# If no name is defined, the relative path to the test directory with appended +# license name is used. Every test has ``licensecheck_`` as prefix. +# +# ``WILL_FAIL`` : Optional parameter that inverts the test result. This parameter is usually only +# used for tests of the module. +# +# Since 5.75.0 + +#============================================================================= +# SPDX-FileCopyrightText: 2020 Andreas Cord-Landwehr <cordlandwehr@kde.org> +# SPDX-License-Identifier: BSD-3-Clause + +option(SKIP_LICENSE_TESTS "Skip outbound license tests" OFF) + +find_package(Python3) +set_package_properties(Python3 PROPERTIES + PURPOSE "Required to run tests of module ECMCheckOutboundLicense" + TYPE OPTIONAL +) +find_package(ReuseTool) +set_package_properties(ReuseTool PROPERTIES + PURPOSE "Required to run tests of module ECMCheckOutboundLicense" + TYPE OPTIONAL +) + +if (NOT SKIP_LICENSE_TESTS AND NOT REUSETOOL_FOUND) + add_feature_info(SPDX_LICENSE_TESTING FALSE "Automatic license testing based on SPDX definitions (requires reuse tool)") + message(WARNING "Reuse tool not found, skipping test generation") +else() + add_feature_info(SPDX_LICENSE_TESTING TRUE "Automatic license testing based on SPDX definitions (requires reuse tool)") +endif() + +set(SPDX_BOM_OUTPUT "${CMAKE_BINARY_DIR}/spdx.txt") + +# test fixture for generating SPDX bill of materials +if(SKIP_LICENSE_TESTS OR NOT REUSETOOL_FOUND) + message(STATUS "Skipping execution of outbound license tests.") +else() + add_test( + NAME generate_spdx_bom + COMMAND reuse spdx -o ${SPDX_BOM_OUTPUT} + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + ) + set_tests_properties(generate_spdx_bom PROPERTIES FIXTURES_SETUP SPDX_BOM) +endif() + +function(ecm_check_outbound_license) + if(SKIP_LICENSE_TESTS OR NOT REUSETOOL_FOUND) + return() + endif() + + set(_options WILL_FAIL) + set(_oneValueArgs TEST_NAME) + set(_multiValueArgs LICENSES FILES) + cmake_parse_arguments(ARG "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN} ) + + if(NOT ARG_LICENSES) + message(FATAL_ERROR "No LICENSES argument given to ecm_check_outbound_license") + endif() + + if(NOT ARG_FILES) + message(WARNING "No FILES argument given to ecm_check_outbound_license") + return() + endif() + + if(NOT ARG_TEST_NAME) + # compute test name based on licensecheck_<relative-path>_<licence> if not name given + string(REPLACE "${CMAKE_SOURCE_DIR}/" "" TEMP_TEST_NAME "${CMAKE_CURRENT_SOURCE_DIR}_${ARG_LICENSE}") + string(MAKE_C_IDENTIFIER ${TEMP_TEST_NAME} ARG_TEST_NAME) + endif() + + # generate file with list of relative file paths + string(REPLACE "${CMAKE_BINARY_DIR}/" "" RELATIVE_PREFIX_PATH ${CMAKE_CURRENT_BINARY_DIR}) + set(OUTPUT_FILE ${CMAKE_BINARY_DIR}/licensecheck_${ARG_TEST_NAME}.txt) + message(STATUS "Generate test input file: ${OUTPUT_FILE}") + file(REMOVE ${OUTPUT_FILE}) + foreach(_file ${ARG_FILES}) + # check script expects files to start with "./", which must be relative to CMAKE_SOURCE_DIR + if (IS_ABSOLUTE ${_file}) + string(REPLACE ${CMAKE_SOURCE_DIR} "." TEMPORARY_PATH ${_file}) + file(APPEND ${OUTPUT_FILE} "${TEMPORARY_PATH}\n") + else() + file(APPEND ${OUTPUT_FILE} "./${RELATIVE_PREFIX_PATH}/${_file}\n") + endif() + endforeach() + + file(COPY ${ECM_MODULE_DIR}/check-outbound-license.py DESTINATION ${CMAKE_BINARY_DIR}) + + foreach(_license ${ARG_LICENSES}) + string(MAKE_C_IDENTIFIER ${_license} LICENSE_ID) + add_test( + NAME licensecheck_${ARG_TEST_NAME}_${LICENSE_ID} + COMMAND python3 ${CMAKE_BINARY_DIR}/check-outbound-license.py -l ${_license} -s ${SPDX_BOM_OUTPUT} -i ${OUTPUT_FILE} + ) + set_tests_properties(licensecheck_${ARG_TEST_NAME}_${LICENSE_ID} PROPERTIES FIXTURES_REQUIRED SPDX_BOM) + set_tests_properties(licensecheck_${ARG_TEST_NAME}_${LICENSE_ID} PROPERTIES WILL_FAIL ${ARG_WILL_FAIL}) + endforeach() +endfunction() |