mirror of
https://gitlab.kitware.com/cmake/cmake.git
synced 2026-09-25 04:09:36 +03:00
Merge topic 'multi_export_sbom'
2900aa2911SBOM: Update experimental UUID273fc4cc49SBOM: Support multi export set SBOMs9669829573Install: Refactor ResolveTargetsInGeneratorExpression7c31cbf9aeSBOM: Handle PACKAGE_URL argument Acked-by: Kitware Robot <kwrobot@kitware.com> Merge-request: !12080
This commit is contained in:
@@ -174,7 +174,7 @@ Exporting Software Bill of Materials (SBOM) Documents
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
export(SBOM <sbom-name> EXPORT <export-name>
|
||||
export(SBOM <sbom-name> EXPORTS <export-names>...
|
||||
[FORMAT <string>]
|
||||
[PROJECT <project-name>|NO_PROJECT_METADATA]
|
||||
[VERSION <major>[.<minor>[.<patch>[.<tweak>]]]]
|
||||
@@ -189,9 +189,10 @@ Exporting Software Bill of Materials (SBOM) Documents
|
||||
Experimental. Gated by ``CMAKE_EXPERIMENTAL_GENERATE_SBOM``.
|
||||
|
||||
Generates a software bill of materials (SBOM) document describing the targets
|
||||
in the export ``<export-name>`` and their dependencies in the build tree.
|
||||
Files are written to the ``sbom/<sbom-name>`` subdirectory of the current
|
||||
build directory.
|
||||
in the listed ``<export-names>`` export sets and their dependencies in the
|
||||
build tree. Targets from all listed exports are aggregated into one document.
|
||||
The generated SBOM will be written to the ``sbom/<sbom-name>`` subdirectory of
|
||||
the current build directory.
|
||||
|
||||
See :command:`install(SBOM)` for details about the supported SBOM formats and a
|
||||
description of the other options.
|
||||
|
||||
@@ -1213,7 +1213,7 @@ Signatures
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
install(SBOM <sbom-name> EXPORT <export-name>
|
||||
install(SBOM <sbom-name> EXPORTS <export-names>...
|
||||
[PROJECT <project-name>|NO_PROJECT_METADATA]
|
||||
[DESTINATION <dir>]
|
||||
[VERSION <major>[.<minor>[.<patch>[.<tweak>]]]]
|
||||
@@ -1232,9 +1232,11 @@ Signatures
|
||||
the interface is designed to allow additional SBOM formats or schema
|
||||
versions to be supported in future CMake releases.
|
||||
|
||||
Target installations are associated with the export ``<export-name>``
|
||||
using the ``EXPORT`` option of the :command:`install(TARGETS)` signature
|
||||
documented above. If ``DESTINATION`` is not specified, a platform-specific
|
||||
Target installations are associated with each export ``<export-names>``
|
||||
in the ``EXPORTS`` list using the ``EXPORTS`` option of the
|
||||
:command:`install(TARGETS)` signature documented above. A single SBOM may
|
||||
cover multiple export sets; targets from all listed exports are aggregated
|
||||
into one document. If ``DESTINATION`` is not specified, a platform-specific
|
||||
default is used.
|
||||
|
||||
Several options may be used to specify package metadata:
|
||||
|
||||
@@ -109,7 +109,7 @@ In order to activate support for the :command:`install(SBOM)` command,
|
||||
set
|
||||
|
||||
* variable ``CMAKE_EXPERIMENTAL_GENERATE_SBOM`` to
|
||||
* value ``ca494ed3-b261-4205-a01f-603c95e4cae0``.
|
||||
* value ``2d856d6d-53e8-488b-a17f-d486d2cac317``.
|
||||
|
||||
This UUID may change in future versions of CMake. Be sure to use the value
|
||||
documented here by the source tree of the version of CMake with which you are
|
||||
|
||||
+10
-8
@@ -214,8 +214,10 @@ add_library(
|
||||
cmExportBuildFileGenerator.cxx
|
||||
cmExportBuildPackageInfoGenerator.h
|
||||
cmExportBuildPackageInfoGenerator.cxx
|
||||
cmExportBuildSbomGenerator.h
|
||||
cmExportBuildSbomGenerator.cxx
|
||||
cmBuildSbomGenerator.h
|
||||
cmBuildSbomGenerator.cxx
|
||||
cmBuildSbomBuilder.h
|
||||
cmBuildSbomBuilder.cxx
|
||||
cmExportCMakeConfigGenerator.h
|
||||
cmExportCMakeConfigGenerator.cxx
|
||||
cmExportFileGenerator.h
|
||||
@@ -228,14 +230,12 @@ add_library(
|
||||
cmExportInstallFileGenerator.cxx
|
||||
cmExportInstallPackageInfoGenerator.h
|
||||
cmExportInstallPackageInfoGenerator.cxx
|
||||
cmExportInstallSbomGenerator.h
|
||||
cmExportInstallSbomGenerator.cxx
|
||||
cmExportPackageInfoGenerator.h
|
||||
cmExportPackageInfoGenerator.cxx
|
||||
cmExportTryCompileFileGenerator.h
|
||||
cmExportTryCompileFileGenerator.cxx
|
||||
cmExportSbomGenerator.h
|
||||
cmExportSbomGenerator.cxx
|
||||
cmSbomBuilder.h
|
||||
cmSbomBuilder.cxx
|
||||
cmExportSet.h
|
||||
cmExportSet.cxx
|
||||
cmExternalMakefileProjectGenerator.cxx
|
||||
@@ -369,8 +369,10 @@ add_library(
|
||||
cmInstallRuntimeDependencySet.cxx
|
||||
cmInstallRuntimeDependencySetGenerator.h
|
||||
cmInstallRuntimeDependencySetGenerator.cxx
|
||||
cmInstallSbomExportGenerator.h
|
||||
cmInstallSbomExportGenerator.cxx
|
||||
cmInstallSbomGenerator.h
|
||||
cmInstallSbomGenerator.cxx
|
||||
cmInstallSbomBuilder.h
|
||||
cmInstallSbomBuilder.cxx
|
||||
cmInstallScriptGenerator.h
|
||||
cmInstallScriptGenerator.cxx
|
||||
cmInstallSubdirectoryGenerator.h
|
||||
|
||||
@@ -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. */
|
||||
#include "cmBuildSbomBuilder.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "cmGeneratorExpression.h"
|
||||
#include "cmGeneratorTarget.h"
|
||||
#include "cmGlobalGenerator.h"
|
||||
#include "cmLocalGenerator.h"
|
||||
#include "cmSbomArguments.h"
|
||||
|
||||
cmBuildSbomBuilder::cmBuildSbomBuilder(cmSbomArguments args,
|
||||
std::vector<cmExportSet*> exportSets,
|
||||
cmLocalGenerator* lg)
|
||||
: cmSbomBuilder(std::move(args), std::move(exportSets), lg)
|
||||
{
|
||||
}
|
||||
|
||||
bool cmBuildSbomBuilder::Generate(std::ostream& os)
|
||||
{
|
||||
if (!this->LocalGenerator) {
|
||||
return false;
|
||||
}
|
||||
return this->GenerateForTargets(os, cmGeneratorExpression::BuildInterface);
|
||||
}
|
||||
|
||||
cmExportFileGenerator::ExportInfo cmBuildSbomBuilder::FindExportInfoFor(
|
||||
cmGeneratorTarget const* target) const
|
||||
{
|
||||
return target->GetLocalGenerator()
|
||||
->GetGlobalGenerator()
|
||||
->FindBuildExportInfo(target);
|
||||
}
|
||||
|
||||
cmSbomBuilder::SbomInfo cmBuildSbomBuilder::FindSbomInfoFor(
|
||||
cmGeneratorTarget const* target) const
|
||||
{
|
||||
return target->GetLocalGenerator()->GetGlobalGenerator()->FindBuildSbomInfo(
|
||||
target);
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/* 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 <vector>
|
||||
|
||||
#include "cmExportFileGenerator.h"
|
||||
#include "cmSbomBuilder.h"
|
||||
|
||||
class cmExportSet;
|
||||
class cmLocalGenerator;
|
||||
class cmSbomArguments;
|
||||
|
||||
/** Build-tree SBOM (`export(SBOM ...)`). Covers the targets in the
|
||||
* associated export sets. */
|
||||
class cmBuildSbomBuilder final : public cmSbomBuilder
|
||||
{
|
||||
public:
|
||||
cmBuildSbomBuilder(cmSbomArguments args,
|
||||
std::vector<cmExportSet*> exportSets,
|
||||
cmLocalGenerator* lg = nullptr);
|
||||
|
||||
bool Generate(std::ostream& os) override;
|
||||
|
||||
protected:
|
||||
cmExportFileGenerator::ExportInfo FindExportInfoFor(
|
||||
cmGeneratorTarget const* target) const override;
|
||||
SbomInfo FindSbomInfoFor(cmGeneratorTarget const* target) const override;
|
||||
};
|
||||
@@ -0,0 +1,16 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file LICENSE.rst or https://cmake.org/licensing for details. */
|
||||
#include "cmBuildSbomGenerator.h"
|
||||
|
||||
#include "cmGeneratedFileStream.h"
|
||||
|
||||
void cmBuildSbomGenerator::Compute(cmLocalGenerator* lg)
|
||||
{
|
||||
this->Builder->Compute(lg);
|
||||
}
|
||||
|
||||
bool cmBuildSbomGenerator::GenerateForBuild()
|
||||
{
|
||||
cmGeneratedFileStream os(this->OutputFile);
|
||||
return this->Builder->Generate(os);
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file LICENSE.rst or https://cmake.org/licensing for details. */
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <cm/memory>
|
||||
|
||||
#include "cmBuildSbomBuilder.h"
|
||||
#include "cmSbomArguments.h"
|
||||
|
||||
class cmExportSet;
|
||||
class cmGeneratorTarget;
|
||||
class cmLocalGenerator;
|
||||
|
||||
/** \class cmBuildSbomGenerator
|
||||
* \brief Thin wrapper around cmBuildSbomBuilder for the build-tree SBOM case.
|
||||
*
|
||||
* Stored on cmMakefile at configure time. At generate time,
|
||||
* ComputeBuildFileGenerators() calls Compute(lg) to resolve export set
|
||||
* targets and supply the local generator — mirroring
|
||||
* cmExportBuildFileGenerator.
|
||||
*/
|
||||
class cmBuildSbomGenerator
|
||||
{
|
||||
public:
|
||||
cmBuildSbomGenerator(cmSbomArguments args,
|
||||
std::vector<cmExportSet*> exportSets,
|
||||
std::string outputFile)
|
||||
: OutputFile(std::move(outputFile))
|
||||
, Builder(cm::make_unique<cmBuildSbomBuilder>(std::move(args),
|
||||
std::move(exportSets)))
|
||||
{
|
||||
}
|
||||
|
||||
void Compute(cmLocalGenerator* lg);
|
||||
|
||||
std::string const& GetOutputFile() const { return this->OutputFile; }
|
||||
|
||||
/** True if this SBOM directly describes `target`. Used by peer SBOMs to
|
||||
* attribute cross-references when install(export) provenance is absent. */
|
||||
bool CoversTarget(cmGeneratorTarget const* target) const
|
||||
{
|
||||
return this->Builder->CoversTarget(target);
|
||||
}
|
||||
std::string const& GetPackageName() const
|
||||
{
|
||||
return this->Builder->GetPackageName();
|
||||
}
|
||||
|
||||
/** Open the output file and write the SBOM document to it. */
|
||||
bool GenerateForBuild();
|
||||
|
||||
private:
|
||||
std::string OutputFile;
|
||||
std::unique_ptr<cmBuildSbomBuilder> Builder;
|
||||
};
|
||||
@@ -55,7 +55,7 @@ cmExperimental::FeatureData const LookupTable[] = {
|
||||
{},
|
||||
cmExperimental::TryCompileCondition::Never },
|
||||
{ "GenerateSbom",
|
||||
"ca494ed3-b261-4205-a01f-603c95e4cae0",
|
||||
"2d856d6d-53e8-488b-a17f-d486d2cac317",
|
||||
"CMAKE_EXPERIMENTAL_GENERATE_SBOM",
|
||||
"CMake's support for generating software bill of materials (Sbom) "
|
||||
"information in SPDX format is experimental. It is meant only for "
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
#include "cmExportBuildFileGenerator.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
@@ -177,33 +176,29 @@ void cmExportBuildFileGenerator::GetTargets(
|
||||
cmExportFileGenerator::ExportInfo cmExportBuildFileGenerator::FindExportInfo(
|
||||
cmGeneratorTarget const* target) const
|
||||
{
|
||||
std::vector<std::string> exportFiles;
|
||||
std::set<std::string> exportSets;
|
||||
std::set<std::string> namespaces;
|
||||
return target->GetLocalGenerator()
|
||||
->GetGlobalGenerator()
|
||||
->FindBuildExportInfo(target);
|
||||
}
|
||||
|
||||
cm::optional<cmExportBuildFileGenerator::ExportRecord>
|
||||
cmExportBuildFileGenerator::FindRecordForTarget(
|
||||
cmGeneratorTarget const* target) const
|
||||
{
|
||||
auto const& name = target->GetName();
|
||||
auto& allExportSets =
|
||||
target->GetLocalGenerator()->GetGlobalGenerator()->GetBuildExportSets();
|
||||
|
||||
for (auto const& exp : allExportSets) {
|
||||
cmExportBuildFileGenerator const* const bfg = exp.second;
|
||||
cmExportSet const* const exportSet = bfg->GetExportSet();
|
||||
std::vector<TargetExport> targets;
|
||||
bfg->GetTargets(targets);
|
||||
if (std::any_of(
|
||||
targets.begin(), targets.end(),
|
||||
[&name](TargetExport const& te) { return te.Name == name; })) {
|
||||
if (exportSet) {
|
||||
exportSets.insert(exportSet->GetName());
|
||||
} else {
|
||||
exportSets.insert(exp.first);
|
||||
}
|
||||
exportFiles.push_back(exp.first);
|
||||
namespaces.insert(bfg->GetNamespace());
|
||||
}
|
||||
std::vector<TargetExport> targets;
|
||||
this->GetTargets(targets);
|
||||
bool const contains =
|
||||
std::any_of(targets.begin(), targets.end(),
|
||||
[&name](TargetExport const& te) { return te.Name == name; });
|
||||
cm::optional<ExportRecord> result;
|
||||
if (contains) {
|
||||
ExportRecord rec;
|
||||
rec.Name = this->ExportSet ? this->ExportSet->GetName() : std::string{};
|
||||
rec.Namespace = this->GetNamespace();
|
||||
result = rec;
|
||||
}
|
||||
|
||||
return { exportFiles, exportSets, namespaces };
|
||||
return result;
|
||||
}
|
||||
|
||||
void cmExportBuildFileGenerator::ComplainAboutMissingTarget(
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <cm/optional>
|
||||
#include <cmext/algorithm>
|
||||
|
||||
#include "cmDiagnostics.h"
|
||||
@@ -56,6 +57,18 @@ public:
|
||||
}
|
||||
void SetExportSet(cmExportSet*);
|
||||
|
||||
struct ExportRecord
|
||||
{
|
||||
std::string Name; // export set name; empty for anonymous exports
|
||||
std::string Namespace; // export namespace
|
||||
};
|
||||
|
||||
/** If this export contains `target`, return a record identifying it
|
||||
* (export set name + namespace). Used by cmGlobalGenerator to assemble
|
||||
* a project-wide view of where targets are exported. */
|
||||
cm::optional<ExportRecord> FindRecordForTarget(
|
||||
cmGeneratorTarget const* target) const;
|
||||
|
||||
/** Set the name of the C++ module directory. */
|
||||
void SetCxxModuleDirectory(std::string cxx_module_dir)
|
||||
{
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
/* 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);
|
||||
|
||||
cmSpdxCreationInfo const* ci =
|
||||
insert_back(doc.Graph, this->GenerateCreationInfo());
|
||||
cmSpdxDocument* project = insert_back(doc.Graph, this->GenerateSbom(ci));
|
||||
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(ci, target)),
|
||||
target, std::move(properties) });
|
||||
}
|
||||
|
||||
for (auto const& target : targets) {
|
||||
this->GenerateProperties(doc, project, ci, 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
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
/* 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;
|
||||
};
|
||||
+85
-24
@@ -15,6 +15,7 @@
|
||||
|
||||
#include "cmArgumentParser.h"
|
||||
#include "cmArgumentParserTypes.h"
|
||||
#include "cmBuildSbomGenerator.h"
|
||||
#include "cmCryptoHash.h"
|
||||
#include "cmDiagnostics.h"
|
||||
#include "cmExecutionStatus.h"
|
||||
@@ -23,7 +24,6 @@
|
||||
#include "cmExportBuildCMakeConfigGenerator.h"
|
||||
#include "cmExportBuildFileGenerator.h"
|
||||
#include "cmExportBuildPackageInfoGenerator.h"
|
||||
#include "cmExportBuildSbomGenerator.h"
|
||||
#include "cmExportSet.h"
|
||||
#include "cmGeneratedFileStream.h"
|
||||
#include "cmGlobalGenerator.h"
|
||||
@@ -88,6 +88,29 @@ static void AddExportGenerator(
|
||||
makefile.AddExportBuildFileGenerator(std::move(exportGenerator));
|
||||
}
|
||||
|
||||
static bool ValidateExportableTarget(std::string const& name, cmMakefile& mf,
|
||||
cmGlobalGenerator* gg,
|
||||
cmExecutionStatus& status)
|
||||
{
|
||||
if (mf.IsAlias(name)) {
|
||||
status.SetError(cmStrCat("given ALIAS target \"", name,
|
||||
"\" which may not be exported."));
|
||||
return false;
|
||||
}
|
||||
cmTarget const* target = gg->FindTarget(name);
|
||||
if (!target) {
|
||||
status.SetError(cmStrCat("given target \"", name,
|
||||
"\" which is not built by this project."));
|
||||
return false;
|
||||
}
|
||||
if (target->GetType() == cmStateEnums::UTILITY) {
|
||||
status.SetError(cmStrCat("given custom target \"", name,
|
||||
"\" which may not be exported."));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool HandleTargetsMode(std::vector<std::string> const& args,
|
||||
cmExecutionStatus& status)
|
||||
{
|
||||
@@ -163,25 +186,7 @@ static bool HandleTargetsMode(std::vector<std::string> const& args,
|
||||
cmGlobalGenerator* gg = mf.GetGlobalGenerator();
|
||||
|
||||
for (std::string const& currentTarget : *arguments.Targets) {
|
||||
if (mf.IsAlias(currentTarget)) {
|
||||
std::ostringstream e;
|
||||
e << "given ALIAS target \"" << currentTarget
|
||||
<< "\" which may not be exported.";
|
||||
status.SetError(e.str());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cmTarget* target = gg->FindTarget(currentTarget)) {
|
||||
if (target->GetType() == cmStateEnums::UTILITY) {
|
||||
status.SetError("given custom target \"" + currentTarget +
|
||||
"\" which may not be exported.");
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
std::ostringstream e;
|
||||
e << "given target \"" << currentTarget
|
||||
<< "\" which is not built by this project.";
|
||||
status.SetError(e.str());
|
||||
if (!ValidateExportableTarget(currentTarget, mf, gg, status)) {
|
||||
return false;
|
||||
}
|
||||
targets.emplace_back(currentTarget, std::string{});
|
||||
@@ -413,10 +418,66 @@ static bool HandleSbomMode(std::vector<std::string> const& args,
|
||||
return false;
|
||||
}
|
||||
|
||||
using arg_t = cmSbomArguments;
|
||||
using gen_t = cmExportBuildSbomGenerator;
|
||||
status.GetMakefile().SetExplicitlyGeneratesSbom(true);
|
||||
return HandleSpecialExportMode<arg_t, gen_t>(args, status);
|
||||
struct SbomExportArguments
|
||||
: public cmSbomArguments
|
||||
, public ArgumentParser::ParseResult
|
||||
{
|
||||
ArgumentParser::NonEmpty<std::vector<std::string>> ExportSetNames;
|
||||
|
||||
using cmSbomArguments::Check;
|
||||
using ArgumentParser::ParseResult::Check;
|
||||
};
|
||||
|
||||
auto parser = cmArgumentParser<SbomExportArguments>{};
|
||||
cmSbomArguments::Bind(parser);
|
||||
parser.Bind("EXPORTS"_s, &SbomExportArguments::ExportSetNames);
|
||||
|
||||
std::vector<std::string> unknownArgs;
|
||||
SbomExportArguments arguments = parser.Parse(args, &unknownArgs);
|
||||
|
||||
if (!arguments.Check(args[0], &unknownArgs, status)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (arguments.ExportSetNames.empty()) {
|
||||
status.SetError(cmStrCat(args[0], " missing EXPORTS."));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!arguments.Check(status) || !arguments.SetMetadataFromProject(status)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
cmMakefile& mf = status.GetMakefile();
|
||||
cmGlobalGenerator* gg = mf.GetGlobalGenerator();
|
||||
|
||||
std::string const dir =
|
||||
arguments.GetDefaultDestination(mf.GetCurrentBinaryDirectory());
|
||||
std::string const fpath = cmStrCat(dir, '/', arguments.GetPackageFileName());
|
||||
|
||||
if (gg->IsBuildSbomFile(fpath)) {
|
||||
status.SetError(cmStrCat("SBOM command already specified for the file "_s,
|
||||
cmSystemTools::GetFilenameNameView(fpath), '.'));
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<cmExportSet*> sets;
|
||||
sets.reserve(arguments.ExportSetNames.size());
|
||||
for (std::string const& name : arguments.ExportSetNames) {
|
||||
cm::optional<cmExportSet*> const exportSet =
|
||||
GetExportSet(name, gg, status);
|
||||
if (!exportSet) {
|
||||
return false;
|
||||
}
|
||||
sets.push_back(*exportSet);
|
||||
}
|
||||
|
||||
auto builder = cm::make_unique<cmBuildSbomGenerator>(arguments, sets, fpath);
|
||||
|
||||
cmBuildSbomGenerator* rawPtr = builder.get();
|
||||
mf.AddBuildSbomGenerator(std::move(builder));
|
||||
gg->AddBuildSbomGenerator(rawPtr);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool HandleSetupMode(std::vector<std::string> const& args,
|
||||
|
||||
@@ -4,10 +4,12 @@
|
||||
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
#include <sstream>
|
||||
#include <utility>
|
||||
|
||||
#include <cm/memory>
|
||||
#include <cm/optional>
|
||||
#include <cm/string_view>
|
||||
#include <cmext/string_view>
|
||||
|
||||
@@ -449,9 +451,9 @@ void cmExportFileGenerator::ResolveTargetsInGeneratorExpressions(
|
||||
}
|
||||
}
|
||||
|
||||
void cmExportFileGenerator::ResolveTargetsInGeneratorExpression(
|
||||
std::string& input, cmGeneratorTarget const* target,
|
||||
cmLocalGenerator const* lg)
|
||||
cm::optional<std::string> cmResolveTargetsInGeneratorExpression(
|
||||
std::string& input,
|
||||
std::function<bool(std::string& name)> const& addTargetNamespace)
|
||||
{
|
||||
std::string::size_type pos = 0;
|
||||
std::string::size_type lastPos = pos;
|
||||
@@ -474,13 +476,13 @@ void cmExportFileGenerator::ResolveTargetsInGeneratorExpression(
|
||||
std::string targetName =
|
||||
input.substr(nameStartPos, commaPos - nameStartPos);
|
||||
|
||||
if (this->AddTargetNamespace(targetName, target, lg)) {
|
||||
if (addTargetNamespace(targetName)) {
|
||||
input.replace(nameStartPos, commaPos - nameStartPos, targetName);
|
||||
}
|
||||
lastPos = nameStartPos + targetName.size() + 1;
|
||||
}
|
||||
|
||||
std::string errorString;
|
||||
cm::optional<std::string> errorString;
|
||||
pos = 0;
|
||||
lastPos = pos;
|
||||
while ((pos = input.find("$<TARGET_NAME:", lastPos)) != std::string::npos) {
|
||||
@@ -496,7 +498,7 @@ void cmExportFileGenerator::ResolveTargetsInGeneratorExpression(
|
||||
"literal.";
|
||||
break;
|
||||
}
|
||||
if (!this->AddTargetNamespace(targetName, target, lg)) {
|
||||
if (!addTargetNamespace(targetName)) {
|
||||
errorString = "$<TARGET_NAME:...> requires its parameter to be a "
|
||||
"reachable target.";
|
||||
break;
|
||||
@@ -507,7 +509,7 @@ void cmExportFileGenerator::ResolveTargetsInGeneratorExpression(
|
||||
|
||||
pos = 0;
|
||||
lastPos = pos;
|
||||
while (errorString.empty() &&
|
||||
while (!errorString &&
|
||||
(pos = input.find("$<LINK_ONLY:", lastPos)) != std::string::npos) {
|
||||
std::string::size_type nameStartPos = pos + cmStrLen("$<LINK_ONLY:");
|
||||
std::string::size_type endPos = input.find('>', nameStartPos);
|
||||
@@ -517,13 +519,13 @@ void cmExportFileGenerator::ResolveTargetsInGeneratorExpression(
|
||||
}
|
||||
std::string libName = input.substr(nameStartPos, endPos - nameStartPos);
|
||||
if (cmGeneratorExpression::IsValidTargetName(libName) &&
|
||||
this->AddTargetNamespace(libName, target, lg)) {
|
||||
addTargetNamespace(libName)) {
|
||||
input.replace(nameStartPos, endPos - nameStartPos, libName);
|
||||
}
|
||||
lastPos = nameStartPos + libName.size() + 1;
|
||||
}
|
||||
|
||||
while (errorString.empty() &&
|
||||
while (!errorString &&
|
||||
(pos = input.find("$<COMPILE_ONLY:", lastPos)) != std::string::npos) {
|
||||
std::string::size_type nameStartPos = pos + cmStrLen("$<COMPILE_ONLY:");
|
||||
std::string::size_type endPos = input.find('>', nameStartPos);
|
||||
@@ -533,17 +535,26 @@ void cmExportFileGenerator::ResolveTargetsInGeneratorExpression(
|
||||
}
|
||||
std::string libName = input.substr(nameStartPos, endPos - nameStartPos);
|
||||
if (cmGeneratorExpression::IsValidTargetName(libName) &&
|
||||
this->AddTargetNamespace(libName, target, lg)) {
|
||||
addTargetNamespace(libName)) {
|
||||
input.replace(nameStartPos, endPos - nameStartPos, libName);
|
||||
}
|
||||
lastPos = nameStartPos + libName.size() + 1;
|
||||
}
|
||||
|
||||
this->ReplaceInstallPrefix(input);
|
||||
return errorString;
|
||||
}
|
||||
|
||||
if (!errorString.empty()) {
|
||||
target->GetLocalGenerator()->IssueMessage(MessageType::FATAL_ERROR,
|
||||
errorString);
|
||||
void cmExportFileGenerator::ResolveTargetsInGeneratorExpression(
|
||||
std::string& input, cmGeneratorTarget const* target,
|
||||
cmLocalGenerator const* lg)
|
||||
{
|
||||
auto err = cmResolveTargetsInGeneratorExpression(
|
||||
input, [this, target, lg](std::string& name) {
|
||||
return this->AddTargetNamespace(name, target, lg);
|
||||
});
|
||||
this->ReplaceInstallPrefix(input);
|
||||
if (err) {
|
||||
target->GetLocalGenerator()->IssueMessage(MessageType::FATAL_ERROR, *err);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,12 +4,14 @@
|
||||
|
||||
#include "cmConfigure.h" // IWYU pragma: keep
|
||||
|
||||
#include <functional>
|
||||
#include <iosfwd>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <cm/optional>
|
||||
#include <cm/string_view>
|
||||
|
||||
#include "cmDiagnostics.h"
|
||||
@@ -32,6 +34,13 @@ public:
|
||||
cmExportFileGenerator();
|
||||
virtual ~cmExportFileGenerator() = default;
|
||||
|
||||
struct ExportInfo
|
||||
{
|
||||
std::vector<std::string> Files;
|
||||
std::set<std::string> Sets;
|
||||
std::set<std::string> Namespaces;
|
||||
};
|
||||
|
||||
/** Set the full path to the export file to generate. */
|
||||
void SetExportFile(char const* mainFile);
|
||||
std::string const& GetMainExportFileName() const;
|
||||
@@ -143,13 +152,6 @@ protected:
|
||||
this->IssueMessage(MessageType::FATAL_ERROR, errorMessage);
|
||||
}
|
||||
|
||||
struct ExportInfo
|
||||
{
|
||||
std::vector<std::string> Files;
|
||||
std::set<std::string> Sets;
|
||||
std::set<std::string> Namespaces;
|
||||
};
|
||||
|
||||
/** Find the set of export files and the unique namespace (if any) for a
|
||||
* target. */
|
||||
virtual ExportInfo FindExportInfo(cmGeneratorTarget const* target) const = 0;
|
||||
@@ -238,3 +240,16 @@ extern template void cmExportFileGenerator::SetImportLinkProperty<cmLinkItem>(
|
||||
std::string const&, cmGeneratorTarget const*, std::string const&,
|
||||
std::vector<cmLinkItem> const&, ImportPropertyMap& properties,
|
||||
ImportLinkPropertyTargetNames);
|
||||
|
||||
/** Walk a generator expression and rewrite the target-name slot of each
|
||||
`$<TARGET_PROPERTY:>`, `$<TARGET_NAME:>`, `$<LINK_ONLY:>`, and
|
||||
`$<COMPILE_ONLY:>` construct via the provided callback. The callback
|
||||
receives the bare target name; if it mutates the name and returns true,
|
||||
the helper splices the new name back into the genex. Returns the
|
||||
parse-level error message, if an error was encountered. Callers handle
|
||||
install-prefix substitution and error reporting themselves. This is used
|
||||
by the cmExportFileGenerator hierarchy, as well as the cmSbomBuilder
|
||||
hierarchy. */
|
||||
cm::optional<std::string> cmResolveTargetsInGeneratorExpression(
|
||||
std::string& input,
|
||||
std::function<bool(std::string& name)> const& addTargetNamespace);
|
||||
|
||||
@@ -265,34 +265,9 @@ void cmExportInstallFileGenerator::HandleMissingTarget(
|
||||
cmExportFileGenerator::ExportInfo cmExportInstallFileGenerator::FindExportInfo(
|
||||
cmGeneratorTarget const* target) const
|
||||
{
|
||||
std::vector<std::string> exportFiles;
|
||||
std::set<std::string> exportSets;
|
||||
std::set<std::string> namespaces;
|
||||
|
||||
auto const& name = target->GetName();
|
||||
auto& allExportSets =
|
||||
target->GetLocalGenerator()->GetGlobalGenerator()->GetExportSets();
|
||||
|
||||
for (auto const& exp : allExportSets) {
|
||||
auto const& exportSet = exp.second;
|
||||
auto const& targets = exportSet.GetTargetExports();
|
||||
|
||||
if (std::any_of(targets.begin(), targets.end(),
|
||||
[&name](std::unique_ptr<cmTargetExport> const& te) {
|
||||
return te->TargetName == name;
|
||||
})) {
|
||||
std::vector<cmInstallExportGenerator const*> const* installs =
|
||||
exportSet.GetInstallations();
|
||||
if (!installs->empty()) {
|
||||
exportSets.insert(exp.first);
|
||||
for (cmInstallExportGenerator const* install : *installs) {
|
||||
exportFiles.push_back(install->GetDestinationFile());
|
||||
namespaces.insert(install->GetNamespace());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return { exportFiles, exportSets, namespaces };
|
||||
return target->GetLocalGenerator()
|
||||
->GetGlobalGenerator()
|
||||
->FindInstallExportInfo(target);
|
||||
}
|
||||
|
||||
void cmExportInstallFileGenerator::ComplainAboutMissingTarget(
|
||||
@@ -301,9 +276,9 @@ void cmExportInstallFileGenerator::ComplainAboutMissingTarget(
|
||||
{
|
||||
std::ostringstream e;
|
||||
e << "install(" << this->IEGen->InstallSubcommand() << " \""
|
||||
<< this->GetExportName() << "\" ...) "
|
||||
<< "includes target \"" << depender->GetName()
|
||||
<< "\" which requires target \"" << dependee->GetName() << "\" ";
|
||||
<< this->GetExportName() << "\" ...) " << "includes target \""
|
||||
<< depender->GetName() << "\" which requires target \""
|
||||
<< dependee->GetName() << "\" ";
|
||||
if (exportInfo.Sets.empty()) {
|
||||
e << "that is not in any export set.";
|
||||
} else {
|
||||
@@ -330,9 +305,8 @@ void cmExportInstallFileGenerator::ComplainAboutDuplicateTarget(
|
||||
{
|
||||
std::ostringstream e;
|
||||
e << "install(" << this->IEGen->InstallSubcommand() << " \""
|
||||
<< this->GetExportName() << "\" ...) "
|
||||
<< "includes target \"" << targetName
|
||||
<< "\" more than once in the export set.";
|
||||
<< this->GetExportName() << "\" ...) " << "includes target \""
|
||||
<< targetName << "\" more than once in the export set.";
|
||||
this->ReportError(e.str());
|
||||
}
|
||||
|
||||
|
||||
@@ -1,247 +0,0 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file LICENSE.rst or https://cmake.org/licensing for details. */
|
||||
#include "cmExportInstallSbomGenerator.h"
|
||||
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <cmext/string_view>
|
||||
|
||||
#include "cmExportSet.h"
|
||||
#include "cmFileSetMetadata.h"
|
||||
#include "cmGeneratorExpression.h"
|
||||
#include "cmGeneratorFileSet.h"
|
||||
#include "cmGeneratorTarget.h"
|
||||
#include "cmInstallExportGenerator.h"
|
||||
#include "cmInstallFileSetGenerator.h"
|
||||
#include "cmLocalGenerator.h"
|
||||
#include "cmMakefile.h"
|
||||
#include "cmMessageType.h"
|
||||
#include "cmOutputConverter.h"
|
||||
#include "cmSbomArguments.h"
|
||||
#include "cmSbomObject.h"
|
||||
#include "cmSpdx.h"
|
||||
#include "cmStateTypes.h"
|
||||
#include "cmStringAlgorithms.h"
|
||||
#include "cmSystemTools.h"
|
||||
#include "cmTarget.h"
|
||||
#include "cmTargetExport.h"
|
||||
|
||||
cmExportInstallSbomGenerator::cmExportInstallSbomGenerator(
|
||||
cmInstallExportGenerator* iegen, cmSbomArguments args)
|
||||
: cmExportSbomGenerator(std::move(args))
|
||||
, cmExportInstallFileGenerator(iegen)
|
||||
{
|
||||
this->SetNamespace(cmStrCat(this->GetPackageName(), "::"_s));
|
||||
}
|
||||
|
||||
std::string cmExportInstallSbomGenerator::GetConfigImportFileGlob() const
|
||||
{
|
||||
std::string glob = cmStrCat(this->FileBase, "@*", this->FileExt);
|
||||
return glob;
|
||||
}
|
||||
|
||||
std::string const& cmExportInstallSbomGenerator::GetExportName() const
|
||||
{
|
||||
return this->GetPackageName();
|
||||
}
|
||||
|
||||
cm::string_view cmExportInstallSbomGenerator::GetImportPrefixWithSlash() const
|
||||
{
|
||||
return "@prefix@/"_s;
|
||||
}
|
||||
|
||||
bool cmExportInstallSbomGenerator::GenerateMainFile(std::ostream& os)
|
||||
{
|
||||
std::vector<cmTargetExport const*> allTargets;
|
||||
{
|
||||
auto visitor = [&](cmTargetExport const* te) { allTargets.push_back(te); };
|
||||
|
||||
if (!this->CollectExports(visitor)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
cmSbomDocument doc;
|
||||
doc.Graph.reserve(256);
|
||||
|
||||
cmSpdxCreationInfo const* ci =
|
||||
insert_back(doc.Graph, this->GenerateCreationInfo());
|
||||
cmSpdxDocument* project = insert_back(doc.Graph, this->GenerateSbom(ci));
|
||||
std::vector<TargetProperties> targets;
|
||||
targets.reserve(allTargets.size());
|
||||
|
||||
for (cmTargetExport const* te : allTargets) {
|
||||
cmGeneratorTarget const* gt = te->Target;
|
||||
ImportPropertyMap properties;
|
||||
if (!this->PopulateInterfaceProperties(te, properties)) {
|
||||
return false;
|
||||
}
|
||||
this->PopulateLinkLibrariesProperty(
|
||||
gt, cmGeneratorExpression::InstallInterface, properties);
|
||||
this->PopulateInterfaceLinkLibrariesProperty(
|
||||
gt, cmGeneratorExpression::InstallInterface, properties);
|
||||
|
||||
targets.push_back(TargetProperties{
|
||||
insert_back(project->RootElements,
|
||||
this->GenerateImportTarget(ci, te->Target)),
|
||||
te->Target, std::move(properties) });
|
||||
}
|
||||
|
||||
for (auto const& target : targets) {
|
||||
this->GenerateProperties(doc, project, ci, target, targets);
|
||||
}
|
||||
|
||||
this->WriteSbom(doc, os);
|
||||
return true;
|
||||
}
|
||||
|
||||
void cmExportInstallSbomGenerator::GenerateImportTargetsConfig(
|
||||
std::ostream& os, std::string const& config, std::string const& suffix)
|
||||
{
|
||||
cmSbomDocument doc;
|
||||
doc.Graph.reserve(256);
|
||||
|
||||
cmSpdxCreationInfo const* ci =
|
||||
insert_back(doc.Graph, this->GenerateCreationInfo());
|
||||
cmSpdxDocument* project = insert_back(doc.Graph, this->GenerateSbom(ci));
|
||||
|
||||
std::vector<TargetProperties> targets;
|
||||
std::string cfg = (config.empty() ? "noconfig" : config);
|
||||
|
||||
for (auto const& te : this->GetExportSet()->GetTargetExports()) {
|
||||
ImportPropertyMap properties;
|
||||
std::set<std::string> importedLocations;
|
||||
|
||||
if (this->GetExportTargetType(te.get()) !=
|
||||
cmStateEnums::INTERFACE_LIBRARY) {
|
||||
this->PopulateImportProperties(config, suffix, te.get(), properties,
|
||||
importedLocations);
|
||||
}
|
||||
this->PopulateInterfaceProperties(te.get(), properties);
|
||||
this->PopulateInterfaceLinkLibrariesProperty(
|
||||
te->Target, cmGeneratorExpression::InstallInterface, properties);
|
||||
this->PopulateLinkLibrariesProperty(
|
||||
te->Target, cmGeneratorExpression::InstallInterface, properties);
|
||||
|
||||
targets.push_back(TargetProperties{
|
||||
insert_back(project->RootElements,
|
||||
this->GenerateImportTarget(ci, te->Target)),
|
||||
te->Target, std::move(properties) });
|
||||
}
|
||||
|
||||
for (auto const& target : targets) {
|
||||
this->GenerateProperties(doc, project, ci, target, targets);
|
||||
}
|
||||
|
||||
this->WriteSbom(doc, os);
|
||||
}
|
||||
|
||||
std::string cmExportInstallSbomGenerator::GenerateImportPrefix() const
|
||||
{
|
||||
std::string expDest = this->IEGen->GetDestination();
|
||||
if (cmSystemTools::FileIsFullPath(expDest)) {
|
||||
std::string const& installPrefix =
|
||||
this->IEGen->GetLocalGenerator()->GetMakefile()->GetSafeDefinition(
|
||||
"CMAKE_INSTALL_PREFIX");
|
||||
if (cmHasPrefix(expDest, installPrefix)) {
|
||||
auto n = installPrefix.length();
|
||||
while (n < expDest.length() && expDest[n] == '/') {
|
||||
++n;
|
||||
}
|
||||
expDest = expDest.substr(n);
|
||||
} else {
|
||||
this->ReportError(
|
||||
cmStrCat("install(SBOM \"", this->GetExportName(),
|
||||
"\" ...) specifies DESTINATION \"", expDest,
|
||||
"\" which is not a subdirectory of the install prefix."));
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
if (expDest.empty()) {
|
||||
return this->GetInstallPrefix();
|
||||
}
|
||||
return cmStrCat(this->GetImportPrefixWithSlash(), expDest);
|
||||
}
|
||||
|
||||
void cmExportInstallSbomGenerator::HandleMissingTarget(
|
||||
std::string& /* link_libs */, cmGeneratorTarget const* /* depender */,
|
||||
cmGeneratorTarget* /* dependee */)
|
||||
{
|
||||
}
|
||||
|
||||
bool cmExportInstallSbomGenerator::CheckInterfaceDirs(
|
||||
std::string const& /* prepro */, cmGeneratorTarget const* /* target */,
|
||||
std::string const& /* prop */) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string cmExportInstallSbomGenerator::InstallNameDir(
|
||||
cmGeneratorTarget const* target, std::string const& config)
|
||||
{
|
||||
std::string install_name_dir;
|
||||
|
||||
cmMakefile* mf = target->Target->GetMakefile();
|
||||
if (mf->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) {
|
||||
install_name_dir =
|
||||
target->GetInstallNameDirForInstallTree(config, "@prefix@");
|
||||
}
|
||||
|
||||
return install_name_dir;
|
||||
}
|
||||
|
||||
std::string cmExportInstallSbomGenerator::GetCxxModulesDirectory() const
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
void cmExportInstallSbomGenerator::GenerateCxxModuleConfigInformation(
|
||||
std::string const&, std::ostream&) const
|
||||
{
|
||||
}
|
||||
|
||||
std::string cmExportInstallSbomGenerator::GetCxxModuleFile(
|
||||
std::string const& /* name */) const
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
cm::optional<std::string> cmExportInstallSbomGenerator::GetFileSetDirectory(
|
||||
cmGeneratorTarget* gte, cmTargetExport const* te,
|
||||
cmGeneratorFileSet const* fileSet, cm::optional<std::string> const& config)
|
||||
{
|
||||
cmInstallFileSetGenerator::DestinationContext result =
|
||||
te->FileSetGenerators.at(fileSet->GetName())
|
||||
->GetDestination(gte, config.value_or(""));
|
||||
|
||||
if (config && !result.HadContextSensitiveCondition) {
|
||||
return {};
|
||||
}
|
||||
|
||||
std::string const& type = fileSet->GetType();
|
||||
if (config && (type == cm::FileSetMetadata::CXX_MODULES)) {
|
||||
cmMakefile* mf = gte->LocalGenerator->GetMakefile();
|
||||
std::ostringstream e;
|
||||
e << "The \"" << gte->GetName() << "\" target's interface file set \""
|
||||
<< fileSet->GetName() << "\" of type \"" << type
|
||||
<< "\" contains context-sensitive base file entries which is not "
|
||||
"supported.";
|
||||
mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
|
||||
return {};
|
||||
}
|
||||
|
||||
cm::optional<std::string> dest = cmOutputConverter::EscapeForCMake(
|
||||
result.UnescapedDestination, cmOutputConverter::WrapQuotes::NoWrap);
|
||||
|
||||
if (!cmSystemTools::FileIsFullPath(result.UnescapedDestination)) {
|
||||
dest = cmStrCat("@prefix@/"_s, *dest);
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
/* 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/optional>
|
||||
#include <cm/string_view>
|
||||
|
||||
#include "cmExportInstallFileGenerator.h"
|
||||
#include "cmExportSbomGenerator.h"
|
||||
|
||||
class cmGeneratorFileSet;
|
||||
class cmGeneratorTarget;
|
||||
class cmInstallExportGenerator;
|
||||
class cmSbomArguments;
|
||||
class cmTargetExport;
|
||||
|
||||
class cmExportInstallSbomGenerator
|
||||
: public cmExportSbomGenerator
|
||||
, public cmExportInstallFileGenerator
|
||||
{
|
||||
public:
|
||||
/** Construct with the export installer that will install the
|
||||
files. */
|
||||
cmExportInstallSbomGenerator(cmInstallExportGenerator* iegen,
|
||||
cmSbomArguments arguments);
|
||||
|
||||
/** Compute the globbing expression used to load per-config import
|
||||
files from the main file. */
|
||||
std::string GetConfigImportFileGlob() const override;
|
||||
|
||||
protected:
|
||||
std::string const& GetExportName() const override;
|
||||
|
||||
cm::string_view GetImportPrefixWithSlash() const override;
|
||||
std::string GetCxxModuleFile(std::string const& name) const override;
|
||||
void GenerateCxxModuleConfigInformation(std::string const&,
|
||||
std::ostream& os) const override;
|
||||
|
||||
// Implement virtual methods from the superclass.
|
||||
bool GenerateMainFile(std::ostream& os) override;
|
||||
void GenerateImportTargetsConfig(std::ostream& os, std::string const& config,
|
||||
std::string const& suffix) override;
|
||||
|
||||
void HandleMissingTarget(std::string& /* link_libs */,
|
||||
cmGeneratorTarget const* /* depender */,
|
||||
cmGeneratorTarget* /* dependee */) override;
|
||||
|
||||
bool CheckInterfaceDirs(std::string const& /* prepro */,
|
||||
cmGeneratorTarget const* /* target */,
|
||||
std::string const& /* prop */) const override;
|
||||
|
||||
char GetConfigFileNameSeparator() const override { return '@'; }
|
||||
|
||||
std::string GenerateImportPrefix() const;
|
||||
std::string InstallNameDir(cmGeneratorTarget const* target,
|
||||
std::string const& config) override;
|
||||
|
||||
std::string GetCxxModulesDirectory() const override;
|
||||
|
||||
cm::optional<std::string> GetFileSetDirectory(
|
||||
cmGeneratorTarget* gte, cmTargetExport const* te,
|
||||
cmGeneratorFileSet const* fileSet,
|
||||
cm::optional<std::string> const& config = {});
|
||||
};
|
||||
@@ -1,86 +0,0 @@
|
||||
/* 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 <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "cmExportFileGenerator.h"
|
||||
#include "cmFindPackageStack.h"
|
||||
#include "cmGeneratorExpression.h"
|
||||
#include "cmSbomArguments.h"
|
||||
|
||||
class cmGeneratorTarget;
|
||||
struct cmSbomDocument;
|
||||
struct cmSpdxDocument;
|
||||
struct cmSpdxPackage;
|
||||
struct cmSpdxCreationInfo;
|
||||
|
||||
class cmExportSbomGenerator : virtual public cmExportFileGenerator
|
||||
{
|
||||
public:
|
||||
cmExportSbomGenerator(cmSbomArguments args);
|
||||
using cmExportFileGenerator::GenerateImportFile;
|
||||
|
||||
protected:
|
||||
using ImportPropertyMap = std::map<std::string, std::string>;
|
||||
|
||||
struct TargetProperties
|
||||
{
|
||||
cmSpdxPackage const* Package;
|
||||
cmGeneratorTarget const* Target;
|
||||
ImportPropertyMap Properties;
|
||||
};
|
||||
|
||||
void WriteSbom(cmSbomDocument& doc, std::ostream& os) const;
|
||||
|
||||
cmSpdxCreationInfo GenerateCreationInfo() const;
|
||||
cmSpdxDocument GenerateSbom(cmSpdxCreationInfo const* ci) const;
|
||||
cmSpdxPackage GenerateImportTarget(cmSpdxCreationInfo const* ci,
|
||||
cmGeneratorTarget const* target) const;
|
||||
|
||||
std::string const& GetPackageName() const { return this->PackageName; }
|
||||
|
||||
bool GenerateImportFile(std::ostream& os) override;
|
||||
bool AddPackageInformation(cmSpdxPackage& artifact, std::string const& name,
|
||||
cmPackageInformation const& package) const;
|
||||
|
||||
bool GenerateProperties(
|
||||
cmSbomDocument& doc, cmSpdxDocument* project, cmSpdxCreationInfo const* ci,
|
||||
TargetProperties const& current,
|
||||
std::vector<TargetProperties> const& allTargets) const;
|
||||
|
||||
void GenerateLinkProperties(
|
||||
cmSbomDocument& doc, cmSpdxDocument* project, cmSpdxCreationInfo const* ci,
|
||||
std::string const& libraries, TargetProperties const& current,
|
||||
std::vector<TargetProperties> const& allTargets) const;
|
||||
|
||||
bool NoteLinkedTarget(cmGeneratorTarget const* target,
|
||||
std::string const& linkedName,
|
||||
cmGeneratorTarget const* linkedTarget) override;
|
||||
|
||||
bool PopulateLinkLibrariesProperty(cmGeneratorTarget const* target,
|
||||
cmGeneratorExpression::PreprocessContext,
|
||||
ImportPropertyMap& properties);
|
||||
|
||||
private:
|
||||
struct LinkInfo
|
||||
{
|
||||
std::string Package;
|
||||
std::string Component;
|
||||
};
|
||||
|
||||
std::string const PackageName;
|
||||
std::string const PackageVersion;
|
||||
std::string const PackageDescription;
|
||||
std::string const PackageWebsite;
|
||||
std::string const PackageLicense;
|
||||
std::string const PackageUrl;
|
||||
cmSbomArguments::SbomFormat const PackageFormat;
|
||||
std::map<std::string, LinkInfo> LinkTargets;
|
||||
std::map<std::string, cmPackageInformation> Requirements;
|
||||
};
|
||||
+141
-13
@@ -27,6 +27,7 @@
|
||||
#include "cmAlgorithms.h"
|
||||
#include "cmArgumentParserTypes.h"
|
||||
#include "cmBuildArgs.h"
|
||||
#include "cmBuildSbomGenerator.h"
|
||||
#include "cmCMakePath.h"
|
||||
#include "cmCPackPropertiesGenerator.h"
|
||||
#include "cmComputeTargetDepends.h"
|
||||
@@ -42,9 +43,10 @@
|
||||
#include "cmGeneratedFileStream.h"
|
||||
#include "cmGeneratorExpression.h"
|
||||
#include "cmGeneratorTarget.h"
|
||||
#include "cmInstallExportGenerator.h"
|
||||
#include "cmInstallGenerator.h"
|
||||
#include "cmInstallRuntimeDependencySet.h"
|
||||
#include "cmInstallSbomExportGenerator.h"
|
||||
#include "cmInstallSbomGenerator.h"
|
||||
#include "cmLinkLineComputer.h"
|
||||
#include "cmList.h"
|
||||
#include "cmListFileCache.h"
|
||||
@@ -63,6 +65,7 @@
|
||||
#include "cmStringAlgorithms.h"
|
||||
#include "cmSyntheticTargetCache.h"
|
||||
#include "cmSystemTools.h"
|
||||
#include "cmTargetExport.h"
|
||||
#include "cmValue.h"
|
||||
#include "cmVersion.h"
|
||||
#include "cmWorkingDirectory.h"
|
||||
@@ -312,6 +315,77 @@ void cmGlobalGenerator::AddBuildExportSet(cmExportBuildFileGenerator* gen)
|
||||
this->BuildExportSets[gen->GetMainExportFileName()] = gen;
|
||||
}
|
||||
|
||||
cmExportFileGenerator::ExportInfo cmGlobalGenerator::FindBuildExportInfo(
|
||||
cmGeneratorTarget const* target) const
|
||||
{
|
||||
cmExportFileGenerator::ExportInfo info;
|
||||
for (auto const& exp : this->BuildExportSets) {
|
||||
if (auto rec = exp.second->FindRecordForTarget(target)) {
|
||||
info.Files.push_back(exp.first);
|
||||
info.Sets.insert(rec->Name.empty() ? exp.first : rec->Name);
|
||||
info.Namespaces.insert(rec->Namespace);
|
||||
}
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
cmExportFileGenerator::ExportInfo cmGlobalGenerator::FindInstallExportInfo(
|
||||
cmGeneratorTarget const* target) const
|
||||
{
|
||||
cmExportFileGenerator::ExportInfo info;
|
||||
auto const& name = target->GetName();
|
||||
for (auto const& exp : this->ExportSets) {
|
||||
auto const& exportSet = exp.second;
|
||||
auto const& targets = exportSet.GetTargetExports();
|
||||
bool const contains =
|
||||
std::any_of(targets.begin(), targets.end(),
|
||||
[&name](std::unique_ptr<cmTargetExport> const& te) {
|
||||
return te->TargetName == name;
|
||||
});
|
||||
if (!contains) {
|
||||
continue;
|
||||
}
|
||||
auto const* installs = exportSet.GetInstallations();
|
||||
if (!installs || installs->empty()) {
|
||||
continue;
|
||||
}
|
||||
info.Sets.insert(exp.first);
|
||||
for (auto const* install : *installs) {
|
||||
info.Files.push_back(install->GetDestinationFile());
|
||||
info.Namespaces.insert(install->GetNamespace());
|
||||
}
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
#ifndef CMAKE_BOOTSTRAP
|
||||
cmSbomBuilder::SbomInfo cmGlobalGenerator::FindBuildSbomInfo(
|
||||
cmGeneratorTarget const* target) const
|
||||
{
|
||||
cmSbomBuilder::SbomInfo info;
|
||||
for (cmBuildSbomGenerator const* g : this->BuildSbomGenerators) {
|
||||
if (g->CoversTarget(target)) {
|
||||
info.Packages.push_back(g->GetPackageName());
|
||||
}
|
||||
}
|
||||
std::sort(info.Packages.begin(), info.Packages.end());
|
||||
return info;
|
||||
}
|
||||
|
||||
cmSbomBuilder::SbomInfo cmGlobalGenerator::FindInstallSbomInfo(
|
||||
cmGeneratorTarget const* target) const
|
||||
{
|
||||
cmSbomBuilder::SbomInfo info;
|
||||
for (cmInstallSbomGenerator const* g : this->InstallSbomGenerators) {
|
||||
if (g->CoversTarget(target)) {
|
||||
info.Packages.push_back(g->GetPackageName());
|
||||
}
|
||||
}
|
||||
std::sort(info.Packages.begin(), info.Packages.end());
|
||||
return info;
|
||||
}
|
||||
#endif
|
||||
|
||||
void cmGlobalGenerator::AddBuildExportExportSet(
|
||||
cmExportBuildFileGenerator* gen)
|
||||
{
|
||||
@@ -319,6 +393,17 @@ void cmGlobalGenerator::AddBuildExportExportSet(
|
||||
this->AddBuildExportSet(gen);
|
||||
}
|
||||
|
||||
void cmGlobalGenerator::AddBuildSbomGenerator(cmBuildSbomGenerator* gen)
|
||||
{
|
||||
this->BuildSbomGenerators.push_back(gen);
|
||||
}
|
||||
|
||||
void cmGlobalGenerator::AddInstallSbomGenerator(
|
||||
cmInstallSbomGenerator const* gen)
|
||||
{
|
||||
this->InstallSbomGenerators.push_back(gen);
|
||||
}
|
||||
|
||||
void cmGlobalGenerator::ForceLinkerLanguages()
|
||||
{
|
||||
}
|
||||
@@ -413,6 +498,24 @@ bool cmGlobalGenerator::IsExportedTargetsFile(
|
||||
return !cm::contains(this->BuildExportExportSets, filename);
|
||||
}
|
||||
|
||||
bool cmGlobalGenerator::IsBuildSbomFile(std::string const& filepath) const
|
||||
{
|
||||
return std::any_of(this->BuildSbomGenerators.begin(),
|
||||
this->BuildSbomGenerators.end(),
|
||||
[&filepath](cmBuildSbomGenerator const* g) {
|
||||
return g->GetOutputFile() == filepath;
|
||||
});
|
||||
}
|
||||
|
||||
bool cmGlobalGenerator::IsInstallSbomFile(std::string const& filepath) const
|
||||
{
|
||||
return std::any_of(this->InstallSbomGenerators.begin(),
|
||||
this->InstallSbomGenerators.end(),
|
||||
[&filepath](cmInstallSbomGenerator const* g) {
|
||||
return g->GetInstallFile() == filepath;
|
||||
});
|
||||
}
|
||||
|
||||
// Find the make program for the generator, required for try compiles
|
||||
bool cmGlobalGenerator::FindMakeProgram(cmMakefile* mf)
|
||||
{
|
||||
@@ -1440,11 +1543,15 @@ bool cmGlobalGenerator::CheckALLOW_DUPLICATE_CUSTOM_TARGETS() const
|
||||
void cmGlobalGenerator::ComputeBuildFileGenerators()
|
||||
{
|
||||
for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i) {
|
||||
std::vector<std::unique_ptr<cmExportBuildFileGenerator>> const& gens =
|
||||
this->Makefiles[i]->GetExportBuildFileGenerators();
|
||||
for (std::unique_ptr<cmExportBuildFileGenerator> const& g : gens) {
|
||||
g->Compute(this->LocalGenerators[i].get());
|
||||
cmLocalGenerator* lg = this->LocalGenerators[i].get();
|
||||
for (auto const& g : this->Makefiles[i]->GetExportBuildFileGenerators()) {
|
||||
g->Compute(lg);
|
||||
}
|
||||
#ifndef CMAKE_BOOTSTRAP
|
||||
for (auto const& g : this->Makefiles[i]->GetBuildSbomGenerators()) {
|
||||
g->Compute(lg);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1621,10 +1728,10 @@ bool cmGlobalGenerator::Compute()
|
||||
bool sbomEnabled = cmExperimental::HasSupportEnabled(
|
||||
*this->Makefiles[0], cmExperimental::Feature::GenerateSbom);
|
||||
|
||||
// Automatically generate SBOM files if enabled.
|
||||
// Automatically generate one SBOM per export set not already tied to an
|
||||
// explicit install(SBOM) call.
|
||||
cmValue sbomFormat = this->GetGlobalSetting("CMAKE_INSTALL_SBOM_FORMATS");
|
||||
if (sbomFormat.IsSet() && !this->Makefiles[0]->ExplicitlyGeneratesSbom() &&
|
||||
sbomEnabled && !isTryCompile) {
|
||||
if (sbomFormat.IsSet() && sbomEnabled && !isTryCompile) {
|
||||
std::string location =
|
||||
this->Makefiles[0]->GetSafeDefinition("CMAKE_INSTALL_LIBDIR");
|
||||
if (location.empty()) {
|
||||
@@ -1632,16 +1739,26 @@ bool cmGlobalGenerator::Compute()
|
||||
}
|
||||
|
||||
std::string projectName = this->LocalGenerators[0]->GetProjectName();
|
||||
cmSbomArguments sbomDefaultArgs;
|
||||
sbomDefaultArgs.ProjectName = projectName;
|
||||
for (auto& exportSet : this->ExportSets) {
|
||||
bool isCovered =
|
||||
std::any_of(this->InstallSbomGenerators.cbegin(),
|
||||
this->InstallSbomGenerators.cend(),
|
||||
[&exportSet](cmInstallSbomGenerator const* g) {
|
||||
return g->CoversExportSet(&exportSet.second);
|
||||
});
|
||||
if (isCovered) {
|
||||
continue;
|
||||
}
|
||||
cmSbomArguments sbomDefaultArgs;
|
||||
sbomDefaultArgs.ProjectName = projectName;
|
||||
sbomDefaultArgs.PackageName = exportSet.first;
|
||||
std::string dest = cmStrCat(location, "/sbom/", projectName);
|
||||
this->Makefiles[0]->AddInstallGenerator(
|
||||
cm::make_unique<cmInstallSbomExportGenerator>(
|
||||
&exportSet.second, dest, "", std::vector<std::string>(), "",
|
||||
cm::make_unique<cmInstallSbomGenerator>(
|
||||
std::vector<cmExportSet*>{ &exportSet.second }, dest, "",
|
||||
std::vector<std::string>(), "",
|
||||
cmInstallGenerator::SelectMessageLevel(this->Makefiles[0].get()),
|
||||
false, std::move(sbomDefaultArgs), "",
|
||||
false, std::move(sbomDefaultArgs),
|
||||
cmInstallGenerator::CaptureContext(this->Makefiles[0].get())));
|
||||
}
|
||||
}
|
||||
@@ -1752,6 +1869,17 @@ void cmGlobalGenerator::Generate()
|
||||
return;
|
||||
}
|
||||
}
|
||||
#ifndef CMAKE_BOOTSTRAP
|
||||
for (auto& sbomGen : this->BuildSbomGenerators) {
|
||||
if (!sbomGen->GenerateForBuild()) {
|
||||
if (!cmSystemTools::GetErrorOccurredFlag()) {
|
||||
this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR,
|
||||
"Could not write SBOM file.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// Update rule hashes.
|
||||
this->CheckRuleHashes();
|
||||
|
||||
|
||||
@@ -24,8 +24,10 @@
|
||||
#include "cmBuildOptions.h"
|
||||
#include "cmCustomCommandLines.h"
|
||||
#include "cmDuration.h"
|
||||
#include "cmExportFileGenerator.h"
|
||||
#include "cmExportSet.h"
|
||||
#include "cmLocalGenerator.h"
|
||||
#include "cmSbomBuilder.h"
|
||||
#include "cmStateSnapshot.h"
|
||||
#include "cmStateTypes.h"
|
||||
#include "cmStringAlgorithms.h"
|
||||
@@ -50,6 +52,8 @@ class cmBuildArgs;
|
||||
class cmDirectoryId;
|
||||
class cmExportBuildFileGenerator;
|
||||
class cmExternalMakefileProjectGenerator;
|
||||
class cmBuildSbomGenerator;
|
||||
class cmInstallSbomGenerator;
|
||||
class cmGeneratorTarget;
|
||||
class cmInstallRuntimeDependencySet;
|
||||
class cmLinkLineComputer;
|
||||
@@ -631,9 +635,54 @@ public:
|
||||
{
|
||||
return this->BuildExportSets;
|
||||
}
|
||||
/** Scan all build-tree exports in the project and report which of them
|
||||
* reference `target`. Used both by cmExportBuildFileGenerator (to resolve
|
||||
* out-of-export link references) and by cmSbomBuilder (to record which
|
||||
* export sets a target appears in for SBOM dependency tracking). */
|
||||
cmExportFileGenerator::ExportInfo FindBuildExportInfo(
|
||||
cmGeneratorTarget const* target) const;
|
||||
|
||||
/** Same as FindBuildExportInfo, but searches install-tree export sets
|
||||
* (those registered via install(EXPORT ...)). */
|
||||
cmExportFileGenerator::ExportInfo FindInstallExportInfo(
|
||||
cmGeneratorTarget const* target) const;
|
||||
|
||||
/** Scan all build-tree SBOMs and report which of them cover `target`. */
|
||||
cmSbomBuilder::SbomInfo FindBuildSbomInfo(
|
||||
cmGeneratorTarget const* target) const;
|
||||
|
||||
/** Same as FindBuildSbomInfo, but searches install-tree SBOMs. */
|
||||
cmSbomBuilder::SbomInfo FindInstallSbomInfo(
|
||||
cmGeneratorTarget const* target) const;
|
||||
void AddBuildExportSet(cmExportBuildFileGenerator* gen);
|
||||
void AddBuildExportExportSet(cmExportBuildFileGenerator* gen);
|
||||
void AddBuildSbomGenerator(cmBuildSbomGenerator* gen);
|
||||
std::vector<cmBuildSbomGenerator*> const& GetBuildSbomGenerators() const
|
||||
{
|
||||
return this->BuildSbomGenerators;
|
||||
}
|
||||
|
||||
// Project-wide registry of install(SBOM) generators.
|
||||
void AddInstallSbomGenerator(cmInstallSbomGenerator const* gen);
|
||||
std::vector<cmInstallSbomGenerator const*> const& GetInstallSbomGenerators()
|
||||
const
|
||||
{
|
||||
return this->InstallSbomGenerators;
|
||||
}
|
||||
|
||||
bool IsExportedTargetsFile(std::string const& filename) const;
|
||||
|
||||
/** True if any registered cmBuildSbomGenerator already targets this
|
||||
* output file path. Used to diagnose duplicate `export(SBOM ...)`
|
||||
* calls that would otherwise silently clobber each other's output. */
|
||||
bool IsBuildSbomFile(std::string const& filepath) const;
|
||||
|
||||
/** True if any registered cmInstallSbomGenerator already targets this
|
||||
* install file path (DESTINATION + filename). Used to diagnose
|
||||
* duplicate `install(SBOM ...)` calls that would otherwise silently
|
||||
* clobber each other at install time. */
|
||||
bool IsInstallSbomFile(std::string const& filepath) const;
|
||||
|
||||
cmExportBuildFileGenerator* GetExportedTargetsFile(
|
||||
std::string const& filename) const;
|
||||
void AddCMP0068WarnTarget(std::string const& target);
|
||||
@@ -820,6 +869,8 @@ protected:
|
||||
cmExportSetMap ExportSets;
|
||||
std::map<std::string, cmExportBuildFileGenerator*> BuildExportSets;
|
||||
std::map<std::string, cmExportBuildFileGenerator*> BuildExportExportSets;
|
||||
std::vector<cmBuildSbomGenerator*> BuildSbomGenerators;
|
||||
std::vector<cmInstallSbomGenerator const*> InstallSbomGenerators;
|
||||
|
||||
std::map<std::string, std::string> AliasTargets;
|
||||
|
||||
|
||||
+30
-19
@@ -41,7 +41,7 @@
|
||||
#include "cmInstallPackageInfoExportGenerator.h"
|
||||
#include "cmInstallRuntimeDependencySet.h"
|
||||
#include "cmInstallRuntimeDependencySetGenerator.h"
|
||||
#include "cmInstallSbomExportGenerator.h"
|
||||
#include "cmInstallSbomGenerator.h"
|
||||
#include "cmInstallScriptGenerator.h"
|
||||
#include "cmInstallTargetGenerator.h"
|
||||
#include "cmList.h"
|
||||
@@ -2513,16 +2513,13 @@ bool HandleSbomMode(std::vector<std::string> const& args,
|
||||
cmInstallCommandArguments ica(helper.DefaultComponentName, *helper.Makefile);
|
||||
|
||||
cmSbomArguments arguments;
|
||||
ArgumentParser::NonEmpty<std::string> exportName;
|
||||
ArgumentParser::NonEmpty<std::string> cxxModulesDirectory;
|
||||
ArgumentParser::NonEmpty<std::vector<std::string>> exportNames;
|
||||
|
||||
arguments.Bind(ica);
|
||||
ica.Bind("EXPORT"_s, exportName);
|
||||
ica.Bind("EXPORTS"_s, exportNames);
|
||||
// ica.Bind("CXX_MODULES_DIRECTORY"_s, cxxModulesDirectory); TODO?
|
||||
|
||||
std::vector<std::string> unknownArgs;
|
||||
ica.Parse(args, &unknownArgs);
|
||||
|
||||
ArgumentParser::ParseResult result = ica.Parse(args, &unknownArgs);
|
||||
if (!result.Check(args[0], &unknownArgs, status)) {
|
||||
return false;
|
||||
@@ -2538,8 +2535,8 @@ bool HandleSbomMode(std::vector<std::string> const& args,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (exportName.empty()) {
|
||||
status.SetError(cmStrCat(args[0], " missing EXPORT."));
|
||||
if (exportNames.empty()) {
|
||||
status.SetError(cmStrCat(args[0], " missing EXPORTS."));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -2558,25 +2555,39 @@ bool HandleSbomMode(std::vector<std::string> const& args,
|
||||
}
|
||||
}
|
||||
|
||||
cmExportSet& exportSet =
|
||||
helper.Makefile->GetGlobalGenerator()->GetExportSets()[exportName];
|
||||
cmGlobalGenerator* gg = helper.Makefile->GetGlobalGenerator();
|
||||
|
||||
std::string const fpath =
|
||||
cmStrCat(dest, '/', arguments.GetPackageFileName());
|
||||
if (gg->IsInstallSbomFile(fpath)) {
|
||||
status.SetError(cmStrCat("SBOM command already specified for the file "_s,
|
||||
cmSystemTools::GetFilenameNameView(fpath), '.'));
|
||||
return false;
|
||||
}
|
||||
|
||||
cmExportSetMap& allExportSets = gg->GetExportSets();
|
||||
std::vector<cmExportSet*> sets;
|
||||
sets.reserve(exportNames.size());
|
||||
for (std::string const& name : exportNames) {
|
||||
sets.push_back(&allExportSets[name]);
|
||||
}
|
||||
|
||||
cmInstallGenerator::MessageLevel message =
|
||||
cmInstallGenerator::SelectMessageLevel(helper.Makefile);
|
||||
|
||||
// Tell the global generator about any installation component names
|
||||
// specified
|
||||
// specified.
|
||||
helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
|
||||
ica.GetComponent());
|
||||
helper.Makefile->SetExplicitlyGeneratesSbom(true);
|
||||
|
||||
// Create the export install generator.
|
||||
helper.Makefile->AddInstallGenerator(
|
||||
cm::make_unique<cmInstallSbomExportGenerator>(
|
||||
&exportSet, dest, ica.GetPermissions(), ica.GetConfigurations(),
|
||||
ica.GetComponent(), message, ica.GetExcludeFromAll(),
|
||||
std::move(arguments), std::move(cxxModulesDirectory),
|
||||
helper.CaptureContext()));
|
||||
// Create the SBOM install generator.
|
||||
auto sbomGen = cm::make_unique<cmInstallSbomGenerator>(
|
||||
std::move(sets), dest, ica.GetPermissions(), ica.GetConfigurations(),
|
||||
ica.GetComponent(), message, ica.GetExcludeFromAll(), std::move(arguments),
|
||||
helper.CaptureContext());
|
||||
cmInstallSbomGenerator const* rawPtr = sbomGen.get();
|
||||
helper.Makefile->AddInstallGenerator(std::move(sbomGen));
|
||||
helper.Makefile->GetGlobalGenerator()->AddInstallSbomGenerator(rawPtr);
|
||||
|
||||
return true;
|
||||
#else
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file LICENSE.rst or https://cmake.org/licensing for details. */
|
||||
#include "cmInstallSbomBuilder.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "cmGeneratorExpression.h"
|
||||
#include "cmGeneratorTarget.h"
|
||||
#include "cmGlobalGenerator.h"
|
||||
#include "cmLocalGenerator.h"
|
||||
#include "cmSbomArguments.h"
|
||||
|
||||
cmInstallSbomBuilder::cmInstallSbomBuilder(
|
||||
cmSbomArguments args, std::vector<cmExportSet*> exportSets,
|
||||
cmLocalGenerator* lg)
|
||||
: cmSbomBuilder(std::move(args), std::move(exportSets), lg)
|
||||
{
|
||||
}
|
||||
|
||||
bool cmInstallSbomBuilder::Generate(std::ostream& os)
|
||||
{
|
||||
if (!this->LocalGenerator) {
|
||||
return false;
|
||||
}
|
||||
return this->GenerateForTargets(os, cmGeneratorExpression::InstallInterface);
|
||||
}
|
||||
|
||||
cmExportFileGenerator::ExportInfo cmInstallSbomBuilder::FindExportInfoFor(
|
||||
cmGeneratorTarget const* target) const
|
||||
{
|
||||
return target->GetLocalGenerator()
|
||||
->GetGlobalGenerator()
|
||||
->FindInstallExportInfo(target);
|
||||
}
|
||||
|
||||
cmSbomBuilder::SbomInfo cmInstallSbomBuilder::FindSbomInfoFor(
|
||||
cmGeneratorTarget const* target) const
|
||||
{
|
||||
return target->GetLocalGenerator()
|
||||
->GetGlobalGenerator()
|
||||
->FindInstallSbomInfo(target);
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/* 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 <vector>
|
||||
|
||||
#include "cmExportFileGenerator.h"
|
||||
#include "cmSbomBuilder.h"
|
||||
|
||||
class cmExportSet;
|
||||
class cmLocalGenerator;
|
||||
class cmSbomArguments;
|
||||
|
||||
/** Install-tree SBOM (`install(SBOM ...)`). Covers the targets in the
|
||||
* associated export sets. */
|
||||
class cmInstallSbomBuilder final : public cmSbomBuilder
|
||||
{
|
||||
public:
|
||||
cmInstallSbomBuilder(cmSbomArguments args,
|
||||
std::vector<cmExportSet*> exportSets,
|
||||
cmLocalGenerator* lg = nullptr);
|
||||
|
||||
bool Generate(std::ostream& os) override;
|
||||
|
||||
protected:
|
||||
cmExportFileGenerator::ExportInfo FindExportInfoFor(
|
||||
cmGeneratorTarget const* target) const override;
|
||||
SbomInfo FindSbomInfoFor(cmGeneratorTarget const* target) const override;
|
||||
};
|
||||
@@ -1,30 +0,0 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file LICENSE.rst or https://cmake.org/licensing for details. */
|
||||
#include "cmInstallSbomExportGenerator.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include <cm/memory>
|
||||
|
||||
#include "cmDiagnosticContext.h"
|
||||
#include "cmExportInstallFileGenerator.h"
|
||||
#include "cmExportInstallSbomGenerator.h"
|
||||
#include "cmSbomArguments.h"
|
||||
|
||||
class cmExportSet;
|
||||
|
||||
cmInstallSbomExportGenerator::cmInstallSbomExportGenerator(
|
||||
cmExportSet* exportSet, std::string destination, std::string filePermissions,
|
||||
std::vector<std::string> const& configurations, std::string component,
|
||||
MessageLevel message, bool excludeFromAll, cmSbomArguments args,
|
||||
std::string cxxModulesDirectory, cmDiagnosticContext context)
|
||||
: cmInstallExportGenerator(
|
||||
exportSet, std::move(destination), std::move(filePermissions),
|
||||
configurations, std::move(component), message, excludeFromAll,
|
||||
args.GetPackageFileName(), args.GetNamespace(),
|
||||
std::move(cxxModulesDirectory), std::move(context))
|
||||
{
|
||||
this->EFGen = cm::make_unique<cmExportInstallSbomGenerator>(this, args);
|
||||
}
|
||||
|
||||
cmInstallSbomExportGenerator::~cmInstallSbomExportGenerator() = default;
|
||||
@@ -1,31 +0,0 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file LICENSE.rst or https://cmake.org/licensing for details. */
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "cmInstallExportGenerator.h"
|
||||
|
||||
class cmDiagnosticContext;
|
||||
class cmExportSet;
|
||||
class cmSbomArguments;
|
||||
|
||||
class cmInstallSbomExportGenerator final : public cmInstallExportGenerator
|
||||
{
|
||||
public:
|
||||
cmInstallSbomExportGenerator(cmExportSet* exportSet, std::string destination,
|
||||
std::string filePermissions,
|
||||
std::vector<std::string> const& configurations,
|
||||
std::string component, MessageLevel message,
|
||||
bool excludeFromAll, cmSbomArguments arguments,
|
||||
std::string cxxModulesDirectory,
|
||||
cmDiagnosticContext context);
|
||||
cmInstallSbomExportGenerator(cmInstallSbomExportGenerator const&) = delete;
|
||||
~cmInstallSbomExportGenerator() override;
|
||||
|
||||
cmInstallSbomExportGenerator& operator=(
|
||||
cmInstallSbomExportGenerator const&) = delete;
|
||||
|
||||
char const* InstallSubcommand() const override { return "SBOM"; }
|
||||
};
|
||||
@@ -0,0 +1,88 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file LICENSE.rst or https://cmake.org/licensing for details. */
|
||||
#include "cmInstallSbomGenerator.h"
|
||||
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <cm/memory>
|
||||
|
||||
#include "cmCryptoHash.h"
|
||||
#include "cmDiagnosticContext.h"
|
||||
#include "cmGeneratedFileStream.h"
|
||||
#include "cmInstallSbomBuilder.h"
|
||||
#include "cmInstallType.h"
|
||||
#include "cmLocalGenerator.h"
|
||||
#include "cmSbomArguments.h"
|
||||
#include "cmStringAlgorithms.h"
|
||||
#include "cmSystemTools.h"
|
||||
|
||||
cmInstallSbomGenerator::cmInstallSbomGenerator(
|
||||
std::vector<cmExportSet*> exportSets, std::string destination,
|
||||
std::string filePermissions, std::vector<std::string> const& configurations,
|
||||
std::string component, MessageLevel message, bool excludeFromAll,
|
||||
cmSbomArguments args, cmDiagnosticContext context)
|
||||
: cmInstallGenerator(std::move(destination), configurations,
|
||||
std::move(component), message, excludeFromAll, false,
|
||||
std::move(context))
|
||||
, FilePermissions(std::move(filePermissions))
|
||||
, SbomFileName(args.GetPackageFileName())
|
||||
, SbomFilePath(cmStrCat(this->Destination, '/', this->SbomFileName))
|
||||
, Builder(cm::make_unique<cmInstallSbomBuilder>(std::move(args),
|
||||
std::move(exportSets)))
|
||||
{
|
||||
}
|
||||
|
||||
cmInstallSbomGenerator::~cmInstallSbomGenerator() = default;
|
||||
|
||||
bool cmInstallSbomGenerator::Compute(cmLocalGenerator* lg)
|
||||
{
|
||||
this->LocalGenerator = lg;
|
||||
this->Builder->Compute(lg);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cmInstallSbomGenerator::CoversTarget(
|
||||
cmGeneratorTarget const* target) const
|
||||
{
|
||||
return this->Builder->CoversTarget(target);
|
||||
}
|
||||
|
||||
std::string const& cmInstallSbomGenerator::GetPackageName() const
|
||||
{
|
||||
return this->Builder->GetPackageName();
|
||||
}
|
||||
|
||||
bool cmInstallSbomGenerator::CoversExportSet(cmExportSet const* set) const
|
||||
{
|
||||
return this->Builder->CoversExportSet(set);
|
||||
}
|
||||
|
||||
void cmInstallSbomGenerator::GenerateScript(std::ostream& os)
|
||||
{
|
||||
// Choose a temporary directory in the build tree to hold the generated SBOM.
|
||||
cmCryptoHash hasher(cmCryptoHash::AlgoMD5);
|
||||
std::string const tempDir =
|
||||
cmStrCat(this->LocalGenerator->GetCurrentBinaryDirectory(),
|
||||
"/CMakeFiles/Sbom/", hasher.HashString(this->Destination));
|
||||
|
||||
cmSystemTools::MakeDirectory(tempDir);
|
||||
|
||||
this->TempSbomFilePath = cmStrCat(tempDir, '/', this->SbomFileName);
|
||||
|
||||
// Generate the SBOM file now, at cmake generate time.
|
||||
cmGeneratedFileStream sbomStream(this->TempSbomFilePath);
|
||||
this->Builder->Generate(sbomStream);
|
||||
|
||||
// Emit the cmake_install.cmake script to copy the file at install time.
|
||||
this->cmInstallGenerator::GenerateScript(os);
|
||||
}
|
||||
|
||||
void cmInstallSbomGenerator::GenerateScriptActions(std::ostream& os,
|
||||
Indent indent)
|
||||
{
|
||||
std::vector<std::string> files{ this->TempSbomFilePath };
|
||||
this->AddInstallRule(os, this->Destination, cmInstallType_FILES, files,
|
||||
false, this->FilePermissions.c_str(), nullptr, nullptr,
|
||||
nullptr, indent);
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/* 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 <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "cmInstallGenerator.h"
|
||||
|
||||
class cmDiagnosticContext;
|
||||
class cmExportSet;
|
||||
class cmGeneratorTarget;
|
||||
class cmInstallSbomBuilder;
|
||||
class cmLocalGenerator;
|
||||
class cmSbomArguments;
|
||||
|
||||
/** \class cmInstallSbomGenerator
|
||||
* \brief Generate installation rules for SBOM files.
|
||||
*
|
||||
* Thin cmInstallGenerator subclass that owns a cmInstallSbomBuilder.
|
||||
* At generate time it writes the SBOM into a temporary file in the build tree;
|
||||
* the cmake_install.cmake script then copies that file to the install
|
||||
* destination.
|
||||
*/
|
||||
class cmInstallSbomGenerator : public cmInstallGenerator
|
||||
{
|
||||
public:
|
||||
cmInstallSbomGenerator(std::vector<cmExportSet*> exportSets,
|
||||
std::string destination, std::string filePermissions,
|
||||
std::vector<std::string> const& configurations,
|
||||
std::string component, MessageLevel message,
|
||||
bool excludeFromAll, cmSbomArguments args,
|
||||
cmDiagnosticContext context);
|
||||
cmInstallSbomGenerator(cmInstallSbomGenerator const&) = delete;
|
||||
~cmInstallSbomGenerator() override;
|
||||
|
||||
cmInstallSbomGenerator& operator=(cmInstallSbomGenerator const&) = delete;
|
||||
|
||||
bool Compute(cmLocalGenerator* lg) override;
|
||||
|
||||
std::string const& GetInstallFile() const { return this->SbomFilePath; }
|
||||
|
||||
/** True if this SBOM directly describes `target`. Used by peer SBOMs to
|
||||
* attribute cross-references when install(export) provenance is absent. */
|
||||
bool CoversTarget(cmGeneratorTarget const* target) const;
|
||||
std::string const& GetPackageName() const;
|
||||
|
||||
/** True if `set` is one of the export sets this SBOM was built from.
|
||||
* Used by the autogen path to skip sets already explicitly tied to an
|
||||
* install(SBOM). */
|
||||
bool CoversExportSet(cmExportSet const* set) const;
|
||||
|
||||
protected:
|
||||
void GenerateScript(std::ostream& os) override;
|
||||
void GenerateScriptActions(std::ostream& os, Indent indent) override;
|
||||
|
||||
private:
|
||||
std::string TempSbomFilePath;
|
||||
std::string const FilePermissions;
|
||||
std::string const SbomFileName;
|
||||
std::string const SbomFilePath;
|
||||
cmLocalGenerator* LocalGenerator = nullptr;
|
||||
std::unique_ptr<cmInstallSbomBuilder> Builder;
|
||||
};
|
||||
+17
-10
@@ -30,6 +30,9 @@
|
||||
#include "cmsys/RegularExpression.hxx"
|
||||
#include "cmsys/String.h"
|
||||
|
||||
#ifndef CMAKE_BOOTSTRAP
|
||||
# include "cmBuildSbomGenerator.h"
|
||||
#endif
|
||||
#include "cmCustomCommand.h"
|
||||
#include "cmCustomCommandLines.h"
|
||||
#include "cmCustomCommandTypes.h"
|
||||
@@ -1018,6 +1021,20 @@ void cmMakefile::AddExportBuildFileGenerator(
|
||||
this->ExportBuildFileGenerators.emplace_back(std::move(gen));
|
||||
}
|
||||
|
||||
#ifndef CMAKE_BOOTSTRAP
|
||||
std::vector<std::unique_ptr<cmBuildSbomGenerator>> const&
|
||||
cmMakefile::GetBuildSbomGenerators() const
|
||||
{
|
||||
return this->BuildSbomGenerators;
|
||||
}
|
||||
|
||||
void cmMakefile::AddBuildSbomGenerator(
|
||||
std::unique_ptr<cmBuildSbomGenerator> gen)
|
||||
{
|
||||
this->BuildSbomGenerators.emplace_back(std::move(gen));
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
struct file_not_persistent
|
||||
{
|
||||
@@ -1482,16 +1499,6 @@ void cmMakefile::AddTestGenerator(std::unique_ptr<cmTestGenerator> g)
|
||||
}
|
||||
}
|
||||
|
||||
bool cmMakefile::ExplicitlyGeneratesSbom() const
|
||||
{
|
||||
return this->ExplicitSbomGenerator;
|
||||
}
|
||||
|
||||
void cmMakefile::SetExplicitlyGeneratesSbom(bool status)
|
||||
{
|
||||
this->ExplicitSbomGenerator = status;
|
||||
}
|
||||
|
||||
void cmMakefile::PushFunctionScope(std::string const& fileName,
|
||||
cmPolicies::PolicyMap const& pm,
|
||||
cmDiagnostics::DiagnosticMap dm)
|
||||
|
||||
+11
-4
@@ -53,6 +53,7 @@ class cmCompiledGeneratorExpression;
|
||||
class cmCustomCommandLines;
|
||||
class cmExecutionStatus;
|
||||
class cmExpandedCommandArgument;
|
||||
class cmBuildSbomGenerator;
|
||||
class cmExportBuildFileGenerator;
|
||||
class cmGeneratorExpressionEvaluationFile;
|
||||
class cmGlobalGenerator;
|
||||
@@ -901,9 +902,6 @@ public:
|
||||
//! Initialize a makefile from its parent
|
||||
void InitializeFromParent(cmMakefile* parent);
|
||||
|
||||
bool ExplicitlyGeneratesSbom() const;
|
||||
void SetExplicitlyGeneratesSbom(bool status = true);
|
||||
|
||||
void AddInstallGenerator(std::unique_ptr<cmInstallGenerator> g);
|
||||
|
||||
std::vector<std::unique_ptr<cmInstallGenerator>>& GetInstallGenerators()
|
||||
@@ -1113,6 +1111,12 @@ public:
|
||||
void AddExportBuildFileGenerator(
|
||||
std::unique_ptr<cmExportBuildFileGenerator> gen);
|
||||
|
||||
#ifndef CMAKE_BOOTSTRAP
|
||||
std::vector<std::unique_ptr<cmBuildSbomGenerator>> const&
|
||||
GetBuildSbomGenerators() const;
|
||||
void AddBuildSbomGenerator(std::unique_ptr<cmBuildSbomGenerator> gen);
|
||||
#endif
|
||||
|
||||
// Maintain a stack of package roots to allow nested PACKAGE_ROOT_PATH
|
||||
// searches
|
||||
std::deque<std::vector<std::string>> FindPackageRootPathStack;
|
||||
@@ -1299,6 +1303,10 @@ private:
|
||||
std::vector<std::unique_ptr<cmExportBuildFileGenerator>>
|
||||
ExportBuildFileGenerators;
|
||||
|
||||
#ifndef CMAKE_BOOTSTRAP
|
||||
std::vector<std::unique_ptr<cmBuildSbomGenerator>> BuildSbomGenerators;
|
||||
#endif
|
||||
|
||||
std::vector<std::unique_ptr<cmGeneratorExpressionEvaluationFile>>
|
||||
EvaluationFiles;
|
||||
|
||||
@@ -1357,7 +1365,6 @@ private:
|
||||
cmFindPackageStack FindPackageStack;
|
||||
unsigned int FindPackageStackNextIndex = 0;
|
||||
|
||||
bool ExplicitSbomGenerator = false;
|
||||
bool DebugFindPkg = false;
|
||||
|
||||
bool CheckSystemVars;
|
||||
|
||||
@@ -41,6 +41,7 @@ public:
|
||||
SbomFormat GetFormat() const;
|
||||
|
||||
ArgumentParser::NonEmpty<std::string> Format;
|
||||
ArgumentParser::NonEmpty<std::string> PackageUrl;
|
||||
|
||||
protected:
|
||||
cm::string_view CommandName() const override;
|
||||
@@ -54,6 +55,7 @@ private:
|
||||
cmProjectInfoArguments* const base = self;
|
||||
Bind(base, parser, "SBOM"_s, &cmProjectInfoArguments::PackageName);
|
||||
Bind(self, parser, "FORMAT"_s, &cmSbomArguments::Format);
|
||||
Bind(self, parser, "PACKAGE_URL"_s, &cmSbomArguments::PackageUrl);
|
||||
cmProjectInfoArguments::Bind(parser, self);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,25 +1,33 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file LICENSE.rst or https://cmake.org/licensing for details. */
|
||||
#include "cmExportSbomGenerator.h"
|
||||
#include "cmSbomBuilder.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <cm/optional>
|
||||
#include <cmext/algorithm>
|
||||
#include <cmext/string_view>
|
||||
|
||||
#include "cmArgumentParserTypes.h"
|
||||
#include "cmDiagnostics.h"
|
||||
#include "cmExportFileGenerator.h"
|
||||
#include "cmExportSet.h"
|
||||
#include "cmFindPackageStack.h"
|
||||
#include "cmGeneratorExpression.h"
|
||||
#include "cmGeneratorTarget.h"
|
||||
#include "cmList.h"
|
||||
#include "cmLocalGenerator.h"
|
||||
#include "cmMakefile.h"
|
||||
#include "cmMessageType.h"
|
||||
#include "cmSbomArguments.h"
|
||||
#include "cmSbomObject.h"
|
||||
#include "cmSpdx.h"
|
||||
@@ -28,6 +36,7 @@
|
||||
#include "cmStringAlgorithms.h"
|
||||
#include "cmSystemTools.h"
|
||||
#include "cmTarget.h"
|
||||
#include "cmTargetExport.h"
|
||||
#include "cmValue.h"
|
||||
|
||||
cmSpdxPackage::PurposeId GetPurpose(cmStateEnums::TargetType type)
|
||||
@@ -50,23 +59,94 @@ cmSpdxPackage::PurposeId GetPurpose(cmStateEnums::TargetType type)
|
||||
}
|
||||
}
|
||||
|
||||
cmExportSbomGenerator::cmExportSbomGenerator(cmSbomArguments args)
|
||||
: PackageName(std::move(args.PackageName))
|
||||
cmSbomBuilder::cmSbomBuilder(cmSbomArguments args,
|
||||
std::vector<cmExportSet*> exportSets,
|
||||
cmLocalGenerator* lg)
|
||||
: LocalGenerator(lg)
|
||||
, ExportSets(std::move(exportSets))
|
||||
, PackageName(std::move(args.PackageName))
|
||||
, Namespace(cmStrCat(this->PackageName, "::"_s))
|
||||
, PackageVersion(std::move(args.Version))
|
||||
, PackageDescription(std::move(args.Description))
|
||||
, PackageWebsite(std::move(args.Website))
|
||||
, PackageUrl(std::move(args.PackageUrl))
|
||||
, PackageLicense(std::move(args.License))
|
||||
, PackageFormat(args.GetFormat())
|
||||
{
|
||||
}
|
||||
|
||||
bool cmExportSbomGenerator::GenerateImportFile(std::ostream& os)
|
||||
std::set<cmGeneratorTarget const*> cmSbomBuilder::CollectTargets() const
|
||||
{
|
||||
return this->GenerateMainFile(os);
|
||||
std::set<cmGeneratorTarget const*> targets;
|
||||
for (cmExportSet* exportSet : this->ExportSets) {
|
||||
for (auto const& te : exportSet->GetTargetExports()) {
|
||||
if (cmGeneratorTarget const* gt =
|
||||
this->LocalGenerator->FindGeneratorTargetToUse(te->TargetName)) {
|
||||
targets.emplace(gt);
|
||||
}
|
||||
}
|
||||
}
|
||||
return targets;
|
||||
}
|
||||
|
||||
void cmExportSbomGenerator::WriteSbom(cmSbomDocument& doc,
|
||||
std::ostream& os) const
|
||||
void cmSbomBuilder::Compute(cmLocalGenerator* lg)
|
||||
{
|
||||
this->LocalGenerator = lg;
|
||||
if (!lg) {
|
||||
return;
|
||||
}
|
||||
for (cmExportSet* es : this->ExportSets) {
|
||||
es->Compute(lg);
|
||||
}
|
||||
// Populate the cache now (rather than at Generate time) so peer SBOMs can
|
||||
// query CoversTarget() during their own NoteLinkedTarget walks.
|
||||
this->SbomTargets = this->CollectTargets();
|
||||
}
|
||||
|
||||
bool cmSbomBuilder::CoversTarget(cmGeneratorTarget const* target) const
|
||||
{
|
||||
return cm::contains(this->SbomTargets, target);
|
||||
}
|
||||
|
||||
bool cmSbomBuilder::CoversExportSet(cmExportSet const* set) const
|
||||
{
|
||||
return std::find(this->ExportSets.cbegin(), this->ExportSets.cend(), set) !=
|
||||
this->ExportSets.cend();
|
||||
}
|
||||
|
||||
bool cmSbomBuilder::GenerateForTargets(
|
||||
std::ostream& os, cmGeneratorExpression::PreprocessContext preprocessContext)
|
||||
{
|
||||
cmSbomDocument doc;
|
||||
doc.Graph.reserve(256);
|
||||
|
||||
cmSpdxCreationInfo const* ci =
|
||||
insert_back(doc.Graph, this->GenerateCreationInfo());
|
||||
cmSpdxDocument* project = insert_back(doc.Graph, this->GenerateSbom(ci));
|
||||
std::vector<TargetProperties> targetProps;
|
||||
targetProps.reserve(this->SbomTargets.size());
|
||||
|
||||
for (cmGeneratorTarget const* target : this->SbomTargets) {
|
||||
ImportPropertyMap properties;
|
||||
this->PopulateLinkLibrariesProperty(target, preprocessContext, properties);
|
||||
this->PopulateInterfaceLinkLibrariesProperty(target, preprocessContext,
|
||||
properties);
|
||||
|
||||
targetProps.push_back(
|
||||
TargetProperties{ insert_back(project->RootElements,
|
||||
this->GenerateImportTarget(ci, target)),
|
||||
target, std::move(properties) });
|
||||
}
|
||||
|
||||
for (TargetProperties const& target : targetProps) {
|
||||
this->GenerateProperties(doc, project, ci, target, targetProps);
|
||||
}
|
||||
|
||||
this->WriteSbom(doc, os);
|
||||
return true;
|
||||
}
|
||||
|
||||
void cmSbomBuilder::WriteSbom(cmSbomDocument& doc, std::ostream& os) const
|
||||
{
|
||||
switch (this->PackageFormat) {
|
||||
case cmSbomArguments::SbomFormat::SPDX_3_0_JSON:
|
||||
@@ -77,7 +157,7 @@ void cmExportSbomGenerator::WriteSbom(cmSbomDocument& doc,
|
||||
}
|
||||
}
|
||||
|
||||
bool cmExportSbomGenerator::AddPackageInformation(
|
||||
bool cmSbomBuilder::AddPackageInformation(
|
||||
cmSpdxPackage& artifact, std::string const& name,
|
||||
cmPackageInformation const& package) const
|
||||
{
|
||||
@@ -114,7 +194,7 @@ bool cmExportSbomGenerator::AddPackageInformation(
|
||||
return true;
|
||||
}
|
||||
|
||||
cmSpdxCreationInfo cmExportSbomGenerator::GenerateCreationInfo() const
|
||||
cmSpdxCreationInfo cmSbomBuilder::GenerateCreationInfo() const
|
||||
{
|
||||
cmSpdxCreationInfo ci;
|
||||
ci.SpdxId = "_:Build#CreationInfo";
|
||||
@@ -125,8 +205,7 @@ cmSpdxCreationInfo cmExportSbomGenerator::GenerateCreationInfo() const
|
||||
return ci;
|
||||
}
|
||||
|
||||
cmSpdxDocument cmExportSbomGenerator::GenerateSbom(
|
||||
cmSpdxCreationInfo const* ci) const
|
||||
cmSpdxDocument cmSbomBuilder::GenerateSbom(cmSpdxCreationInfo const* ci) const
|
||||
{
|
||||
cmSpdxDocument proj;
|
||||
proj.Name = PackageName;
|
||||
@@ -145,7 +224,7 @@ cmSpdxDocument cmExportSbomGenerator::GenerateSbom(
|
||||
return proj;
|
||||
}
|
||||
|
||||
cmSpdxPackage cmExportSbomGenerator::GenerateImportTarget(
|
||||
cmSpdxPackage cmSbomBuilder::GenerateImportTarget(
|
||||
cmSpdxCreationInfo const* ci, cmGeneratorTarget const* target) const
|
||||
{
|
||||
cmSpdxPackage package;
|
||||
@@ -169,7 +248,7 @@ cmSpdxPackage cmExportSbomGenerator::GenerateImportTarget(
|
||||
return package;
|
||||
}
|
||||
|
||||
void cmExportSbomGenerator::GenerateLinkProperties(
|
||||
void cmSbomBuilder::GenerateLinkProperties(
|
||||
cmSbomDocument& doc, cmSpdxDocument* project, cmSpdxCreationInfo const* ci,
|
||||
std::string const& libraries, TargetProperties const& current,
|
||||
std::vector<TargetProperties> const& allTargets) const
|
||||
@@ -269,7 +348,7 @@ void cmExportSbomGenerator::GenerateLinkProperties(
|
||||
}
|
||||
}
|
||||
|
||||
bool cmExportSbomGenerator::GenerateProperties(
|
||||
bool cmSbomBuilder::GenerateProperties(
|
||||
cmSbomDocument& doc, cmSpdxDocument* proj, cmSpdxCreationInfo const* ci,
|
||||
TargetProperties const& current,
|
||||
std::vector<TargetProperties> const& allTargets) const
|
||||
@@ -281,7 +360,7 @@ bool cmExportSbomGenerator::GenerateProperties(
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cmExportSbomGenerator::PopulateLinkLibrariesProperty(
|
||||
bool cmSbomBuilder::PopulateLinkLibrariesProperty(
|
||||
cmGeneratorTarget const* target,
|
||||
cmGeneratorExpression::PreprocessContext preprocessRule,
|
||||
ImportPropertyMap& properties)
|
||||
@@ -296,8 +375,7 @@ bool cmExportSbomGenerator::PopulateLinkLibrariesProperty(
|
||||
std::string prepro =
|
||||
cmGeneratorExpression::Preprocess(*input, preprocessRule);
|
||||
if (!prepro.empty()) {
|
||||
this->ResolveTargetsInGeneratorExpressions(prepro, target,
|
||||
ReplaceFreeTargets);
|
||||
this->ResolveTargetsInGeneratorExpressions(prepro, target);
|
||||
properties[linkIfaceProp] = prepro;
|
||||
hadLINK_LIBRARIES = true;
|
||||
}
|
||||
@@ -306,11 +384,38 @@ bool cmExportSbomGenerator::PopulateLinkLibrariesProperty(
|
||||
return hadLINK_LIBRARIES;
|
||||
}
|
||||
|
||||
bool cmExportSbomGenerator::NoteLinkedTarget(
|
||||
cmGeneratorTarget const* target, std::string const& linkedName,
|
||||
cmGeneratorTarget const* linkedTarget)
|
||||
bool cmSbomBuilder::AddTargetNamespace(std::string& input,
|
||||
cmGeneratorTarget const* target,
|
||||
cmLocalGenerator const* lg)
|
||||
{
|
||||
if (cm::contains(this->ExportedTargets, linkedTarget)) {
|
||||
cmGeneratorTarget::TargetOrString resolved =
|
||||
target->ResolveTargetReference(input, lg);
|
||||
|
||||
cmGeneratorTarget* tgt = resolved.Target;
|
||||
if (!tgt) {
|
||||
input = resolved.String;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (tgt->IsImported()) {
|
||||
input = tgt->GetName();
|
||||
return this->NoteLinkedTarget(target, input, tgt);
|
||||
}
|
||||
|
||||
if (this->SbomTargets.find(tgt) != this->SbomTargets.end()) {
|
||||
input = this->Namespace + tgt->GetExportName();
|
||||
} else {
|
||||
input = tgt->GetName();
|
||||
}
|
||||
|
||||
return this->NoteLinkedTarget(target, input, tgt);
|
||||
}
|
||||
|
||||
bool cmSbomBuilder::NoteLinkedTarget(cmGeneratorTarget const* target,
|
||||
std::string const& linkedName,
|
||||
cmGeneratorTarget const* linkedTarget)
|
||||
{
|
||||
if (cm::contains(this->SbomTargets, linkedTarget)) {
|
||||
this->LinkTargets.emplace(linkedName,
|
||||
LinkInfo{ "", linkedTarget->GetExportName() });
|
||||
return true;
|
||||
@@ -357,8 +462,9 @@ bool cmExportSbomGenerator::NoteLinkedTarget(
|
||||
return true;
|
||||
}
|
||||
|
||||
// Target belongs to another export from this build.
|
||||
auto const& exportInfo = this->FindExportInfo(linkedTarget);
|
||||
// Target belongs to another export from this build or install.
|
||||
// The leaf class chooses which export map to consult.
|
||||
auto const& exportInfo = this->FindExportInfoFor(linkedTarget);
|
||||
if (exportInfo.Namespaces.size() == 1 && exportInfo.Sets.size() == 1) {
|
||||
auto const& linkNamespace = *exportInfo.Namespaces.begin();
|
||||
if (!cmHasSuffix(linkNamespace, "::")) {
|
||||
@@ -366,8 +472,10 @@ bool cmExportSbomGenerator::NoteLinkedTarget(
|
||||
cmDiagnostics::CMD_AUTHOR,
|
||||
cmStrCat("Target \"", target->GetName(), "\" references target \"",
|
||||
linkedName,
|
||||
"\", which does not use the standard namespace separator. "
|
||||
"This is not allowed."));
|
||||
"\", whose export does not use the standard namespace "
|
||||
"separator. The dependency will be recorded by its bare "
|
||||
"target name without provenance."));
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string pkgName{ linkNamespace.data(), linkNamespace.size() - 2 };
|
||||
@@ -381,8 +489,121 @@ bool cmExportSbomGenerator::NoteLinkedTarget(
|
||||
return true;
|
||||
}
|
||||
|
||||
// Target belongs to multiple namespaces or multiple export sets.
|
||||
// cmExportFileGenerator::HandleMissingTarget should have complained about
|
||||
// this already.
|
||||
if (exportInfo.Sets.empty()) {
|
||||
// install(export) provenance is unavailable. Fall back to SBOM-level
|
||||
// attribution: any peer SBOM (of the same build/install mode) that
|
||||
// covers this target lends its package name. install(export) wins
|
||||
// when both are available; only reached here when install(export) is
|
||||
// absent.
|
||||
auto const& sbomInfo = this->FindSbomInfoFor(linkedTarget);
|
||||
if (sbomInfo.Packages.empty()) {
|
||||
target->Makefile->IssueMessage(
|
||||
MessageType::FATAL_ERROR,
|
||||
cmStrCat("Target \"", target->GetName(), "\" references target \"",
|
||||
linkedName,
|
||||
"\" which has no install(EXPORT)/export(EXPORT) namespace "
|
||||
"and is not covered by any SBOM. An SBOM cannot attribute "
|
||||
"this dependency. Give \"",
|
||||
linkedTarget->GetName(),
|
||||
"\" an install(EXPORT)/export(EXPORT) with a NAMESPACE, or "
|
||||
"include it in an install(SBOM)/export(SBOM)."));
|
||||
return false;
|
||||
}
|
||||
std::string const& pkgName = sbomInfo.Packages.front();
|
||||
if (sbomInfo.Packages.size() > 1) {
|
||||
target->Makefile->IssueDiagnostic(
|
||||
cmDiagnostics::CMD_AUTHOR,
|
||||
cmStrCat(
|
||||
"Target \"", target->GetName(), "\" references target \"",
|
||||
linkedName,
|
||||
"\" which has no install(EXPORT)/export(EXPORT) namespace and is "
|
||||
"covered by multiple SBOMs: ",
|
||||
cmJoin(sbomInfo.Packages, ", "), ". Attributing to \"", pkgName,
|
||||
"\" (first alphabetically)."));
|
||||
}
|
||||
std::string component = linkedTarget->GetExportName();
|
||||
this->LinkTargets.emplace(linkedName, LinkInfo{ pkgName, component });
|
||||
this->Requirements[pkgName].Components.emplace(std::move(component));
|
||||
return true;
|
||||
}
|
||||
|
||||
std::ostringstream e;
|
||||
e << "Target \"" << target->GetName() << "\" references target \""
|
||||
<< linkedName << "\" ";
|
||||
if (exportInfo.Sets.size() == 1) {
|
||||
e << "that is in an export set which is exported multiple times "
|
||||
"with different namespaces: ";
|
||||
} else {
|
||||
e << "that is in multiple export sets: ";
|
||||
}
|
||||
e << cmJoin(exportInfo.Files, ", ") << ".\n"
|
||||
<< "An SBOM cannot attribute a dependency exported in more than one "
|
||||
"export set or with more than one namespace. Consider "
|
||||
"consolidating the exports of the \""
|
||||
<< linkedTarget->GetName() << "\" target to a single export.";
|
||||
target->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
|
||||
return false;
|
||||
}
|
||||
|
||||
void cmSbomBuilder::ResolveTargetsInGeneratorExpression(
|
||||
std::string& input, cmGeneratorTarget const* target,
|
||||
cmLocalGenerator const* lg)
|
||||
{
|
||||
auto err = cmResolveTargetsInGeneratorExpression(
|
||||
input, [this, target, lg](std::string& name) {
|
||||
return this->AddTargetNamespace(name, target, lg);
|
||||
});
|
||||
if (err) {
|
||||
target->GetLocalGenerator()->IssueMessage(MessageType::FATAL_ERROR, *err);
|
||||
}
|
||||
}
|
||||
|
||||
void cmSbomBuilder::ResolveTargetsInGeneratorExpressions(
|
||||
std::string& input, cmGeneratorTarget const* target)
|
||||
{
|
||||
cmLocalGenerator const* lg = target->GetLocalGenerator();
|
||||
std::vector<std::string> parts;
|
||||
cmGeneratorExpression::Split(input, parts);
|
||||
|
||||
std::string sep;
|
||||
input.clear();
|
||||
for (std::string& li : parts) {
|
||||
if (target->IsLinkLookupScope(li, lg)) {
|
||||
continue;
|
||||
}
|
||||
if (cmGeneratorExpression::Find(li) == std::string::npos) {
|
||||
this->AddTargetNamespace(li, target, lg);
|
||||
} else {
|
||||
this->ResolveTargetsInGeneratorExpression(li, target, lg);
|
||||
}
|
||||
input += sep + li;
|
||||
sep = ";";
|
||||
}
|
||||
}
|
||||
|
||||
bool cmSbomBuilder::PopulateInterfaceLinkLibrariesProperty(
|
||||
cmGeneratorTarget const* target,
|
||||
cmGeneratorExpression::PreprocessContext preprocessRule,
|
||||
ImportPropertyMap& properties)
|
||||
{
|
||||
if (!target->IsLinkable()) {
|
||||
return false;
|
||||
}
|
||||
static std::array<std::string, 3> const linkIfaceProps = {
|
||||
{ "INTERFACE_LINK_LIBRARIES", "INTERFACE_LINK_LIBRARIES_DIRECT",
|
||||
"INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE" }
|
||||
};
|
||||
bool hadINTERFACE_LINK_LIBRARIES = false;
|
||||
for (std::string const& linkIfaceProp : linkIfaceProps) {
|
||||
if (cmValue input = target->GetProperty(linkIfaceProp)) {
|
||||
std::string prepro =
|
||||
cmGeneratorExpression::Preprocess(*input, preprocessRule);
|
||||
if (!prepro.empty()) {
|
||||
this->ResolveTargetsInGeneratorExpressions(prepro, target);
|
||||
properties[linkIfaceProp] = prepro;
|
||||
hadINTERFACE_LINK_LIBRARIES = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return hadINTERFACE_LINK_LIBRARIES;
|
||||
}
|
||||
@@ -0,0 +1,179 @@
|
||||
/* 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 <map>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "cmExportFileGenerator.h"
|
||||
#include "cmFindPackageStack.h"
|
||||
#include "cmGeneratorExpression.h"
|
||||
#include "cmSbomArguments.h"
|
||||
|
||||
class cmExportSet;
|
||||
class cmGeneratorTarget;
|
||||
class cmLocalGenerator;
|
||||
struct cmSbomDocument;
|
||||
struct cmSpdxDocument;
|
||||
struct cmSpdxPackage;
|
||||
struct cmSpdxCreationInfo;
|
||||
|
||||
/** \class cmSbomBuilder
|
||||
* \brief Abstract base for SBOM document generators.
|
||||
*
|
||||
* Concrete leaves (cmBuildSbomBuilder, cmInstallSbomBuilder) supply two
|
||||
* pure virtuals:
|
||||
*
|
||||
* - Generate(): selects the generator-expression preprocess context
|
||||
* (BuildInterface vs InstallInterface) and delegates to the shared
|
||||
* GenerateForTargets() body.
|
||||
* - FindExportInfoFor(): consults the mode's export map (build-tree vs
|
||||
* install-tree) to resolve cross-export references.
|
||||
*
|
||||
* All shared SPDX assembly, link-graph walking, and serialization lives
|
||||
* here so that the leaves stay trivial.
|
||||
*/
|
||||
class cmSbomBuilder
|
||||
{
|
||||
public:
|
||||
virtual ~cmSbomBuilder() = default;
|
||||
|
||||
/** Compute phase: wire the local generator, run Compute() on the owned
|
||||
* export sets, and populate the SbomTargets cache so peer SBOMs can
|
||||
* query CoversTarget() before any Generate() runs. */
|
||||
void Compute(cmLocalGenerator* lg);
|
||||
|
||||
/** Produce the SBOM document on `os`. Implementations pick the
|
||||
* generator-expression preprocess context (BuildInterface vs
|
||||
* InstallInterface) and delegate to GenerateForTargets. */
|
||||
virtual bool Generate(std::ostream& os) = 0;
|
||||
|
||||
/** Identifier this SBOM publishes itself as (the SPDX document name and
|
||||
* the namespace under which other SBOMs refer to its contents). */
|
||||
std::string const& GetPackageName() const { return this->PackageName; }
|
||||
|
||||
/** True if `target` is one of the targets this SBOM directly describes. */
|
||||
bool CoversTarget(cmGeneratorTarget const* target) const;
|
||||
|
||||
/** True if `set` is one of the export sets this SBOM was built from. */
|
||||
bool CoversExportSet(cmExportSet const* set) const;
|
||||
|
||||
/** Names of peer SBOMs (same build/install mode) that cover a target.
|
||||
* Used by NoteLinkedTarget to attribute a cross-reference when no
|
||||
* install(export) namespace is available. Sorted alphabetically. */
|
||||
struct SbomInfo
|
||||
{
|
||||
std::vector<std::string> Packages;
|
||||
};
|
||||
|
||||
protected:
|
||||
cmSbomBuilder(cmSbomArguments args, std::vector<cmExportSet*> exportSets,
|
||||
cmLocalGenerator* lg);
|
||||
|
||||
/** Mode-specific: where does `target` appear in the project's exports?
|
||||
* Build leaves consult cmGlobalGenerator::FindBuildExportInfo;
|
||||
* install leaves consult cmGlobalGenerator::FindInstallExportInfo. */
|
||||
virtual cmExportFileGenerator::ExportInfo FindExportInfoFor(
|
||||
cmGeneratorTarget const* target) const = 0;
|
||||
|
||||
/** Mode-specific: which peer SBOMs cover `target`?
|
||||
* Build leaves consult cmGlobalGenerator::FindBuildSbomInfo;
|
||||
* install leaves consult cmGlobalGenerator::FindInstallSbomInfo. */
|
||||
virtual SbomInfo FindSbomInfoFor(cmGeneratorTarget const* target) const = 0;
|
||||
|
||||
/** The set of targets the SBOM directly describes — derived from the
|
||||
* associated export sets. */
|
||||
std::set<cmGeneratorTarget const*> CollectTargets() const;
|
||||
|
||||
/** Generate an sbom for the targets in this->SbomTargets. Each leaf class
|
||||
* calls this internally */
|
||||
bool GenerateForTargets(
|
||||
std::ostream& os,
|
||||
cmGeneratorExpression::PreprocessContext preprocessContext);
|
||||
|
||||
using ImportPropertyMap = std::map<std::string, std::string>;
|
||||
|
||||
struct TargetProperties
|
||||
{
|
||||
cmSpdxPackage const* Package;
|
||||
cmGeneratorTarget const* Target;
|
||||
ImportPropertyMap Properties;
|
||||
};
|
||||
|
||||
void WriteSbom(cmSbomDocument& doc, std::ostream& os) const;
|
||||
|
||||
cmSpdxCreationInfo GenerateCreationInfo() const;
|
||||
cmSpdxDocument GenerateSbom(cmSpdxCreationInfo const* ci) const;
|
||||
cmSpdxPackage GenerateImportTarget(cmSpdxCreationInfo const* ci,
|
||||
cmGeneratorTarget const* target) const;
|
||||
|
||||
bool AddPackageInformation(cmSpdxPackage& artifact, std::string const& name,
|
||||
cmPackageInformation const& package) const;
|
||||
|
||||
bool GenerateProperties(
|
||||
cmSbomDocument& doc, cmSpdxDocument* project, cmSpdxCreationInfo const* ci,
|
||||
TargetProperties const& current,
|
||||
std::vector<TargetProperties> const& allTargets) const;
|
||||
|
||||
void GenerateLinkProperties(
|
||||
cmSbomDocument& doc, cmSpdxDocument* project, cmSpdxCreationInfo const* ci,
|
||||
std::string const& libraries, TargetProperties const& current,
|
||||
std::vector<TargetProperties> const& allTargets) const;
|
||||
|
||||
bool NoteLinkedTarget(cmGeneratorTarget const* target,
|
||||
std::string const& linkedName,
|
||||
cmGeneratorTarget const* linkedTarget);
|
||||
|
||||
bool AddTargetNamespace(std::string& input, cmGeneratorTarget const* target,
|
||||
cmLocalGenerator const* lg);
|
||||
|
||||
void ResolveTargetsInGeneratorExpression(std::string& input,
|
||||
cmGeneratorTarget const* target,
|
||||
cmLocalGenerator const* lg);
|
||||
void ResolveTargetsInGeneratorExpressions(std::string& input,
|
||||
cmGeneratorTarget const* target);
|
||||
|
||||
bool PopulateInterfaceLinkLibrariesProperty(
|
||||
cmGeneratorTarget const* target,
|
||||
cmGeneratorExpression::PreprocessContext preprocessRule,
|
||||
ImportPropertyMap& properties);
|
||||
|
||||
bool PopulateLinkLibrariesProperty(cmGeneratorTarget const* target,
|
||||
cmGeneratorExpression::PreprocessContext,
|
||||
ImportPropertyMap& properties);
|
||||
|
||||
// Set at construction or via setters
|
||||
cmLocalGenerator* LocalGenerator = nullptr;
|
||||
|
||||
// Inputs
|
||||
std::vector<cmExportSet*> ExportSets;
|
||||
|
||||
private:
|
||||
struct LinkInfo
|
||||
{
|
||||
std::string Package;
|
||||
std::string Component;
|
||||
};
|
||||
|
||||
// Metadata
|
||||
std::string const PackageName;
|
||||
std::string const Namespace;
|
||||
std::string const PackageVersion;
|
||||
std::string const PackageDescription;
|
||||
std::string const PackageWebsite;
|
||||
std::string const PackageUrl;
|
||||
std::string const PackageLicense;
|
||||
cmSbomArguments::SbomFormat const PackageFormat;
|
||||
|
||||
// Derived from inputs at generate time
|
||||
std::set<cmGeneratorTarget const*> SbomTargets;
|
||||
|
||||
// Accumulated during generation
|
||||
std::map<std::string, LinkInfo> LinkTargets;
|
||||
std::map<std::string, cmPackageInformation> Requirements;
|
||||
};
|
||||
@@ -0,0 +1,24 @@
|
||||
set(failures "")
|
||||
|
||||
foreach(f explicit_root_sbom explicit_subdir_sbom)
|
||||
if(NOT EXISTS "${RunCMake_TEST_INSTALL_DIR}/${f}.spdx.json")
|
||||
list(APPEND failures "expected explicit SBOM ${f}.spdx.json to exist")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
foreach(f implicit_root implicit_subdir)
|
||||
if(NOT EXISTS "${RunCMake_TEST_INSTALL_DIR}/lib/sbom/test_project/${f}.spdx.json")
|
||||
list(APPEND failures "expected autogen SBOM ${f}.spdx.json to exist")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
foreach(f explicit_root explicit_subdir)
|
||||
if(EXISTS "${RunCMake_TEST_INSTALL_DIR}/lib/sbom/test_project/${f}.spdx.json")
|
||||
list(APPEND failures "autogen wrongly produced ${f}.spdx.json (should be suppressed by explicit install(SBOM))")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if(failures)
|
||||
string(REPLACE ";" "\n " msg "${failures}")
|
||||
set(RunCMake_TEST_FAILED "${msg}")
|
||||
endif()
|
||||
@@ -0,0 +1,12 @@
|
||||
project(test_project)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/../Sbom/Setup.cmake)
|
||||
|
||||
add_library(libA INTERFACE)
|
||||
add_library(libB INTERFACE)
|
||||
|
||||
install(TARGETS libA EXPORT explicit_root DESTINATION .)
|
||||
install(TARGETS libB EXPORT implicit_root DESTINATION .)
|
||||
|
||||
install(SBOM explicit_root_sbom EXPORTS explicit_root DESTINATION .)
|
||||
|
||||
add_subdirectory(PartialCoverage_subdir)
|
||||
@@ -0,0 +1,7 @@
|
||||
add_library(libC INTERFACE)
|
||||
add_library(libD INTERFACE)
|
||||
|
||||
install(TARGETS libC EXPORT explicit_subdir DESTINATION .)
|
||||
install(TARGETS libD EXPORT implicit_subdir DESTINATION .)
|
||||
|
||||
install(SBOM explicit_subdir_sbom EXPORTS explicit_subdir DESTINATION .)
|
||||
@@ -1,2 +0,0 @@
|
||||
file(READ "${RunCMake_TEST_INSTALL_DIR}/lib/sbom/test_project/dog.spdx.json" content)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/../Sbom/ReferencesNonExportedTarget-install-check.cmake)
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,6 @@
|
||||
CMake Error in CMakeLists\.txt:
|
||||
Target "canine" references target "mammal" which has no
|
||||
install\(EXPORT\)/export\(EXPORT\) namespace and is not covered by any SBOM\.
|
||||
An SBOM cannot attribute this dependency\. Give "mammal" an
|
||||
install\(EXPORT\)/export\(EXPORT\) with a NAMESPACE, or include it in an
|
||||
install\(SBOM\)/export\(SBOM\)\.
|
||||
@@ -2,11 +2,20 @@ include(RunCMake)
|
||||
|
||||
set(common_test_options
|
||||
-Wno-author
|
||||
"-DCMAKE_EXPERIMENTAL_GENERATE_SBOM:STRING=ca494ed3-b261-4205-a01f-603c95e4cae0"
|
||||
"-DCMAKE_EXPERIMENTAL_GENERATE_SBOM:STRING=2d856d6d-53e8-488b-a17f-d486d2cac317"
|
||||
"-DCMAKE_INSTALL_SBOM_FORMATS:STRING=JSON"
|
||||
"-DCMAKE_INSTALL_LIBDIR=lib"
|
||||
)
|
||||
|
||||
function(run_cmake_error test)
|
||||
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${test}-build)
|
||||
set(RunCMake_TEST_OPTIONS ${common_test_options})
|
||||
if(NOT RunCMake_GENERATOR_IS_MULTI_CONFIG)
|
||||
list(APPEND RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=DEBUG)
|
||||
endif()
|
||||
run_cmake(${test})
|
||||
endfunction()
|
||||
|
||||
function(run_cmake_install test)
|
||||
set(extra_options ${ARGN})
|
||||
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${test}-build)
|
||||
@@ -19,7 +28,9 @@ function(run_cmake_install test)
|
||||
|
||||
run_cmake(${test})
|
||||
set(RunCMake_TEST_NO_CLEAN TRUE)
|
||||
set(RunCMake_TEST_OUTPUT_MERGE 1)
|
||||
run_cmake_command(${test}-build ${CMAKE_COMMAND} --build . --config Debug)
|
||||
unset(RunCMake_TEST_OUTPUT_MERGE)
|
||||
run_cmake_command(${test}-install ${CMAKE_COMMAND} --install . --config Debug)
|
||||
endfunction()
|
||||
|
||||
@@ -28,5 +39,7 @@ run_cmake_install(InterfaceTarget)
|
||||
run_cmake_install(SharedTarget)
|
||||
|
||||
run_cmake_install(MissingPackageNamespace)
|
||||
run_cmake_install(ReferencesNonExportedTarget)
|
||||
run_cmake_install(ProjectMetadata)
|
||||
run_cmake_install(PartialCoverage)
|
||||
|
||||
run_cmake_error(ReferencesNonExportedTarget)
|
||||
|
||||
@@ -2,6 +2,6 @@ include(${CMAKE_CURRENT_LIST_DIR}/../Sbom/ApplicationTarget.cmake)
|
||||
|
||||
export(
|
||||
SBOM application_targets
|
||||
EXPORT application_targets
|
||||
EXPORTS application_targets
|
||||
FORMAT "spdx-3.0+json"
|
||||
)
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,2 @@
|
||||
CMake Error at DuplicateSbom\.cmake:[0-9]+ \(export\):
|
||||
export SBOM command already specified for the file mySbom\.spdx\.json\.
|
||||
@@ -0,0 +1,5 @@
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/../Sbom/DuplicateSbom.cmake)
|
||||
|
||||
export(EXPORT setA FILE setA.cmake)
|
||||
export(SBOM mySbom EXPORTS setA)
|
||||
export(SBOM mySbom EXPORTS setA)
|
||||
@@ -0,0 +1,2 @@
|
||||
file(READ "${RunCMake_TEST_BINARY_DIR}/sbom/mySbom/mySbom.spdx.json" content)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/../Sbom/EmptyNamespaceFallback-install-check.cmake)
|
||||
@@ -0,0 +1,4 @@
|
||||
CMake Warning \(author\) in CMakeLists\.txt:
|
||||
Target "libb" references target "liba", whose export does not use the
|
||||
standard namespace separator\. The dependency will be recorded by its bare
|
||||
target name without provenance\.
|
||||
@@ -0,0 +1,5 @@
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/../Sbom/EmptyNamespaceFallback.cmake)
|
||||
|
||||
export(EXPORT setA FILE setA.cmake)
|
||||
export(EXPORT setB NAMESPACE B:: FILE setB.cmake)
|
||||
export(SBOM mySbom EXPORTS setB)
|
||||
@@ -0,0 +1,5 @@
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/../Sbom/InstallExportPlusSbomSameSet.cmake)
|
||||
|
||||
export(EXPORT export_set_a NAMESPACE A:: FILE export_set_a.cmake)
|
||||
export(SBOM mySbom EXPORTS export_set_a)
|
||||
export(EXPORT export_set_b FILE export_set_b.cmake)
|
||||
@@ -2,5 +2,5 @@ include(${CMAKE_CURRENT_LIST_DIR}/../Sbom/InterfaceTarget.cmake)
|
||||
|
||||
export(
|
||||
SBOM interface_targets
|
||||
EXPORT interface_targets
|
||||
EXPORTS interface_targets
|
||||
)
|
||||
|
||||
@@ -2,6 +2,6 @@ include(${CMAKE_CURRENT_LIST_DIR}/../Sbom/MissingPackageNamespace.cmake)
|
||||
|
||||
export(
|
||||
SBOM test_targets
|
||||
EXPORT test_targets
|
||||
EXPORTS test_targets
|
||||
VERSION 1.0.2
|
||||
)
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,7 @@
|
||||
CMake Error in CMakeLists\.txt:
|
||||
Target "libb" references target "liba" that is in an export set which is
|
||||
exported multiple times with different namespaces:[^,]+setA-A\.cmake,[^,]+setA-OldA\.cmake\.
|
||||
|
||||
An SBOM cannot attribute a dependency exported in more than one export set
|
||||
or with more than one namespace\. Consider consolidating the exports of the
|
||||
"liba" target to a single export\.
|
||||
@@ -0,0 +1,5 @@
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/../Sbom/MultiNamespaceAmbiguity.cmake)
|
||||
|
||||
export(EXPORT setA NAMESPACE A:: FILE setA-A.cmake)
|
||||
export(EXPORT setA NAMESPACE OldA:: FILE setA-OldA.cmake)
|
||||
export(SBOM mySbom EXPORTS setB)
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,8 @@
|
||||
CMake Error in CMakeLists\.txt:
|
||||
Target "libb" references target "liba" that is in multiple export sets:
|
||||
.*/setA1\.cmake,
|
||||
.*/setA2\.cmake\.
|
||||
|
||||
An SBOM cannot attribute a dependency exported in more than one export set
|
||||
or with more than one namespace\. Consider consolidating the exports of the
|
||||
"liba" target to a single export\.
|
||||
@@ -0,0 +1,5 @@
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/../Sbom/MultiSetAmbiguity.cmake)
|
||||
|
||||
export(EXPORT setA1 NAMESPACE A1:: FILE setA1.cmake)
|
||||
export(EXPORT setA2 NAMESPACE A2:: FILE setA2.cmake)
|
||||
export(SBOM mySbom EXPORTS setB)
|
||||
@@ -0,0 +1,2 @@
|
||||
file(READ "${RunCMake_TEST_BINARY_DIR}/sbom/mySbom/mySbom.spdx.json" content)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/../Sbom/MultiSetSingleSbom-install-check.cmake)
|
||||
@@ -0,0 +1,5 @@
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/../Sbom/MultiSetSingleSbom.cmake)
|
||||
|
||||
export(EXPORT setA NAMESPACE A:: FILE setA.cmake)
|
||||
export(EXPORT setB NAMESPACE B:: FILE setB.cmake)
|
||||
export(SBOM mySbom EXPORTS setA setB)
|
||||
@@ -1,2 +1,3 @@
|
||||
file(READ "${RunCMake_TEST_BINARY_DIR}/sbom/test_targets/test_targets.spdx.json" content)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/../Sbom/ProjectMetadata-install-check.cmake)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/../Sbom/ProjectMetadataExplicitAssertions.cmake)
|
||||
|
||||
@@ -2,9 +2,10 @@ include(${CMAKE_CURRENT_LIST_DIR}/../Sbom/ProjectMetadata.cmake)
|
||||
|
||||
export(
|
||||
SBOM test_targets
|
||||
EXPORT test_targets
|
||||
EXPORTS test_targets
|
||||
DESCRIPTION "An eloquent description"
|
||||
LICENSE "BSD-3"
|
||||
HOMEPAGE_URL "www.example.com"
|
||||
PACKAGE_URL "https://example.com/test_targets.tar.gz"
|
||||
VERSION "1.3.4"
|
||||
)
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
file(READ "${RunCMake_TEST_BINARY_DIR}/sbom/dog/dog.spdx.json" content)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/../Sbom/ReferencesNonExportedTarget-install-check.cmake)
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,6 @@
|
||||
CMake Error in CMakeLists\.txt:
|
||||
Target "canine" references target "mammal" which has no
|
||||
install\(EXPORT\)/export\(EXPORT\) namespace and is not covered by any SBOM\.
|
||||
An SBOM cannot attribute this dependency\. Give "mammal" an
|
||||
install\(EXPORT\)/export\(EXPORT\) with a NAMESPACE, or include it in an
|
||||
install\(SBOM\)/export\(SBOM\)\.
|
||||
@@ -1,3 +1,3 @@
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/../Sbom/ReferencesNonExportedTarget.cmake)
|
||||
|
||||
export(SBOM dog EXPORT dog)
|
||||
export(SBOM dog EXPORTS dog)
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
file(READ "${RunCMake_TEST_BINARY_DIR}/sbom/bar/bar.spdx.json" BAR_CONTENT)
|
||||
file(READ "${RunCMake_TEST_BINARY_DIR}/sbom/foo/foo.spdx.json" FOO_CONTENT)
|
||||
file(READ "${RunCMake_TEST_BINARY_DIR}/sbom/bar_sbom/bar_sbom.spdx.json" BAR_CONTENT)
|
||||
file(READ "${RunCMake_TEST_BINARY_DIR}/sbom/foo_sbom/foo_sbom.spdx.json" FOO_CONTENT)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/../Sbom/Requirements-install-check.cmake)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/../Sbom/Requirements.cmake)
|
||||
|
||||
export(SBOM foo EXPORT foo)
|
||||
export(SBOM bar EXPORT bar)
|
||||
export(EXPORT foo NAMESPACE foo:: FILE foo.cmake)
|
||||
export(SBOM foo_sbom EXPORTS foo)
|
||||
export(SBOM bar_sbom EXPORTS bar)
|
||||
|
||||
@@ -2,9 +2,18 @@ include(RunCMake)
|
||||
|
||||
set(common_test_options
|
||||
-Wno-author
|
||||
"-DCMAKE_EXPERIMENTAL_GENERATE_SBOM:STRING=ca494ed3-b261-4205-a01f-603c95e4cae0"
|
||||
"-DCMAKE_EXPERIMENTAL_GENERATE_SBOM:STRING=2d856d6d-53e8-488b-a17f-d486d2cac317"
|
||||
)
|
||||
|
||||
function(run_cmake_error test)
|
||||
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${test}-build)
|
||||
set(RunCMake_TEST_OPTIONS ${common_test_options})
|
||||
if(NOT RunCMake_GENERATOR_IS_MULTI_CONFIG)
|
||||
list(APPEND RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=DEBUG)
|
||||
endif()
|
||||
run_cmake(${test})
|
||||
endfunction()
|
||||
|
||||
function(run_cmake_install test)
|
||||
set(extra_options ${ARGN})
|
||||
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${test}-build)
|
||||
@@ -17,14 +26,27 @@ function(run_cmake_install test)
|
||||
|
||||
run_cmake(${test})
|
||||
set(RunCMake_TEST_NO_CLEAN TRUE)
|
||||
set(RunCMake_TEST_OUTPUT_MERGE 1)
|
||||
run_cmake_command(${test}-build ${CMAKE_COMMAND} --build . --config Debug)
|
||||
unset(RunCMake_TEST_OUTPUT_MERGE)
|
||||
run_cmake_command(${test}-install ${CMAKE_COMMAND} --install . --config Debug)
|
||||
endfunction()
|
||||
|
||||
run_cmake_install(ApplicationTarget)
|
||||
run_cmake_install(InstallExportPlusSbomSameSet)
|
||||
run_cmake_install(InterfaceTarget)
|
||||
run_cmake_install(SharedTarget)
|
||||
run_cmake_install(Requirements)
|
||||
run_cmake_install(SbomNamespaceFallback)
|
||||
run_cmake_install(MultiSetSingleSbom)
|
||||
run_cmake_install(TargetInMultipleSets)
|
||||
run_cmake_install(EmptyNamespaceFallback -Wauthor)
|
||||
run_cmake_install(SbomNamespaceAmbiguity -Wauthor)
|
||||
|
||||
run_cmake_install(MissingPackageNamespace)
|
||||
run_cmake_install(ReferencesNonExportedTarget)
|
||||
run_cmake_install(ProjectMetadata)
|
||||
|
||||
run_cmake_error(ReferencesNonExportedTarget)
|
||||
run_cmake_error(MultiNamespaceAmbiguity)
|
||||
run_cmake_error(MultiSetAmbiguity)
|
||||
run_cmake_error(DuplicateSbom)
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
file(READ "${RunCMake_TEST_BINARY_DIR}/sbom/bar_sbom/bar_sbom.spdx.json" BAR_CONTENT)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/../Sbom/SbomNamespaceAmbiguity-install-check.cmake)
|
||||
@@ -0,0 +1,4 @@
|
||||
CMake Warning \(author\) in CMakeLists\.txt:
|
||||
Target "libc" references target "libb" which has no
|
||||
install\(EXPORT\)/export\(EXPORT\) namespace and is covered by multiple SBOMs:
|
||||
foo_sbom, foo_sbom2\. Attributing to "foo_sbom" \(first alphabetically\)\.
|
||||
@@ -0,0 +1,5 @@
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/../Sbom/SbomNamespaceAmbiguity.cmake)
|
||||
|
||||
export(SBOM foo_sbom EXPORTS foo)
|
||||
export(SBOM foo_sbom2 EXPORTS foo)
|
||||
export(SBOM bar_sbom EXPORTS bar)
|
||||
@@ -0,0 +1,3 @@
|
||||
file(READ "${RunCMake_TEST_BINARY_DIR}/sbom/bar/bar.spdx.json" BAR_CONTENT)
|
||||
file(READ "${RunCMake_TEST_BINARY_DIR}/sbom/foo/foo.spdx.json" FOO_CONTENT)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/../Sbom/SbomNamespaceFallback-install-check.cmake)
|
||||
@@ -0,0 +1,4 @@
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/../Sbom/SbomNamespaceFallback.cmake)
|
||||
|
||||
export(SBOM foo EXPORTS foo)
|
||||
export(SBOM bar EXPORTS bar)
|
||||
@@ -2,5 +2,5 @@ include(${CMAKE_CURRENT_LIST_DIR}/../Sbom/SharedTarget.cmake)
|
||||
|
||||
export(
|
||||
SBOM shared_targets
|
||||
EXPORT shared_targets
|
||||
EXPORTS shared_targets
|
||||
)
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
file(READ "${RunCMake_TEST_BINARY_DIR}/sbom/mySbom/mySbom.spdx.json" content)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/../Sbom/TargetInMultipleSets-install-check.cmake)
|
||||
@@ -0,0 +1,3 @@
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/../Sbom/TargetInMultipleSets.cmake)
|
||||
|
||||
export(SBOM mySbom EXPORTS setA1 setA2)
|
||||
@@ -1,7 +1,7 @@
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/../Sbom/ApplicationTarget.cmake)
|
||||
|
||||
install(SBOM application_targets
|
||||
EXPORT application_targets
|
||||
EXPORTS application_targets
|
||||
FORMAT "spdx-3.0+json"
|
||||
DESTINATION .
|
||||
)
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,2 @@
|
||||
CMake Error at DuplicateSbom\.cmake:[0-9]+ \(install\):
|
||||
install SBOM command already specified for the file mySbom\.spdx\.json\.
|
||||
@@ -0,0 +1,4 @@
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/../Sbom/DuplicateSbom.cmake)
|
||||
|
||||
install(SBOM mySbom EXPORTS setA DESTINATION .)
|
||||
install(SBOM mySbom EXPORTS setA DESTINATION .)
|
||||
@@ -0,0 +1,2 @@
|
||||
file(READ "${RunCMake_TEST_INSTALL_DIR}/mySbom.spdx.json" content)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/../Sbom/EmptyNamespaceFallback-install-check.cmake)
|
||||
@@ -0,0 +1,4 @@
|
||||
CMake Warning \(author\) in CMakeLists\.txt:
|
||||
Target "libb" references target "liba", whose export does not use the
|
||||
standard namespace separator\. The dependency will be recorded by its bare
|
||||
target name without provenance\.
|
||||
@@ -0,0 +1,5 @@
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/../Sbom/EmptyNamespaceFallback.cmake)
|
||||
|
||||
install(EXPORT setA DESTINATION lib/cmake/A)
|
||||
install(EXPORT setB NAMESPACE B:: DESTINATION lib/cmake/B)
|
||||
install(SBOM mySbom EXPORTS setB DESTINATION .)
|
||||
@@ -14,6 +14,6 @@ install(
|
||||
)
|
||||
|
||||
install(SBOM interface_targets
|
||||
EXPORT interface_targets
|
||||
EXPORTS interface_targets
|
||||
DESTINATION .
|
||||
)
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/../Sbom/InstallExportPlusSbomSameSet.cmake)
|
||||
|
||||
install(EXPORT export_set_a NAMESPACE A:: DESTINATION lib/cmake/setA)
|
||||
install(SBOM mySbom EXPORTS export_set_a DESTINATION .)
|
||||
install(EXPORT export_set_b DESTINATION lib/cmake/setB)
|
||||
@@ -1,6 +1,6 @@
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/../Sbom/InterfaceTarget.cmake)
|
||||
|
||||
install(SBOM interface_targets
|
||||
EXPORT interface_targets
|
||||
EXPORTS interface_targets
|
||||
DESTINATION .
|
||||
)
|
||||
|
||||
@@ -2,6 +2,6 @@ include(${CMAKE_CURRENT_LIST_DIR}/../Sbom/MissingPackageNamespace.cmake)
|
||||
|
||||
install(SBOM test_targets
|
||||
VERSION "1.0.2"
|
||||
EXPORT test_targets
|
||||
EXPORTS test_targets
|
||||
DESTINATION .
|
||||
)
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,8 @@
|
||||
CMake Error in CMakeLists\.txt:
|
||||
Target "libb" references target "liba" that is in an export set which is
|
||||
exported multiple times with different namespaces: lib/cmake/A/setA\.cmake,
|
||||
lib/cmake/OldA/setA\.cmake\.
|
||||
|
||||
An SBOM cannot attribute a dependency exported in more than one export set
|
||||
or with more than one namespace\. Consider consolidating the exports of the
|
||||
"liba" target to a single export\.
|
||||
@@ -0,0 +1,5 @@
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/../Sbom/MultiNamespaceAmbiguity.cmake)
|
||||
|
||||
install(EXPORT setA NAMESPACE A:: DESTINATION lib/cmake/A)
|
||||
install(EXPORT setA NAMESPACE OldA:: DESTINATION lib/cmake/OldA)
|
||||
install(SBOM mySbom EXPORTS setB DESTINATION .)
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,7 @@
|
||||
CMake Error in CMakeLists\.txt:
|
||||
Target "libb" references target "liba" that is in multiple export sets:
|
||||
lib/cmake/A1/setA1\.cmake, lib/cmake/A2/setA2\.cmake\.
|
||||
|
||||
An SBOM cannot attribute a dependency exported in more than one export set
|
||||
or with more than one namespace\. Consider consolidating the exports of the
|
||||
"liba" target to a single export\.
|
||||
@@ -0,0 +1,5 @@
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/../Sbom/MultiSetAmbiguity.cmake)
|
||||
|
||||
install(EXPORT setA1 NAMESPACE A1:: DESTINATION lib/cmake/A1)
|
||||
install(EXPORT setA2 NAMESPACE A2:: DESTINATION lib/cmake/A2)
|
||||
install(SBOM mySbom EXPORTS setB DESTINATION .)
|
||||
@@ -0,0 +1,2 @@
|
||||
file(READ "${RunCMake_TEST_INSTALL_DIR}/mySbom.spdx.json" content)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/../Sbom/MultiSetSingleSbom-install-check.cmake)
|
||||
@@ -0,0 +1,5 @@
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/../Sbom/MultiSetSingleSbom.cmake)
|
||||
|
||||
install(EXPORT setA NAMESPACE A:: DESTINATION lib/cmake/A)
|
||||
install(EXPORT setB NAMESPACE B:: DESTINATION lib/cmake/B)
|
||||
install(SBOM mySbom EXPORTS setA setB DESTINATION .)
|
||||
@@ -1,2 +1,3 @@
|
||||
file(READ "${RunCMake_TEST_INSTALL_DIR}/test_targets.spdx.json" content)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/../Sbom/ProjectMetadata-install-check.cmake)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/../Sbom/ProjectMetadataExplicitAssertions.cmake)
|
||||
|
||||
@@ -5,7 +5,8 @@ install(
|
||||
DESCRIPTION "An eloquent description"
|
||||
LICENSE "BSD-3"
|
||||
HOMEPAGE_URL "www.example.com"
|
||||
PACKAGE_URL "https://example.com/test_targets.tar.gz"
|
||||
VERSION "1.3.4"
|
||||
EXPORT test_targets
|
||||
EXPORTS test_targets
|
||||
DESTINATION .
|
||||
)
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
file(READ "${RunCMake_TEST_INSTALL_DIR}/dog.spdx.json" content)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/../Sbom/ReferencesNonExportedTarget-install-check.cmake)
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,6 @@
|
||||
CMake Error in CMakeLists\.txt:
|
||||
Target "canine" references target "mammal" which has no
|
||||
install\(EXPORT\)/export\(EXPORT\) namespace and is not covered by any SBOM\.
|
||||
An SBOM cannot attribute this dependency\. Give "mammal" an
|
||||
install\(EXPORT\)/export\(EXPORT\) with a NAMESPACE, or include it in an
|
||||
install\(SBOM\)/export\(SBOM\)\.
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user