Coverage Report

Created: 2026-07-14 07:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/CMake/Source/cmSbomBuilder.h
Line
Count
Source
1
/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
2
   file LICENSE.rst or https://cmake.org/licensing for details. */
3
#pragma once
4
5
#include "cmConfigure.h" // IWYU pragma: keep
6
7
#include <iosfwd>
8
#include <map>
9
#include <set>
10
#include <string>
11
#include <vector>
12
13
#include "cmExportFileGenerator.h"
14
#include "cmFindPackageStack.h"
15
#include "cmGeneratorExpression.h"
16
#include "cmSbomArguments.h"
17
18
class cmExportSet;
19
class cmGeneratorTarget;
20
class cmLocalGenerator;
21
struct cmSbomDocument;
22
struct cmSpdxDocument;
23
struct cmSpdxPackage;
24
struct cmSpdxCreationInfo;
25
26
/** \class cmSbomBuilder
27
 *  \brief Abstract base for SBOM document generators.
28
 *
29
 *  Concrete leaves (cmBuildSbomBuilder, cmInstallSbomBuilder) supply two
30
 *  pure virtuals:
31
 *
32
 *  - Generate(): selects the generator-expression preprocess context
33
 *    (BuildInterface vs InstallInterface) and delegates to the shared
34
 *    GenerateForTargets() body.
35
 *  - FindExportInfoFor(): consults the mode's export map (build-tree vs
36
 *    install-tree) to resolve cross-export references.
37
 *
38
 *  All shared SPDX assembly, link-graph walking, and serialization lives
39
 *  here so that the leaves stay trivial.
40
 */
