qtbase/cmake/QtPublicSbomSystemDepHelpers.cmake
Cristian Le d7e2d6b22c Use _qt_internal_dealias_target
Pick-to: 6.8
Change-Id: Iffc1148ed7655c724ea0609be01978ab7d5e7f8f
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
(cherry picked from commit 10affadd125b615b47979c4469be55bdbe5a189d)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
2025-03-06 21:09:24 +00:00

166 lines
7.1 KiB
CMake

# Copyright (C) 2024 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
# Records information about a system library target, usually due to a qt_find_package call.
# This information is later used to generate packages for the system libraries, but only after
# confirming that the library was used (linked) into any of the Qt targets.
function(_qt_internal_sbom_record_system_library_usage target)
if(NOT QT_GENERATE_SBOM)
return()
endif()
set(opt_args "")
set(single_args
TYPE
PACKAGE_VERSION
FRIENDLY_PACKAGE_NAME
)
set(multi_args "")
cmake_parse_arguments(PARSE_ARGV 1 arg "${opt_args}" "${single_args}" "${multi_args}")
_qt_internal_validate_all_args_are_parsed(arg)
if(NOT arg_TYPE)
message(FATAL_ERROR "TYPE must be set")
endif()
# A package might be looked up more than once, make sure to record it once.
get_property(already_recorded GLOBAL PROPERTY
_qt_internal_sbom_recorded_system_library_target_${target})
if(already_recorded)
return()
endif()
set_property(GLOBAL PROPERTY
_qt_internal_sbom_recorded_system_library_target_${target} TRUE)
# Defer spdx id creation until _qt_internal_sbom_begin_project is called, so we know the
# project name. The project name is used in the package infix generation of the system library,
# but _qt_internal_sbom_record_system_library_usage might be called before sbom generation
# has started, e.g. during _qt_internal_find_third_party_dependencies.
set(spdx_options
${target}
TYPE "${arg_TYPE}"
PACKAGE_NAME "${arg_FRIENDLY_PACKAGE_NAME}"
)
get_cmake_property(sbom_repo_begin_called _qt_internal_sbom_repo_begin_called)
if(sbom_repo_begin_called AND TARGET "${target}")
_qt_internal_sbom_record_system_library_spdx_id(${target} ${spdx_options})
else()
set_property(GLOBAL PROPERTY
_qt_internal_sbom_recorded_system_library_spdx_options_${target} "${spdx_options}")
endif()
# Defer sbom info creation until we detect usage of the system library (whether the library is
# linked into any other target).
set_property(GLOBAL APPEND PROPERTY
_qt_internal_sbom_recorded_system_library_targets "${target}")
set_property(GLOBAL PROPERTY
_qt_internal_sbom_recorded_system_library_options_${target} "${ARGN}")
endfunction()
# Helper to record spdx ids of all system library targets that were found so far.
function(_qt_internal_sbom_record_system_library_spdx_ids)
get_property(recorded_targets GLOBAL PROPERTY _qt_internal_sbom_recorded_system_library_targets)
if(NOT recorded_targets)
return()
endif()
foreach(target IN LISTS recorded_targets)
get_property(args GLOBAL PROPERTY
_qt_internal_sbom_recorded_system_library_spdx_options_${target})
# qt_find_package PROVIDED_TARGETS might refer to non-existent targets in certain cases,
# like zstd::libzstd_shared for qt_find_package(WrapZSTD), because we are not sure what
# kind of zstd build was done. Make sure to check if the target exists before recording it.
if(TARGET "${target}")
set(target_unaliased "${target}")
_qt_internal_dealias_target(target_unaliased)
_qt_internal_sbom_record_system_library_spdx_id(${target_unaliased} ${args})
else()
message(DEBUG
"Skipping recording system library for SBOM because target does not exist: "
" ${target}")
endif()
endforeach()
endfunction()
# Helper to record the spdx id of a system library target.
function(_qt_internal_sbom_record_system_library_spdx_id target)
# Save the spdx id before the sbom info is added, so we can refer to it in relationships.
_qt_internal_sbom_record_target_spdx_id(${ARGN} OUT_VAR package_spdx_id)
if(NOT package_spdx_id)
message(FATAL_ERROR "Could not generate spdx id for system library target: ${target}")
endif()
set_target_properties("${target}" PROPERTIES _qt_internal_sbom_is_system_library TRUE)
set_property(GLOBAL PROPERTY
_qt_internal_sbom_recorded_system_library_package_${target} "${package_spdx_id}")
endfunction()
# Goes through the list of consumed system libraries (those that were linked in) and creates
# sbom packages for them.
# Uses information from recorded system libraries (calls to qt_find_package).
function(_qt_internal_sbom_add_recorded_system_libraries)
get_property(recorded_targets GLOBAL PROPERTY _qt_internal_sbom_recorded_system_library_targets)
get_property(consumed_targets GLOBAL PROPERTY _qt_internal_sbom_consumed_system_library_targets)
set(unconsumed_targets "${recorded_targets}")
set(generated_package_names "")
message(DEBUG
"System libraries that were marked consumed "
"(some target linked to them): ${consumed_targets}")
message(DEBUG
"System libraries that were recorded "
"(they were marked with qt_find_package()): ${recorded_targets}")
foreach(target IN LISTS consumed_targets)
# Some system targets like qtspeech SpeechDispatcher::SpeechDispatcher might be aliased,
# and we can't set properties on them, so unalias the target name.
set(target_original "${target}")
_qt_internal_dealias_target(target)
get_property(args GLOBAL PROPERTY
_qt_internal_sbom_recorded_system_library_options_${target})
get_property(package_name GLOBAL PROPERTY
_qt_internal_sbom_recorded_system_library_package_${target})
set_property(GLOBAL PROPERTY _qt_internal_sbom_recorded_system_library_target_${target} "")
set_property(GLOBAL PROPERTY _qt_internal_sbom_recorded_system_library_options_${target} "")
set_property(GLOBAL PROPERTY _qt_internal_sbom_recorded_system_library_package_${target} "")
# Guard against generating a package multiple times. Can happen when multiple targets belong
# to the same package.
if(sbom_generated_${package_name})
continue()
endif()
# Automatic system library sbom recording happens at project root source dir scope, which
# means it might accidentally pick up a qt_attribution.json file from the project root,
# that is not intended to be use for system libraries.
# For now, explicitly disable using the root attribution file.
list(APPEND args NO_CURRENT_DIR_ATTRIBUTION)
list(APPEND generated_package_names "${package_name}")
set(sbom_generated_${package_name} TRUE)
_qt_internal_extend_sbom(${target} ${args})
_qt_internal_finalize_sbom(${target})
list(REMOVE_ITEM unconsumed_targets "${target_original}")
endforeach()
message(DEBUG "System libraries that were recorded, but not consumed: ${unconsumed_targets}")
message(DEBUG "Generated SBOMs for the following system packages: ${generated_package_names}")
# Clean up, before configuring next repo project.
set_property(GLOBAL PROPERTY _qt_internal_sbom_consumed_system_library_targets "")
set_property(GLOBAL PROPERTY _qt_internal_sbom_recorded_system_library_targets "")
endfunction()