mirror of
https://github.com/Kitware/CMake.git
synced 2026-07-01 20:27:24 +00:00
cmSbom: Add export(SBOM) build generators and unit tests
This commit is contained in:
@@ -203,6 +203,8 @@ add_library(
|
||||
cmExportBuildFileGenerator.cxx
|
||||
cmExportBuildPackageInfoGenerator.h
|
||||
cmExportBuildPackageInfoGenerator.cxx
|
||||
cmExportBuildSbomGenerator.h
|
||||
cmExportBuildSbomGenerator.cxx
|
||||
cmExportCMakeConfigGenerator.h
|
||||
cmExportCMakeConfigGenerator.cxx
|
||||
cmExportFileGenerator.h
|
||||
|
||||
86
Source/cmExportBuildSbomGenerator.cxx
Normal file
86
Source/cmExportBuildSbomGenerator.cxx
Normal file
@@ -0,0 +1,86 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file LICENSE.rst or https://cmake.org/licensing for details. */
|
||||
#include "cmExportBuildSbomGenerator.h"
|
||||
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <cmext/string_view>
|
||||
|
||||
#include "cmGeneratorExpression.h"
|
||||
#include "cmSbomArguments.h"
|
||||
#include "cmSbomObject.h"
|
||||
#include "cmSpdx.h"
|
||||
#include "cmStringAlgorithms.h"
|
||||
|
||||
class cmGeneratorTarget;
|
||||
|
||||
cmExportBuildSbomGenerator::cmExportBuildSbomGenerator(cmSbomArguments args)
|
||||
: cmExportSbomGenerator(args)
|
||||
{
|
||||
this->SetNamespace(cmStrCat(this->GetPackageName(), "::"_s));
|
||||
}
|
||||
|
||||
bool cmExportBuildSbomGenerator::GenerateMainFile(std::ostream& os)
|
||||
{
|
||||
if (!this->CollectExports([&](cmGeneratorTarget const*) {})) {
|
||||
return false;
|
||||
}
|
||||
|
||||
cmSbomDocument doc;
|
||||
doc.Graph.reserve(256);
|
||||
|
||||
cmSpdxDocument* project = insert_back(doc.Graph, this->GenerateSbom());
|
||||
std::vector<TargetProperties> targets;
|
||||
|
||||
for (auto const& exp : this->Exports) {
|
||||
cmGeneratorTarget const* target = exp.Target;
|
||||
|
||||
ImportPropertyMap properties;
|
||||
this->PopulateInterfaceProperties(target, properties);
|
||||
this->PopulateInterfaceLinkLibrariesProperty(
|
||||
target, cmGeneratorExpression::BuildInterface, properties);
|
||||
this->PopulateLinkLibrariesProperty(
|
||||
target, cmGeneratorExpression::BuildInterface, properties);
|
||||
|
||||
targets.push_back(TargetProperties{
|
||||
insert_back(project->RootElements, this->GenerateImportTarget(target)),
|
||||
target, std::move(properties) });
|
||||
}
|
||||
|
||||
for (auto const& target : targets) {
|
||||
this->GenerateProperties(doc, project, target, targets);
|
||||
}
|
||||
|
||||
this->WriteSbom(doc, os);
|
||||
return true;
|
||||
}
|
||||
|
||||
void cmExportBuildSbomGenerator::HandleMissingTarget(
|
||||
std::string& /* link_libs */, cmGeneratorTarget const* /* depender */,
|
||||
cmGeneratorTarget* /* dependee */)
|
||||
{
|
||||
}
|
||||
|
||||
std::string cmExportBuildSbomGenerator::GetCxxModulesDirectory() const
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
cm::string_view cmExportBuildSbomGenerator::GetImportPrefixWithSlash() const
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string cmExportBuildSbomGenerator::GetCxxModuleFile(
|
||||
std::string const& /*name*/) const
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
void cmExportBuildSbomGenerator::GenerateCxxModuleConfigInformation(
|
||||
std::string const& /*name*/, std::ostream& /*os*/) const
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
41
Source/cmExportBuildSbomGenerator.h
Normal file
41
Source/cmExportBuildSbomGenerator.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file LICENSE.rst or https://cmake.org/licensing for details. */
|
||||
#pragma once
|
||||
|
||||
#include "cmConfigure.h" // IWYU pragma: keep
|
||||
|
||||
#include <iosfwd>
|
||||
#include <string>
|
||||
|
||||
#include <cm/string_view>
|
||||
|
||||
#include "cmExportBuildFileGenerator.h"
|
||||
#include "cmExportSbomGenerator.h"
|
||||
|
||||
class cmSbomArguments;
|
||||
|
||||
class cmExportBuildSbomGenerator
|
||||
: public cmExportBuildFileGenerator
|
||||
, public cmExportSbomGenerator
|
||||
{
|
||||
public:
|
||||
cmExportBuildSbomGenerator(cmSbomArguments args);
|
||||
|
||||
protected:
|
||||
void HandleMissingTarget(std::string& link_libs,
|
||||
cmGeneratorTarget const* depender,
|
||||
cmGeneratorTarget* dependee) override;
|
||||
bool GenerateMainFile(std::ostream& os) override;
|
||||
void GenerateImportTargetsConfig(std::ostream&, std::string const&,
|
||||
std::string const&) override
|
||||
{
|
||||
}
|
||||
std::string GetCxxModulesDirectory() const override;
|
||||
|
||||
cm::string_view GetImportPrefixWithSlash() const override;
|
||||
|
||||
std::string GetCxxModuleFile(std::string const& /*name*/) const override;
|
||||
|
||||
void GenerateCxxModuleConfigInformation(std::string const& /*name*/,
|
||||
std::ostream& /*os*/) const override;
|
||||
};
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "cmExportBuildCMakeConfigGenerator.h"
|
||||
#include "cmExportBuildFileGenerator.h"
|
||||
#include "cmExportBuildPackageInfoGenerator.h"
|
||||
#include "cmExportBuildSbomGenerator.h"
|
||||
#include "cmExportSet.h"
|
||||
#include "cmGeneratedFileStream.h"
|
||||
#include "cmGlobalGenerator.h"
|
||||
@@ -30,6 +31,7 @@
|
||||
#include "cmPackageInfoArguments.h"
|
||||
#include "cmPolicies.h"
|
||||
#include "cmRange.h"
|
||||
#include "cmSbomArguments.h"
|
||||
#include "cmStateTypes.h"
|
||||
#include "cmStringAlgorithms.h"
|
||||
#include "cmSubcommandTable.h"
|
||||
@@ -217,6 +219,7 @@ static bool HandleExportMode(std::vector<std::string> const& args,
|
||||
ArgumentParser::NonEmpty<std::string> Filename;
|
||||
ArgumentParser::NonEmpty<std::string> CxxModulesDirectory;
|
||||
cm::optional<cmPackageInfoArguments> PackageInfo;
|
||||
cm::optional<cmSbomArguments> Sbom;
|
||||
bool ExportPackageDependencies = false;
|
||||
};
|
||||
|
||||
@@ -243,16 +246,29 @@ static bool HandleExportMode(std::vector<std::string> const& args,
|
||||
&ExportArguments::PackageInfo);
|
||||
}
|
||||
|
||||
cmArgumentParser<cmSbomArguments> sbomParser;
|
||||
cmSbomArguments::Bind(sbomParser);
|
||||
|
||||
if (cmExperimental::HasSupportEnabled(
|
||||
status.GetMakefile(), cmExperimental::Feature::GenerateSbom)) {
|
||||
parser.BindSubParser("SBOM"_s, sbomParser, &ExportArguments::Sbom);
|
||||
}
|
||||
|
||||
std::vector<std::string> unknownArgs;
|
||||
ExportArguments arguments = parser.Parse(args, &unknownArgs);
|
||||
|
||||
cmMakefile& mf = status.GetMakefile();
|
||||
cmGlobalGenerator* gg = mf.GetGlobalGenerator();
|
||||
|
||||
if (arguments.PackageInfo && arguments.Sbom) {
|
||||
status.SetError("PACKAGE_INFO and SBOM are mutually exclusive.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!arguments.Check(args[0], &unknownArgs, status)) {
|
||||
cmPolicies::PolicyStatus const p =
|
||||
status.GetMakefile().GetPolicyStatus(cmPolicies::CMP0208);
|
||||
if (arguments.PackageInfo || !unknownArgs.empty() ||
|
||||
if (arguments.PackageInfo || arguments.Sbom || !unknownArgs.empty() ||
|
||||
p == cmPolicies::NEW) {
|
||||
return false;
|
||||
}
|
||||
@@ -279,11 +295,31 @@ static bool HandleExportMode(std::vector<std::string> const& args,
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (arguments.Sbom) {
|
||||
if (arguments.Sbom->PackageName.empty()) {
|
||||
status.SetError("SBOM missing required value.");
|
||||
return false;
|
||||
}
|
||||
if (!arguments.Filename.empty()) {
|
||||
status.SetError("SBOM and FILE are mutually exclusive.");
|
||||
return false;
|
||||
}
|
||||
if (!arguments.Namespace.empty()) {
|
||||
status.SetError("SBOM and NAMESPACE are mutually exclusive.");
|
||||
return false;
|
||||
}
|
||||
if (!arguments.Sbom->Check(status) ||
|
||||
!arguments.Sbom->SetMetadataFromProject(status)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
std::string fname;
|
||||
if (arguments.Filename.empty()) {
|
||||
if (arguments.PackageInfo) {
|
||||
fname = arguments.PackageInfo->GetPackageFileName();
|
||||
} else if (arguments.Sbom) {
|
||||
fname = arguments.Sbom->GetPackageFileName();
|
||||
} else {
|
||||
fname = arguments.ExportSetName + ".cmake";
|
||||
}
|
||||
@@ -338,6 +374,9 @@ static bool HandleExportMode(std::vector<std::string> const& args,
|
||||
auto ebpg = cm::make_unique<cmExportBuildPackageInfoGenerator>(
|
||||
*arguments.PackageInfo);
|
||||
ebfg = std::move(ebpg);
|
||||
} else if (arguments.Sbom) {
|
||||
auto ebsg = cm::make_unique<cmExportBuildSbomGenerator>(*arguments.Sbom);
|
||||
ebfg = std::move(ebsg);
|
||||
} else {
|
||||
auto ebcg = cm::make_unique<cmExportBuildCMakeConfigGenerator>();
|
||||
ebcg->SetNamespace(arguments.Namespace);
|
||||
|
||||
@@ -50,9 +50,9 @@ protected:
|
||||
cmGeneratorTarget const* /* depender */,
|
||||
cmGeneratorTarget* /* dependee */) override;
|
||||
|
||||
bool CheckInterfaceDirs(std::string const& prepro,
|
||||
cmGeneratorTarget const* target,
|
||||
std::string const& prop) const override;
|
||||
bool CheckInterfaceDirs(std::string const& /* prepro */,
|
||||
cmGeneratorTarget const* /* target */,
|
||||
std::string const& /* prop */) const override;
|
||||
|
||||
char GetConfigFileNameSeparator() const override { return '@'; }
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file LICENSE.rst or https://cmake.org/licensing for details. */
|
||||
file LICENSE.rst or https://cmake.org/licensing for details. */
|
||||
#include "cmExportSbomGenerator.h"
|
||||
|
||||
#include <array>
|
||||
|
||||
@@ -1341,6 +1341,7 @@ add_RunCMake_test(AutoExportDll
|
||||
|
||||
add_RunCMake_test(AndroidMK)
|
||||
add_RunCMake_test(ExportPackageInfo)
|
||||
add_RunCMake_test(ExportSbom)
|
||||
add_RunCMake_test(InstallPackageInfo)
|
||||
add_RunCMake_test(InstallExportsAsPackageInfo)
|
||||
add_RunCMake_test(InstallSbom)
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
file(READ "${RunCMake_TEST_BINARY_DIR}/application_targets.spdx.json" content)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/../Sbom/ApplicationTarget-install-check.cmake)
|
||||
7
Tests/RunCMake/ExportSbom/ApplicationTarget.cmake
Normal file
7
Tests/RunCMake/ExportSbom/ApplicationTarget.cmake
Normal file
@@ -0,0 +1,7 @@
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/../Sbom/ApplicationTarget.cmake)
|
||||
|
||||
export(
|
||||
EXPORT application_targets
|
||||
SBOM application_targets
|
||||
FORMAT "spdx-3.0+json"
|
||||
)
|
||||
3
Tests/RunCMake/ExportSbom/CMakeLists.txt
Normal file
3
Tests/RunCMake/ExportSbom/CMakeLists.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
cmake_minimum_required(VERSION 3.30)
|
||||
project(${RunCMake_TEST} NONE)
|
||||
include(${RunCMake_TEST}.cmake)
|
||||
@@ -0,0 +1,2 @@
|
||||
file(READ "${RunCMake_TEST_BINARY_DIR}/interface_targets.spdx.json" content)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/../Sbom/InterfaceTarget-install-check.cmake)
|
||||
6
Tests/RunCMake/ExportSbom/InterfaceTarget.cmake
Normal file
6
Tests/RunCMake/ExportSbom/InterfaceTarget.cmake
Normal file
@@ -0,0 +1,6 @@
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/../Sbom/InterfaceTarget.cmake)
|
||||
|
||||
export(
|
||||
EXPORT interface_targets
|
||||
SBOM interface_targets
|
||||
)
|
||||
@@ -0,0 +1,2 @@
|
||||
file(READ "${RunCMake_TEST_BINARY_DIR}/interface_targets.spdx.json" content)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/../Sbom/MissingPackageNamespace-install-check.cmake)
|
||||
7
Tests/RunCMake/ExportSbom/MissingPackageNamespace.cmake
Normal file
7
Tests/RunCMake/ExportSbom/MissingPackageNamespace.cmake
Normal file
@@ -0,0 +1,7 @@
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/../Sbom/MissingPackageNamespace.cmake)
|
||||
|
||||
export(
|
||||
EXPORT test_targets
|
||||
SBOM interface_targets
|
||||
VERSION 1.0.2
|
||||
)
|
||||
@@ -0,0 +1,2 @@
|
||||
file(READ "${RunCMake_TEST_BINARY_DIR}/test_targets.spdx.json" content)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/../Sbom/ProjectMetadata-install-check.cmake)
|
||||
10
Tests/RunCMake/ExportSbom/ProjectMetadata.cmake
Normal file
10
Tests/RunCMake/ExportSbom/ProjectMetadata.cmake
Normal file
@@ -0,0 +1,10 @@
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/../Sbom/ProjectMetadata.cmake)
|
||||
|
||||
export(
|
||||
EXPORT test_targets
|
||||
SBOM test_targets
|
||||
DESCRIPTION "An eloquent description"
|
||||
LICENSE "BSD-3"
|
||||
HOMEPAGE_URL "www.example.com"
|
||||
VERSION "1.3.4"
|
||||
)
|
||||
@@ -0,0 +1,2 @@
|
||||
file(READ "${RunCMake_TEST_BINARY_DIR}/dog.spdx.json" content)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/../Sbom/ReferencesNonExportedTarget-install-check.cmake)
|
||||
@@ -0,0 +1,3 @@
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/../Sbom/ReferencesNonExportedTarget.cmake)
|
||||
|
||||
export(EXPORT dog SBOM dog)
|
||||
@@ -0,0 +1,3 @@
|
||||
file(READ "${RunCMake_TEST_BINARY_DIR}/bar.spdx.json" BAR_CONTENT)
|
||||
file(READ "${RunCMake_TEST_BINARY_DIR}/foo.spdx.json" FOO_CONTENT)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/../Sbom/Requirements-install-check.cmake)
|
||||
4
Tests/RunCMake/ExportSbom/Requirements.cmake
Normal file
4
Tests/RunCMake/ExportSbom/Requirements.cmake
Normal file
@@ -0,0 +1,4 @@
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/../Sbom/Requirements.cmake)
|
||||
|
||||
export(EXPORT foo SBOM foo)
|
||||
export(EXPORT bar SBOM bar)
|
||||
32
Tests/RunCMake/ExportSbom/RunCMakeTest.cmake
Normal file
32
Tests/RunCMake/ExportSbom/RunCMakeTest.cmake
Normal file
@@ -0,0 +1,32 @@
|
||||
include(RunCMake)
|
||||
|
||||
set(common_test_options
|
||||
-Wno-dev
|
||||
"-DCMAKE_EXPERIMENTAL_GENERATE_SBOM:STRING=ca494ed3-b261-4205-a01f-603c95e4cae0"
|
||||
"-DCMAKE_EXPERIMENTAL_FIND_CPS_PACKAGES:STRING=e82e467b-f997-4464-8ace-b00808fff261"
|
||||
"-DCMAKE_EXPERIMENTAL_EXPORT_PACKAGE_INFO:STRING=b80be207-778e-46ba-8080-b23bba22639e"
|
||||
)
|
||||
|
||||
function(run_cmake_install test)
|
||||
set(extra_options ${ARGN})
|
||||
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${test}-build)
|
||||
set(RunCMake_TEST_INSTALL_DIR ${RunCMake_BINARY_DIR}/${test}-install)
|
||||
set(RunCMake_TEST_OPTIONS ${common_test_options} ${extra_options})
|
||||
list(APPEND RunCMake_TEST_OPTIONS -DCMAKE_INSTALL_PREFIX=${RunCMake_TEST_INSTALL_DIR})
|
||||
if(NOT RunCMake_GENERATOR_IS_MULTI_CONFIG)
|
||||
list(APPEND RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=DEBUG)
|
||||
endif()
|
||||
|
||||
run_cmake(${test})
|
||||
set(RunCMake_TEST_NO_CLEAN TRUE)
|
||||
run_cmake_command(${test}-build ${CMAKE_COMMAND} --build . --config Debug)
|
||||
run_cmake_command(${test}-install ${CMAKE_COMMAND} --install . --config Debug)
|
||||
endfunction()
|
||||
|
||||
run_cmake_install(ApplicationTarget)
|
||||
run_cmake_install(InterfaceTarget)
|
||||
run_cmake_install(SharedTarget)
|
||||
run_cmake_install(Requirements)
|
||||
|
||||
run_cmake_install(MissingPackageNamespace)
|
||||
run_cmake_install(ReferencesNonExportedTarget)
|
||||
@@ -0,0 +1,2 @@
|
||||
file(READ "${RunCMake_TEST_BINARY_DIR}/shared_targets.spdx.json" content)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/../Sbom/SharedTarget-install-check.cmake)
|
||||
6
Tests/RunCMake/ExportSbom/SharedTarget.cmake
Normal file
6
Tests/RunCMake/ExportSbom/SharedTarget.cmake
Normal file
@@ -0,0 +1,6 @@
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/../Sbom/SharedTarget.cmake)
|
||||
|
||||
export(
|
||||
EXPORT shared_targets
|
||||
SBOM shared_targets
|
||||
)
|
||||
Reference in New Issue
Block a user