CMake: Improve license handling for SBOMs

Add a NO_ATTRIBUTION_LICENSE_ID option to allow to skip including
license references from qt_attribution.json files.

Add a QT_LICENSE_ID option that can take an "id" value and return one
of the common license expressions we use throughout Qt repositories:
- GPL3 with exception for tools / apps
- GFDL for documentation
- GPL3 only modules
etc.

Add a QT_SBOM_DEFAULT_QT_LICENSE_ID_LIBRARIES variable that can be set
at directory scope (or root repo scope) to use a specific license id
for all qt modules / plugins created within that repo, e.g. the
Commercial + GPL3 variant. These can be opted out, to fallback to the
"default" license by passing NO_DEFAULT_QT_LICENSE_ID_LIBRARIES.

Add a similar variable  QT_SBOM_DEFAULT_QT_LICENSE_ID_EXECUTABLES
for tools / apps, including a NO_DEFAULT_QT_LICENSE_ID_EXECUTABLES
option.

Modify the logic for setting licenses for qt targets:
- use whatever is set in QT_SBOM_DEFAULT_QT_LICENSE_EXECUTABLES
  for tools and apps
- or use the 'GPL3 with exception' variant for tools and apps
- use whatever is set in QT_SBOM_DEFAULT_QT_LICENSE_LIBARRIES for
  modules ands plugins
- or use the default Commercial + LGPL3 + GPL variant for
  modules and plugins

Amends 37a5e001277db9e1392a242171ab2b88cb6c3049

Task-number: QTBUG-122899
Change-Id: I3a8abac62b9f4b342f91ef139064884f02aa935e
Reviewed-by:  Alexey Edelev <alexey.edelev@qt.io>
(cherry picked from commit fe90ba704168d47cf88d0c6512380b525f38f5d3)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Alexandru Croitor 2024-06-14 17:51:12 +02:00 committed by Qt Cherry-pick Bot
parent 9be3d7a7a0
commit aea52288d6

View File

