Files
RedBear-OS/local/recipes/qt/qtbase/source/cmake/QtPublicSbomCycloneDXHelpers.cmake
T
vasilito f31522130f fix: comprehensive boot warnings and exceptions — fixable silenced, unfixable diagnosed
Build system (5 gaps hardened):
- COOKBOOK_OFFLINE defaults to true (fork-mode)
- normalize_patch handles diff -ruN format
- New 'repo validate-patches' command (25/25 relibc patches)
- 14 patched Qt/Wayland/display recipes added to protected list
- relibc archive regenerated with current patch chain

Boot fixes (fixable):
- Full ISO EFI partition: 16 MiB → 1 MiB (matches mini, BIOS hardcoded 2 MiB offset)
- D-Bus system bus: absolute /usr/bin/dbus-daemon path (was skipped)
- redbear-sessiond: absolute /usr/bin/redbear-sessiond path (was skipped)
- daemon framework: silenced spurious INIT_NOTIFY warnings for oneshot_async services (P0-daemon-silence-init-notify.patch)
- udev-shim: demoted INIT_NOTIFY warning to INFO (expected for oneshot_async)
- relibc: comprehensive named semaphores (sem_open/close/unlink) replacing upstream todo!() stubs
- greeterd: Wayland socket timeout 15s → 30s (compositor DRM wait)
- greeter-ui: built and linked (header guard unification, sem_compat stubs removed)
- mc: un-ignored in both configs, fixed glib/libiconv/pcre2 transitive deps
- greeter config: removed stale keymapd dependency from display/greeter services
- prefix toolchain: relibc headers synced, _RELIBC_STDLIB_H guard unified

Unfixable (diagnosed, upstream):
- i2c-hidd: abort on no-I2C-hardware (QEMU) — process::exit → relibc abort
- kded6/greeter-ui: page fault 0x8 — Qt library null deref
- Thread panics fd != -1 — Rust std library on Redox
- DHCP timeout / eth0 MAC — QEMU user-mode networking
- hwrngd/thermald — no hardware RNG/thermal in VM
- live preload allocation — BIOS memory fragmentation, continues on demand
2026-05-05 20:20:37 +01:00

385 lines
14 KiB
CMake

