Coverage Report

Created: 2026-06-15 07:03

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
133
  bool NoteLinkedTarget(cmGeneratorTarget const* target,
134
                        std::string const& linkedName,
135
                        cmGeneratorTarget const* linkedTarget);
136
137
  bool AddTargetNamespace(std::string& input, cmGeneratorTarget const* target,
138
                          cmLocalGenerator const* lg);
139
140
  void ResolveTargetsInGeneratorExpression(std::string& input,
141
                                           cmGeneratorTarget const* target,
142
                                           cmLocalGenerator const* lg);
143
  void ResolveTargetsInGeneratorExpressions(std::string& input,
144
                                            cmGeneratorTarget const* target);
145
146
  bool PopulateInterfaceLinkLibrariesProperty(
147
    cmGeneratorTarget const* target,
148
    cmGeneratorExpression::PreprocessContext preprocessRule,
149
    ImportPropertyMap& properties);
150
151
  bool PopulateLinkLibrariesProperty(cmGeneratorTarget const* target,
152
                                     cmGeneratorExpression::PreprocessContext,
153
                                     ImportPropertyMap& properties);
154
155
  // Set at construction or via setters
156
  cmLocalGenerator* LocalGenerator = nullptr;
157
158
  // Inputs
159
  std::vector<cmExportSet*> ExportSets;
160
161
private:
162
  struct LinkInfo
163
  {
164
    std::string Package;
165
    std::string Component;
166
  };
167
168
  // Metadata
169
  std::string const PackageName;
170
  std::string const Namespace;
171
  std::string const PackageVersion;
172
  std::string const PackageDescription;
173
  std::string const PackageWebsite;
174
  std::string const PackageUrl;
175
  std::string const PackageLicense;
176
  cmSbomArguments::SbomFormat const PackageFormat;
177
178
  // Derived from inputs at generate time
179
  std::set<cmGeneratorTarget const*> SbomTargets;
180
181
  // Accumulated during generation
182
  std::map<std::string, LinkInfo> LinkTargets;
183
  std::map<std::string, cmPackageInformation> Requirements;
184
  std::vector<std::string> Configurations;
185
};