@ -267,7 +267,10 @@ endfunction()
macro(_qt_internal_get_sbom_add_target_common_options opt_args single_args multi_args)
set(${opt_args}
NO_CURRENT_DIR_ATTRIBUTION
NO_ATTRIBUTION_LICENSE_ID
NO_DEFAULT_QT_LICENSE
NO_DEFAULT_QT_LICENSE_ID_LIBRARIES
NO_DEFAULT_QT_LICENSE_ID_EXECUTABLES
NO_DEFAULT_DIRECTORY_QT_LICENSE
NO_DEFAULT_QT_COPYRIGHTS
NO_DEFAULT_QT_PACKAGE_VERSION
@ -279,6 +282,7 @@ macro(_qt_internal_get_sbom_add_target_common_options opt_args single_args multi
CPE_VENDOR
CPE_PRODUCT
LICENSE_EXPRESSION
QT_LICENSE_ID
DOWNLOAD_LOCATION
ATTRIBUTION_ENTRY_INDEX
)
@ -392,21 +396,58 @@ function(_qt_internal_sbom_add_target target)
_qt_internal_sbom_handle_qt_attribution_files(qa ${attribution_args})
# Collect license expressions, but each expression needs to be abided, so we AND them.
# Collect license expressions, but in most cases, each expression needs to be abided, so we
# AND the accumulated license expressions.
set(license_expression "")
if(arg_LICENSE_EXPRESSION)
set(license_expression "${arg_LICENSE_EXPRESSION}")
endif()
if(is_qt_entity_type AND NOT arg_NO_DEFAULT_QT_LICENSE)
_qt_internal_sbom_get_default_qt_license_id(qt_license_expression)
# For Qt entities, we have some special handling.
if(is_qt_entity_type AND NOT arg_NO_DEFAULT_QT_LICENSE AND NOT arg_QT_LICENSE_ID)
if(arg_TYPE STREQUAL "QT_TOOL" OR arg_TYPE STREQUAL "QT_APP")
if(QT_SBOM_DEFAULT_QT_LICENSE_ID_EXECUTABLES
AND NOT arg_NO_DEFAULT_QT_LICENSE_ID_EXECUTABLES)
# A repo might contain only the "gpl3" license variant as the default for all
# executables, so allow setting it at the repo level to avoid having to repeat it
# for each target.
_qt_internal_sbom_get_spdx_license_expression(
"${QT_SBOM_DEFAULT_QT_LICENSE_ID_EXECUTABLES}" qt_license_expression)
else()
# For tools and apps, we use the gpl exception variant by default.
_qt_internal_sbom_get_spdx_license_expression("QT_COMMERCIAL_OR_GPL3_WITH_EXCEPTION"
qt_license_expression)
endif()
elseif(QT_SBOM_DEFAULT_QT_LICENSE_ID_LIBRARIES
AND NOT arg_NO_DEFAULT_QT_LICENSE_ID_LIBRARIES)
# A repo might contain only the "gpl3" license variant as the default for all modules
# and plugins, so allow setting it at the repo level to avoid having to repeat it
# for each target.
_qt_internal_sbom_get_spdx_license_expression(
"${QT_SBOM_DEFAULT_QT_LICENSE_ID_LIBRARIES}" qt_license_expression)
else()
# Otherwise, for modules and plugins we use the default qt license.
_qt_internal_sbom_get_spdx_license_expression("QT_DEFAULT" qt_license_expression)
endif()
_qt_internal_sbom_join_two_license_ids_with_op(
"${license_expression}" "AND" "${qt_license_expression}"
license_expression)
endif()
# Allow setting a license expression per directory scope via a variable.
# Some Qt entities might request a specific license from the subset that we usually use.
if(arg_QT_LICENSE_ID)
_qt_internal_sbom_get_spdx_license_expression("${arg_QT_LICENSE_ID}"
requested_license_expression)
_qt_internal_sbom_join_two_license_ids_with_op(
"${license_expression}" "AND" "${requested_license_expression}"
license_expression)
endif()
# Allow setting a license expression string per directory scope via a variable.
if(is_qt_entity_type AND QT_SBOM_LICENSE_EXPRESSION AND NOT arg_NO_DEFAULT_DIRECTORY_QT_LICENSE)
set(qt_license_expression "${QT_SBOM_LICENSE_EXPRESSION}")
_qt_internal_sbom_join_two_license_ids_with_op(
@ -414,7 +455,8 @@ function(_qt_internal_sbom_add_target target)
license_expression)
endif()
if(qa_license_id)
# Read a license expression from the attribution json file.
if(qa_license_id AND NOT arg_NO_ATTRIBUTION_LICENSE_ID)
if(NOT qa_license_id MATCHES "urn:dje:license")
_qt_internal_sbom_join_two_license_ids_with_op(
"${license_expression}" "AND" "${qa_license_id}"
@ -431,6 +473,8 @@ function(_qt_internal_sbom_add_target target)
if(license_expression)
list(APPEND project_package_options LICENSE_CONCLUDED "${license_expression}")
# For qt entities we know the license we provide, so we mark it as declared as well.
if(is_qt_entity_type)
list(APPEND project_package_options LICENSE_DECLARED "${license_expression}")
endif()
@ -2332,11 +2376,45 @@ function(_qt_internal_sbom_get_package_purpose type out_purpose)
set(${out_purpose} "${package_purpose}" PARENT_SCOPE)
endfunction()
# Get the default qt spdx license expression.
function(_qt_internal_sbom_get_default_qt_license_id out_var)
set(${out_var}
"LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only"
PARENT_SCOPE)
# Get a qt spdx license expression given the id.
function(_qt_internal_sbom_get_spdx_license_expression id out_var)
set(license "")
# The default for modules / plugins
if(id STREQUAL "QT_DEFAULT" OR id STREQUAL "QT_COMMERCIAL_OR_LGPL3")
set(license "LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only")
# For commercial only entities
elseif(id STREQUAL "QT_COMMERCIAL")
set(license "LicenseRef-Qt-Commercial")
# For GPL3 only modules
elseif(id STREQUAL "QT_COMMERCIAL_OR_GPL3")
set(license "LicenseRef-Qt-Commercial OR GPL-3.0-only")
# For tools and apps
elseif(id STREQUAL "QT_COMMERCIAL_OR_GPL3_WITH_EXCEPTION")
set(license "LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0")
# For things like the qtmain library
elseif(id STREQUAL "QT_COMMERCIAL_OR_BSD3")
set(license "LicenseRef-Qt-Commercial OR BSD-3-Clause")
# For documentation
elseif(id STREQUAL "QT_COMMERCIAL_OR_GFDL1_3")
set(license "LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only")
# For examples and the like
elseif(id STREQUAL "BSD3")
set(license "BSD-3-Clause")
endif()
if(NOT license)
message(FATAL_ERROR "No SPDX license expression found for id: ${id}")
endif()
set(${out_var} "${license}" PARENT_SCOPE)
endfunction()
# Get the default qt copyright.