41
class cmSbomBuilder
42
{
43
public:
44
0
  virtual ~cmSbomBuilder() = default;
45
46
  /** Compute phase: wire the local generator, run Compute() on the owned
47
   *  export sets, and populate the SbomTargets cache so peer SBOMs can
48
   *  query CoversTarget() before any Generate() runs. */
49
  void Compute(cmLocalGenerator* lg);
50
51
  /** Produce the SBOM document on `os`.  Implementations select their own
52
   *  target set (via CollectTargets) and preprocess context. */
53
  virtual bool Generate(std::ostream& os, std::string const& config) = 0;
54
55
  /** Identifier this SBOM publishes itself as (the SPDX document name and
56
   *  the namespace under which other SBOMs refer to its contents). */
57
0
  std::string const& GetPackageName() const { return this->PackageName; }
58
59
  /** True if `target` is one of the targets this SBOM directly describes. */
60
  bool CoversTarget(cmGeneratorTarget const* target) const;
61
  bool CoversExportSet(cmExportSet const* set) const;
62
63
  void AddConfiguration(std::string const& config)
64
0
  {
65
0
    this->Configurations.push_back(config);
66
0
  }
67
68
  /** Names of peer SBOMs (same build/install mode) that cover a target.
69
   *  Used by NoteLinkedTarget to attribute a cross-reference when no
70
   *  install(export) namespace is available.  Sorted alphabetically. */
71
  struct SbomInfo
72
  {
73
    std::vector<std::string> Packages;
74
  };
75
76
protected:
77
  cmSbomBuilder(cmSbomArguments args, std::vector<cmExportSet*> exportSets,
78
                cmLocalGenerator* lg);
79
80
  /** Mode-specific: where does `target` appear in the project's exports?
81
   *  Build leaves consult cmGlobalGenerator::FindBuildExportInfo;
82
   *  install leaves consult cmGlobalGenerator::FindInstallExportInfo. */
83
  virtual cmExportFileGenerator::ExportInfo FindExportInfoFor(
84
    cmGeneratorTarget const* target) const = 0;
85
86
  /** Mode-specific: which peer SBOMs cover `target`?
87
   *  Build leaves consult cmGlobalGenerator::FindBuildSbomInfo;
88
   *  install leaves consult cmGlobalGenerator::FindInstallSbomInfo. */
89
  virtual SbomInfo FindSbomInfoFor(cmGeneratorTarget const* target) const = 0;
90
91
  /** The set of targets the SBOM directly describes — derived from the
92
   *  associated export sets. */
93
  std::set<cmGeneratorTarget const*> CollectTargets() const;
94
95
  /** Generate an sbom for the targets in this->SbomTargets. Each leaf class
96
   * calls this internally */
97
  bool GenerateForTargets(
98
    std::ostream& os, std::string const& config,
99
    cmGeneratorExpression::PreprocessContext preprocessContext);
100
101
  using ImportPropertyMap = std::map<std::string, std::string>;
102
103
  struct TargetProperties
104
  {
105
    cmSpdxPackage const* Package;
106
    cmGeneratorTarget const* Target;
107
    ImportPropertyMap Properties;
108
  };
109
110
  void WriteSbom(cmSbomDocument& doc, std::ostream& os) const;
111
112
  cmSpdxCreationInfo GenerateCreationInfo() const;
113
  cmSpdxDocument GenerateSbom(cmSpdxCreationInfo const* ci) const;
114
  cmSpdxPackage GenerateImportTarget(cmSpdxCreationInfo const* ci,
115
                                     cmGeneratorTarget const* target) const;
116
117
  bool AddPackageInformation(cmSpdxPackage& artifact, std::string const& name,
118
                             cmPackageInformation const& package) const;
119
120
  bool GenerateProperties(cmSbomDocument& doc, cmSpdxDocument* project,
121
                          cmSpdxCreationInfo const* ci,
122
                          TargetProperties const& current,
123
                          std::vector<TargetProperties> const& allTargets,
124
                          std::string const& config) const;
125
126
  bool GenerateLinkProperties(cmSbomDocument& doc, cmSpdxDocument* project,
127
                              cmSpdxCreationInfo const* ci,
128
                              std::string const& libraries,
129
                              TargetProperties const& current,
130
                              std::vector<TargetProperties> const& allTargets,
131
                              std::string const& config) const;
132
  bool GenerateMetaProperties(cmSbomDocument& doc, cmSpdxDocument* project,
133
                              cmSpdxCreationInfo const* ci,
134
                              TargetProperties const& current) const;
135
136
  bool NoteLinkedTarget(cmGeneratorTarget const* target,
137
                        std::string const& linkedName,
138
                        cmGeneratorTarget const* linkedTarget);
139
140
  bool AddTargetNamespace(std::string& input, cmGeneratorTarget const* target,
141
                          cmLocalGenerator const* lg);
142
143
  void ResolveTargetsInGeneratorExpression(std::string& input,
144
                                           cmGeneratorTarget const* target,
145
                                           cmLocalGenerator const* lg);
146
  void ResolveTargetsInGeneratorExpressions(std::string& input,
147
                                            cmGeneratorTarget const* target);
148
149
  bool PopulateInterfaceLinkLibrariesProperty(
150
    cmGeneratorTarget const* target,
151
    cmGeneratorExpression::PreprocessContext preprocessRule,
152
    ImportPropertyMap& properties);
153
154
  bool PopulateLinkLibrariesProperty(cmGeneratorTarget const* target,
155
                                     cmGeneratorExpression::PreprocessContext,
156
                                     ImportPropertyMap& properties);
157
158
  // Set at construction or via setters
159
  cmLocalGenerator* LocalGenerator = nullptr;
160
161
  // Inputs
162
  std::vector<cmExportSet*> ExportSets;
163
164
private:
165
  struct LinkInfo
166
  {
167
    std::string Package;
168
    std::string Component;
169
    std::string License;
170
  };
171
172
  // Metadata
173
  std::string const PackageName;
174
  std::string const Namespace;
175
  std::string const PackageVersion;
176
  std::string const PackageDescription;
177
  std::string const PackageWebsite;
178
  std::string const PackageUrl;
179
  std::string const DataLicense;
180
  std::string const DefaultLicense;
181
  cmSbomArguments::SbomFormat const PackageFormat;
182
183
  // Derived from inputs at generate time
184
  std::set<cmGeneratorTarget const*> SbomTargets;
185
186
  // Accumulated during generation
187
  std::map<std::string, LinkInfo> LinkTargets;
188
  std::map<std::string, cmPackageInformation> Requirements;
189
  std::vector<std::string> Configurations;
190
191
  // Targets for which license data has been generated
192
  mutable std::set<std::string> GeneratedLinkLicenses;
193
};