# Copyright (C) 2025 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
# Gets the helper python script name and relative dir in the source dir.
function(_qt_internal_sbom_get_cyclone_dx_generator_script_name
out_var_generator_name
out_var_generator_relative_dir)
set(generator_name "qt_cyclonedx_generator.py")
_qt_internal_path_join(generator_relative_dir
"util" "sbom" "cyclonedx" "qt_cyclonedx_generator")
set(${out_var_generator_name} "${generator_name}" PARENT_SCOPE)
set(${out_var_generator_relative_dir} "${generator_relative_dir}" PARENT_SCOPE)
endfunction()
# Ges the path to the helper python script, which should be used to generate CycloneDX document.
# Prefers the source path over the installed path, for easier development of the script.
function(_qt_internal_sbom_get_cyclone_dx_generator_path out_var)
_qt_internal_sbom_get_cyclone_dx_generator_script_name(generator_name generator_relative_dir)
_qt_internal_path_join(qtbase_script_path
"${QT_SOURCE_TREE}" "${generator_relative_dir}" "${generator_name}")
_qt_internal_path_join(installed_script_path
"${QT6_INSTALL_PREFIX}" "${QT6_INSTALL_LIBEXECS}" "${generator_name}")
# qtbase sources available, always use them, regardless if it's a prefix or non-prefix build.
# Makes development easier.
if(EXISTS "${qtbase_script_path}")
set(script_path "${qtbase_script_path}")
# qtbase sources unavailable, use installed files.
elseif(EXISTS "${installed_script_path}")
set(script_path "${installed_script_path}")
else()
message(FATAL_ERROR "Can't find ${generator_name} file.")
endif()
set(${out_var} "${script_path}" PARENT_SCOPE)
endfunction()
# Parses the options for a single CYDX_PROPERTY_ENTRY, and creates a toml snippet to add a
# CycloneDX property to the final toml document.
function(_qt_internal_sbom_parse_cydx_property_entry_options)
set(opt_args "")
set(single_args
CYDX_PROPERTY_NAME
CYDX_PROPERTY_VALUE
OUT_VAR
)
set(multi_args "")
cmake_parse_arguments(PARSE_ARGV 0 arg "${opt_args}" "${single_args}" "${multi_args}")
_qt_internal_validate_all_args_are_parsed(arg)
if(NOT arg_CYDX_PROPERTY_NAME)
message(FATAL_ERROR "CYDX_PROPERTY_NAME is required.")
endif()
if(NOT arg_CYDX_PROPERTY_VALUE)
message(FATAL_ERROR "CYDX_PROPERTY_VALUE is required.")
endif()
if(NOT arg_OUT_VAR)
message(FATAL_ERROR "OUT_VAR is required.")
endif()
set(${arg_OUT_VAR} "
[[components.properties]]
name = \\\"${arg_CYDX_PROPERTY_NAME}\\\"
value = \\\"${arg_CYDX_PROPERTY_VALUE}\\\"
" PARENT_SCOPE)
endfunction()
# Processes a list of CycloneDX property entries, and creates their toml representation as output.
function(_qt_internal_sbom_handle_cydx_properties)
set(opt_args "")
set(single_args
OUT_VAR_CYDX_PROPERTIES_STRING
)
set(multi_args
CYDX_PROPERTIES
)
cmake_parse_arguments(PARSE_ARGV 0 arg "${opt_args}" "${single_args}" "${multi_args}")
_qt_internal_validate_all_args_are_parsed(arg)
if(NOT arg_OUT_VAR_CYDX_PROPERTIES_STRING)
message(FATAL_ERROR "OUT_VAR_CYDX_PROPERTIES_STRING is required.")
endif()
# Collect each CYDX_PROPERTY_ENTRY args into a separate variable.
set(prop_idx -1)
set(prop_entry_indices "")
foreach(prop_arg IN LISTS arg_CYDX_PROPERTIES)
if(prop_arg STREQUAL "CYDX_PROPERTY_ENTRY")
math(EXPR prop_idx "${prop_idx}+1")
list(APPEND prop_entry_indices "${prop_idx}")
elseif(prop_idx GREATER_EQUAL 0)
list(APPEND prop_${prop_idx}_args "${prop_arg}")
else()
message(FATAL_ERROR "Missing CYDX_PROPERTY_ENTRY keyword.")
endif()
endforeach()
set(properties_string "")
foreach(prop_idx IN LISTS prop_entry_indices)
_qt_internal_sbom_parse_cydx_property_entry_options(
${prop_${prop_idx}_args}
OUT_VAR property_tuple
)
string(APPEND properties_string "${property_tuple}")
endforeach()
set(${arg_OUT_VAR_CYDX_PROPERTIES_STRING} "${properties_string}" PARENT_SCOPE)
endfunction()
# Outputs extra Cyclone DX properties based on the sbom entity type.
function(_qt_internal_sbom_handle_qt_entity_cydx_properties)
set(opt_args "")
set(single_args
SBOM_ENTITY_TYPE
OUT_CYDX_PROPERTIES
)
set(multi_args "")
cmake_parse_arguments(PARSE_ARGV 0 arg "${opt_args}" "${single_args}" "${multi_args}")
_qt_internal_validate_all_args_are_parsed(arg)
if(NOT arg_SBOM_ENTITY_TYPE)
message(FATAL_ERROR "SBOM_ENTITY_TYPE is required.")
endif()
if(NOT arg_OUT_CYDX_PROPERTIES)
message(FATAL_ERROR "OUT_CYDX_PROPERTIES is required.")
endif()
set(cydx_properties "")
list(APPEND cydx_properties
CYDX_PROPERTY_ENTRY
CYDX_PROPERTY_NAME "qt:sbom:entity_type"
CYDX_PROPERTY_VALUE "${arg_SBOM_ENTITY_TYPE}"
)
_qt_internal_sbom_is_qt_entity_type("${arg_SBOM_ENTITY_TYPE}" is_qt_entity_type)
if(is_qt_entity_type)
list(APPEND cydx_properties
CYDX_PROPERTY_ENTRY
CYDX_PROPERTY_NAME "qt:sbom:is_qt_entity_type"
CYDX_PROPERTY_VALUE "true"
)
endif()
_qt_internal_sbom_is_qt_3rd_party_entity_type("${arg_SBOM_ENTITY_TYPE}"
is_qt_3rd_party_entity_type)
if(is_qt_3rd_party_entity_type)
list(APPEND cydx_properties
CYDX_PROPERTY_ENTRY
CYDX_PROPERTY_NAME "qt:sbom:is_qt_3rd_party_entity_type"
CYDX_PROPERTY_VALUE "true"
)
endif()
set(${arg_OUT_CYDX_PROPERTIES} "${cydx_properties}" PARENT_SCOPE)
endfunction()
# Maps an sbom entity type to a cyclone dx component type.
function(_qt_internal_sbom_get_cyclone_component_type out_var sbom_entity_type)
set(library_types
"QT_MODULE"
"QT_PLUGIN"
"QML_PLUGIN"
"QT_THIRD_PARTY_MODULE"
"QT_THIRD_PARTY_SOURCES"
"SYSTEM_LIBRARY"
"LIBRARY"
"THIRD_PARTY_LIBRARY"
"THIRD_PARTY_LIBRARY_WITH_FILES"
"THIRD_PARTY_SOURCES"
)
set(application_types
"QT_TOOL"
"QT_APP"
"EXECUTABLE"
)
if(sbom_entity_type IN_LIST library_types)
set(component_type "library")
elseif(sbom_entity_type IN_LIST application_types)
set(component_type "application")
else()
# Default to library for now, because it's unclear what would be a better default.
set(component_type "library")
endif()
set(${out_var} "${component_type}" PARENT_SCOPE)
endfunction()
# Generates a pseudo-unique serial number for a CycloneDX sbom document.
#
# The spec says that a BOM serial number must conform to RFC 4122, but doesn't specify which
# kind of uuid version should be generated.
# The upstream python library generates a version 4 uuid, which is fully random.
# CMake can only generate version 3 and 5 uuids, which are fully deterministic based on the given
# NAMESPACE and NAME values.
# Generating a fully random uuid prevents build reproducibility. The maintainer of the Cyclone DX
# spec even mentions that here:
# https://github.com/CycloneDX/specification/issues/97#issuecomment-955904904
# And yet to to do component-wise inter-document linking using the BOM-Link mechanism, you have to
# use serial numbers.
#
# Because the spec doesn't explicitly prohibit it, we will generate a version 5 uuid based on the
# SPDX_NAMESPACE passed to the function, which is supposed to be unique enough, because it contains
# the project / document name (e.g. qtbase) and its version or git version.
# This should alleviate the reproducibility problem as well.
function(_qt_internal_sbom_get_cyclone_bom_serial_number)
set(opt_args "")
set(single_args
SPDX_NAMESPACE
OUT_VAR_UUID
OUT_VAR_SERIAL_NUMBER
)
set(multi_args "")
cmake_parse_arguments(PARSE_ARGV 0 arg "${opt_args}" "${single_args}" "${multi_args}")
_qt_internal_validate_all_args_are_parsed(arg)
_qt_internal_sbom_set_default_option_value_and_error_if_empty(SPDX_NAMESPACE "")
_qt_internal_sbom_get_document_namespace_uuid_namespace(uuid_namespace)
string(UUID uuid NAMESPACE "${uuid_namespace}" NAME "${arg_SPDX_NAMESPACE}" TYPE SHA1)
set(cyclone_dx_serial_number "urn:cdx:${uuid}")
if(arg_OUT_VAR_UUID)
set("${arg_OUT_VAR_UUID}" "${uuid}" PARENT_SCOPE)
endif()
if(arg_OUT_VAR_SERIAL_NUMBER)
set("${arg_OUT_VAR_SERIAL_NUMBER}" "${cyclone_dx_serial_number}" PARENT_SCOPE)
endif()
endfunction()
# See https://github.com/CycloneDX/guides/blob/main/SBOM/en/0x52-Linking.md
function(_qt_internal_sbom_get_cydx_external_bom_link target out_var)
get_target_property(spdx_id "${target}" _qt_sbom_spdx_id)
get_target_property(bom_serial_number "${target}" _qt_sbom_cydx_bom_serial_number_uuid)
set(bom_version "1")
set(bom_link "urn:cdx:${bom_serial_number}/${bom_version}#${spdx_id}")
set(${out_var} "${bom_link}" PARENT_SCOPE)
endfunction()
# Records necessary details of external target dependencies in global properties, to later create
# the CycloneDX packages for them. The info collection needs to be done immediately in the directory
# scope where the targets were found, because they might not be global, and thus can't be accessed
# later.
function(_qt_internal_sbom_record_external_target_dependecies)
set(opt_args "")
set(single_args "")
set(multi_args
TARGETS
)
cmake_parse_arguments(PARSE_ARGV 0 arg "${opt_args}" "${single_args}" "${multi_args}")
_qt_internal_validate_all_args_are_parsed(arg)
if(NOT arg_TARGETS)
return()
endif()
get_property(existing_ids GLOBAL PROPERTY _qt_internal_sbom_external_target_dep_ids)
if(NOT existing_ids)
set(existing_ids "")
endif()
foreach(target IN LISTS arg_TARGETS)
# Use the full spdx id (one prefixed with the containing DocumentRef-) because that's what
# our spdx dependency relationships use at the moment.
# Both Foo and FooPrivate map to the same spdx_id, so we need to avoid duplicates on spdx id
# level.
get_target_property(spdx_id "${target}" _qt_sbom_spdx_id)
if(spdx_id IN_LIST existing_ids)
continue()
endif()
list(APPEND existing_ids "${spdx_id}")
set_property(GLOBAL APPEND PROPERTY _qt_internal_sbom_external_target_dep_ids "${spdx_id}")
# This is checked in _qt_internal_sbom_add_target, to prevent duplicate creation of
# system library targets.
set_property(GLOBAL APPEND PROPERTY _qt_internal_sbom_external_target_dependencies
"${target}")
get_target_property(package_name "${target}" _qt_sbom_package_name)
get_target_property(sbom_entity_type "${target}" _qt_sbom_entity_type)
get_target_property(package_version "${target}" _qt_sbom_package_version)
_qt_internal_sbom_get_cydx_external_bom_link("${target}" external_bom_link)
if(NOT package_name)
message(FATAL_ERROR "Target '${target}' does not provide a SBOM package name")
endif()
set_property(GLOBAL
PROPERTY "_qt_internal_sbom_external_target_dep_${spdx_id}_target"
"${target}")
set_property(GLOBAL
PROPERTY "_qt_internal_sbom_external_target_dep_${spdx_id}_package_name"
"${package_name}")
set_property(GLOBAL
PROPERTY "_qt_internal_sbom_external_target_dep_${spdx_id}_sbom_entity_type"
"${sbom_entity_type}")
set_property(GLOBAL
PROPERTY "_qt_internal_sbom_external_target_dep_${spdx_id}_package_version"
"${package_version}")
set_property(GLOBAL
PROPERTY "_qt_internal_sbom_external_target_dep_${spdx_id}_external_bom_link"
"${external_bom_link}")
endforeach()
endfunction()
# Goes through the list of recorded external target dependencies collected during target
# dependency analysis, and adds them as CycloneDX packages to the CycloneDX document.
# This is different from SPDX v2.3, which doesn't require creating a package for dependencies that
# are defined in a different document.
function(_qt_internal_sbom_add_cydx_external_target_dependencies)
get_property(spdx_ids GLOBAL PROPERTY _qt_internal_sbom_external_target_dep_ids)
if(NOT spdx_ids)
# Clean up external target dependencies, before configuring next repo project.
set_property(GLOBAL PROPERTY _qt_internal_sbom_external_target_dep_ids "")
set_property(GLOBAL PROPERTY _qt_internal_sbom_external_target_dependencies "")
return()
endif()
# Just in case, don't add duplicates.
set(visited_spdx_ids "")
foreach(spdx_id IN LISTS spdx_ids)
if(spdx_id IN_LIST visited_spdx_ids)
continue()
endif()
get_cmake_property(package_name
"_qt_internal_sbom_external_target_dep_${spdx_id}_package_name")
get_cmake_property(sbom_entity_type
"_qt_internal_sbom_external_target_dep_${spdx_id}_sbom_entity_type")
get_cmake_property(package_version
"_qt_internal_sbom_external_target_dep_${spdx_id}_package_version")
get_cmake_property(external_bom_link
"_qt_internal_sbom_external_target_dep_${spdx_id}_external_bom_link")
_qt_internal_sbom_generate_cyclone_add_package(
PACKAGE "${package_name}"
SPDXID "${spdx_id}"
SBOM_ENTITY_TYPE "${sbom_entity_type}"
VERSION "${package_version}"
EXTERNAL_BOM_LINK "${external_bom_link}"
)
list(APPEND visited_spdx_ids "${spdx_id}")
endforeach()
# Clean up external target dependencies, before configuring next repo project.
set_property(GLOBAL PROPERTY _qt_internal_sbom_external_target_dep_ids "")
set_property(GLOBAL PROPERTY _qt_internal_sbom_external_target_dependencies "")
endfunction()
# Records a license id and its text in global properties, to be added to the CycloneDX document
# later.
function(_qt_internal_sbom_record_license_cydx)
set(opt_args "")
set(single_args
LICENSE_ID
EXTRACTED_TEXT
)
set(multi_args "")
cmake_parse_arguments(PARSE_ARGV 0 arg "${opt_args}" "${single_args}" "${multi_args}")
_qt_internal_validate_all_args_are_parsed(arg)
set_property(GLOBAL APPEND PROPERTY
_qt_internal_sbom_cydx_licenses "${arg_LICENSE_ID}")
set_property(GLOBAL PROPERTY
_qt_internal_sbom_cydx_licenses_${arg_LICENSE_ID}_text "${arg_EXTRACTED_TEXT}"
)
endfunction()