aboutsummaryrefslogtreecommitdiff
path: root/modules/ECMCheckOutboundLicense.cmake
diff options
context:
space:
mode:
Diffstat (limited to 'modules/ECMCheckOutboundLicense.cmake')
-rw-r--r--modules/ECMCheckOutboundLicense.cmake153
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()