CMake: Move SBOM project ops setup to run at project begin time

Previously Python and other sbom tooling was looked up at SBOM
project end time.
This was fine for the use cases we had so far, but it prevents
introducing new API that wants call the spdx tools before the end of
the project. Such API will be introduced in a follow up change.

Move the python interpreter, python dependency lookup and other sbom
tooling setup to happen at project begin time.

Task-number: QTBUG-122899
Task-number: QTBUG-129901
Task-number: QTBUG-131377
Change-Id: Ic8884e378c0ffd9720ede26b0c61f4122f3bb9d9
Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
Reviewed-by: Alexey Edelev <alexey.edelev@qt.io>
(cherry picked from commit 2fa815341c68148ff00c6d16be017f80e4032ef1)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
(cherry picked from commit 6e74281ba3a8c7535a5a0902ef619872712e1a37)
This commit is contained in:
Alexandru Croitor 2024-12-09 16:36:58 +01:00 committed by Qt Cherry-pick Bot
parent fb3e74615d
commit 30bfeab29b
2 changed files with 83 additions and 75 deletions

View File

@ -251,12 +251,9 @@ Relationship: SPDXRef-DOCUMENT DESCRIBES ${project_spdx_id}
set_property(GLOBAL PROPERTY _qt_sbom_spdx_id_count 0)
endfunction()
# Signals the end of recording sbom information for a project.
# Creates an 'sbom' custom target to generate an incomplete sbom at build time (no checksums).
# Creates install rules to install a complete (with checksums) sbom.
# Also allows running various post-installation steps like NTIA validation, auditing, json
# generation, etc
function(_qt_internal_sbom_end_project_generate)
# Handles the look up of Python, Python spdx dependencies and other various post-installation steps
# like NTIA validation, auditing, json generation, etc.
function(_qt_internal_sbom_setup_project_ops_generation)
set(opt_args
GENERATE_JSON
GENERATE_JSON_REQUIRED
@ -275,20 +272,6 @@ function(_qt_internal_sbom_end_project_generate)
cmake_parse_arguments(PARSE_ARGV 0 arg "${opt_args}" "${single_args}" "${multi_args}")
_qt_internal_validate_all_args_are_parsed(arg)
get_property(sbom_build_output_path GLOBAL PROPERTY _qt_sbom_build_output_path)
get_property(sbom_build_output_path_without_ext GLOBAL PROPERTY
_qt_sbom_build_output_path_without_ext)
get_property(sbom_install_output_path GLOBAL PROPERTY _qt_sbom_install_output_path)
get_property(sbom_install_output_path_without_ext GLOBAL PROPERTY
_qt_sbom_install_output_path_without_ext)
if(NOT sbom_build_output_path)
message(FATAL_ERROR "Call _qt_internal_sbom_begin_project() first")
endif()
_qt_internal_get_staging_area_spdx_file_path(staging_area_spdx_file)
if(arg_GENERATE_JSON AND NOT QT_INTERNAL_NO_SBOM_PYTHON_OPS)
set(op_args
OP_KEY "GENERATE_JSON"
@ -354,6 +337,25 @@ function(_qt_internal_sbom_end_project_generate)
BUILD_TIME_SCRIPT_PATH_OUT_VAR reuse_lint_script
)
endif()
endfunction()
# Signals the end of recording sbom information for a project.
# Creates an 'sbom' custom target to generate an incomplete sbom at build time (no checksums).
# Creates install rules to install a complete (with checksums) sbom.
function(_qt_internal_sbom_end_project_generate)
get_property(sbom_build_output_path GLOBAL PROPERTY _qt_sbom_build_output_path)
get_property(sbom_build_output_path_without_ext GLOBAL PROPERTY
_qt_sbom_build_output_path_without_ext)
get_property(sbom_install_output_path GLOBAL PROPERTY _qt_sbom_install_output_path)
get_property(sbom_install_output_path_without_ext GLOBAL PROPERTY
_qt_sbom_install_output_path_without_ext)
if(NOT sbom_build_output_path)
message(FATAL_ERROR "Call _qt_internal_sbom_begin_project() first")
endif()
_qt_internal_get_staging_area_spdx_file_path(staging_area_spdx_file)
get_cmake_property(cmake_include_files _qt_sbom_cmake_include_files)
get_cmake_property(cmake_end_include_files _qt_sbom_cmake_end_include_files)

View File

@ -284,6 +284,66 @@ function(_qt_internal_sbom_begin_project)
_qt_internal_sbom_record_system_library_spdx_ids()
set_property(GLOBAL PROPERTY _qt_internal_sbom_repo_begin_called TRUE)
_qt_internal_sbom_setup_project_ops()
endfunction()
# Check various internal options to decide which sbom generation operations should be setup.
# Considered operations are generation of a JSON sbom, validation of the SBOM, NTIA checker, etc.
function(_qt_internal_sbom_setup_project_ops)
set(options "")
if(QT_SBOM_GENERATE_JSON OR QT_INTERNAL_SBOM_GENERATE_JSON OR QT_INTERNAL_SBOM_DEFAULT_CHECKS)
list(APPEND options GENERATE_JSON)
endif()
# Tring to generate the JSON might fail if the python dependencies are not available.
# The user can explicitly request to fail the build if dependencies are not found.
# error out. For internal options that the CI uses, we always want to fail the build if the
# deps are not found.
if(QT_SBOM_REQUIRE_GENERATE_JSON OR QT_INTERNAL_SBOM_GENERATE_JSON
OR QT_INTERNAL_SBOM_DEFAULT_CHECKS)
list(APPEND options GENERATE_JSON_REQUIRED)
endif()
if(QT_SBOM_VERIFY OR QT_INTERNAL_SBOM_VERIFY OR QT_INTERNAL_SBOM_DEFAULT_CHECKS)
list(APPEND options VERIFY_SBOM)
endif()
# Do the same requirement check for SBOM verification.
if(QT_SBOM_REQUIRE_VERIFY OR QT_INTERNAL_SBOM_VERIFY OR QT_INTERNAL_SBOM_DEFAULT_CHECKS)
list(APPEND options VERIFY_SBOM_REQUIRED)
endif()
if(QT_INTERNAL_SBOM_VERIFY_NTIA_COMPLIANT OR QT_INTERNAL_SBOM_DEFAULT_CHECKS)
list(APPEND options VERIFY_NTIA_COMPLIANT)
endif()
if(QT_INTERNAL_SBOM_SHOW_TABLE OR QT_INTERNAL_SBOM_DEFAULT_CHECKS)
list(APPEND options SHOW_TABLE)
endif()
if(QT_INTERNAL_SBOM_AUDIT OR QT_INTERNAL_SBOM_AUDIT_NO_ERROR)
list(APPEND options AUDIT)
endif()
if(QT_INTERNAL_SBOM_AUDIT_NO_ERROR)
list(APPEND options AUDIT_NO_ERROR)
endif()
if(QT_GENERATE_SOURCE_SBOM)
list(APPEND options GENERATE_SOURCE_SBOM)
endif()
if(QT_LINT_SOURCE_SBOM)
list(APPEND options LINT_SOURCE_SBOM)
endif()
if(QT_INTERNAL_LINT_SOURCE_SBOM_NO_ERROR)
list(APPEND options LINT_SOURCE_SBOM_NO_ERROR)
endif()
_qt_internal_sbom_setup_project_ops_generation(${options})
endfunction()
# Ends repo sbom project generation.
@ -312,61 +372,7 @@ function(_qt_internal_sbom_end_project)
endforeach()
endif()
set(end_project_options "")
if(QT_SBOM_GENERATE_JSON OR QT_INTERNAL_SBOM_GENERATE_JSON OR QT_INTERNAL_SBOM_DEFAULT_CHECKS)
list(APPEND end_project_options GENERATE_JSON)
endif()
# Tring to generate the JSON might fail if the python dependencies are not available.
# The user can explicitly request to fail the build if dependencies are not found.
# error out. For internal options that the CI uses, we always want to fail the build if the
# deps are not found.
if(QT_SBOM_REQUIRE_GENERATE_JSON OR QT_INTERNAL_SBOM_GENERATE_JSON
OR QT_INTERNAL_SBOM_DEFAULT_CHECKS)
list(APPEND end_project_options GENERATE_JSON_REQUIRED)
endif()
if(QT_SBOM_VERIFY OR QT_INTERNAL_SBOM_VERIFY OR QT_INTERNAL_SBOM_DEFAULT_CHECKS)
list(APPEND end_project_options VERIFY_SBOM)
endif()
# Do the same requirement check for SBOM verification.
if(QT_SBOM_REQUIRE_VERIFY OR QT_INTERNAL_SBOM_VERIFY OR QT_INTERNAL_SBOM_DEFAULT_CHECKS)
list(APPEND end_project_options VERIFY_SBOM_REQUIRED)
endif()
if(QT_INTERNAL_SBOM_VERIFY_NTIA_COMPLIANT OR QT_INTERNAL_SBOM_DEFAULT_CHECKS)
list(APPEND end_project_options VERIFY_NTIA_COMPLIANT)
endif()
if(QT_INTERNAL_SBOM_SHOW_TABLE OR QT_INTERNAL_SBOM_DEFAULT_CHECKS)
list(APPEND end_project_options SHOW_TABLE)
endif()
if(QT_INTERNAL_SBOM_AUDIT OR QT_INTERNAL_SBOM_AUDIT_NO_ERROR)
list(APPEND end_project_options AUDIT)
endif()
if(QT_INTERNAL_SBOM_AUDIT_NO_ERROR)
list(APPEND end_project_options AUDIT_NO_ERROR)
endif()
if(QT_GENERATE_SOURCE_SBOM)
list(APPEND end_project_options GENERATE_SOURCE_SBOM)
endif()
if(QT_LINT_SOURCE_SBOM)
list(APPEND end_project_options LINT_SOURCE_SBOM)
endif()
if(QT_INTERNAL_LINT_SOURCE_SBOM_NO_ERROR)
list(APPEND end_project_options LINT_SOURCE_SBOM_NO_ERROR)
endif()
_qt_internal_sbom_end_project_generate(
${end_project_options}
)
_qt_internal_sbom_end_project_generate()
# Clean up external document ref properties, because each repo needs to start from scratch
# in a top-level build.