Coverage Report

Created: 2026-02-09 06:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/CMake/Source/cmGeneratorExpression.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 <map>
8
#include <memory>
9
#include <set>
10
#include <string>
11
#include <utility>
12
#include <vector>
13
14
#include <cm/string_view>
15
16
#include "cmListFileCache.h"
17
#include "cmLocalGenerator.h"
18
19
namespace cm {
20
namespace GenEx {
21
struct Context;
22
}
23
}
24
25
class cmake;
26
class cmCompiledGeneratorExpression;
27
class cmGeneratorTarget;
28
struct cmGeneratorExpressionDAGChecker;
29
struct cmGeneratorExpressionEvaluator;
30
31
/** \class cmGeneratorExpression
32
 * \brief Evaluate generate-time query expression syntax.
33
 *
34
 * cmGeneratorExpression instances are used by build system generator
35
 * implementations to evaluate the $<> generator expression syntax.
36
 * Generator expressions are evaluated just before the generate step
37
 * writes strings into the build system.  They have knowledge of the
38
 * build configuration which is not available at configure time.
39
 */
40
class cmGeneratorExpression
41
{
42
public:
43
  /** Construct. */
44
  cmGeneratorExpression(cmake& cmakeInstance,
45
                        cmListFileBacktrace backtrace = cmListFileBacktrace());
46
  ~cmGeneratorExpression();
47
48
  cmGeneratorExpression(cmGeneratorExpression const&) = delete;
49
  cmGeneratorExpression& operator=(cmGeneratorExpression const&) = delete;
50
51
  std::unique_ptr<cmCompiledGeneratorExpression> Parse(
52
    std::string input) const;
53
54
  static std::string Evaluate(
55
    std::string input, cmLocalGenerator const* lg, std::string const& config,
56
    cmGeneratorTarget const* headTarget = nullptr,
57
    cmGeneratorExpressionDAGChecker* dagChecker = nullptr,
58
    cmGeneratorTarget const* currentTarget = nullptr,
59
    std::string const& language = std::string());
60
61
  static bool ForbidGeneratorExpressions(
62
    cmGeneratorTarget const* target, std::string const& propertyName,
63
    std::string const& propertyValue, std::string& evaluatedValue,
64
    std::map<std::string, std::vector<std::string>>& allowList);
65
66
  static bool ForbidGeneratorExpressions(cmGeneratorTarget const* target,
67
                                         std::string const& propertyName,
68
                                         std::string const& propertyValue);
69
70
  enum PreprocessContext
71
  {
72
    StripAllGeneratorExpressions,
73
    BuildInterface,
74
    InstallInterface
75
  };
76
77
  static std::string Preprocess(cm::string_view input,
78
                                PreprocessContext context,
79
                                cm::string_view importPrefix = {});
80
81
  static std::string Collect(
82
    std::string const& input,
83
    std::map<std::string, std::vector<std::string>>& collected);
84
85
  static void Split(std::string const& input,
86
                    std::vector<std::string>& output);
87
88
  static cm::string_view::size_type Find(cm::string_view input);
89
90
  static bool IsValidTargetName(std::string const& input);
91
92
  static std::string StripEmptyListElements(std::string const& input);
93
94
  static bool StartsWithGeneratorExpression(std::string const& input)
95
2.35k
  {
96
2.35k
    return input.length() >= 2 && input[0] == '$' && input[1] == '<';
97
2.35k
  }
98
  static bool StartsWithGeneratorExpression(char const* input)
99
3.33M
  {
100
3.33M
    return input && input[0] == '$' && input[1] == '<';
101
3.33M
  }
102
103
  static void ReplaceInstallPrefix(std::string& input,
104
                                   std::string const& replacement);
105
106
private:
107
  cmake& CMakeInstance;
108
  cmListFileBacktrace Backtrace;
109
};
110
111
class cmCompiledGeneratorExpression
112
{
113
public:
114
  ~cmCompiledGeneratorExpression();
115
116
  cmCompiledGeneratorExpression(cmCompiledGeneratorExpression const&) = delete;
117
  cmCompiledGeneratorExpression& operator=(
118
    cmCompiledGeneratorExpression const&) = delete;
119
120
  std::string const& Evaluate(
121
    cmLocalGenerator const* lg, std::string const& config,
122
    cmGeneratorTarget const* headTarget = nullptr) const;
123
124
  std::string const& Evaluate(
125
    cm::GenEx::Context const& context,
126
    cmGeneratorExpressionDAGChecker* dagChecker,
127
    cmGeneratorTarget const* headTarget = nullptr,
128
    cmGeneratorTarget const* currentTarget = nullptr) const;
129
130
  /** Get set of targets found during evaluations.  */
131
  std::set<cmGeneratorTarget*> const& GetTargets() const
132
0
  {
133
0
    return this->DependTargets;
134
0
  }
135
136
  std::set<std::string> const& GetSeenTargetProperties() const
137
0
  {
138
0
    return this->SeenTargetProperties;
139
0
  }
140
141
  std::set<cmGeneratorTarget const*> const& GetAllTargetsSeen() const
142
0
  {
143
0
    return this->AllTargetsSeen;
144
0
  }
145
146
0
  std::string const& GetInput() const { return this->Input; }
147
148
0
  cmListFileBacktrace GetBacktrace() const { return this->Backtrace; }
149
  bool GetHadContextSensitiveCondition() const
150
0
  {
151
0
    return this->HadContextSensitiveCondition;
152
0
  }
153
  bool GetHadHeadSensitiveCondition() const
154
0
  {
155
0
    return this->HadHeadSensitiveCondition;
156
0
  }
157
  bool GetHadLinkLanguageSensitiveCondition() const
158
0
  {
159
0
    return this->HadLinkLanguageSensitiveCondition;
160
0
  }
161
  std::set<cmGeneratorTarget const*> GetSourceSensitiveTargets() const
162
0
  {
163
0
    return this->SourceSensitiveTargets;
164
0
  }
165
166
  void SetEvaluateForBuildsystem(bool eval)
167
0
  {
168
0
    this->EvaluateForBuildsystem = eval;
169
0
  }
170
171
0
  void SetQuiet(bool quiet) { this->Quiet = quiet; }
172
173
  void GetMaxLanguageStandard(cmGeneratorTarget const* tgt,
174
                              std::map<std::string, std::string>& mapping);
175
176
private:
177
  cmCompiledGeneratorExpression(cmake& cmakeInstance,
178
                                cmListFileBacktrace backtrace,
179
                                std::string input);
180
181
  friend class cmGeneratorExpression;
182
183
  cmListFileBacktrace Backtrace;
184
  std::vector<std::unique_ptr<cmGeneratorExpressionEvaluator>> Evaluators;
185
  std::string const Input;
186
  bool NeedsEvaluation;
187
  bool EvaluateForBuildsystem = false;
188
  bool Quiet = false;
189
190
  mutable std::set<cmGeneratorTarget*> DependTargets;
191
  mutable std::set<cmGeneratorTarget const*> AllTargetsSeen;
192
  mutable std::set<std::string> SeenTargetProperties;
193
  mutable std::map<cmGeneratorTarget const*,
194
                   std::map<std::string, std::string>>
195
    MaxLanguageStandard;
196
  mutable std::string Output;
197
  mutable bool HadContextSensitiveCondition = false;
198
  mutable bool HadHeadSensitiveCondition = false;
199
  mutable bool HadLinkLanguageSensitiveCondition = false;
200
  mutable std::set<cmGeneratorTarget const*> SourceSensitiveTargets;
201
};
202
203
class cmGeneratorExpressionInterpreter
204
{
205
public:
206
  cmGeneratorExpressionInterpreter(cmLocalGenerator const* localGenerator,
207
                                   std::string config,
208
                                   cmGeneratorTarget const* headTarget,
209
                                   std::string language = std::string())
210
0
    : GeneratorExpression(*localGenerator->GetCMakeInstance())
211
0
    , LocalGenerator(localGenerator)
212
0
    , Config(std::move(config))
213
0
    , HeadTarget(headTarget)
214
0
    , Language(std::move(language))
215
0
  {
216
0
  }
217
218
  cmGeneratorExpressionInterpreter(cmGeneratorExpressionInterpreter const&) =
219
    delete;
220
  cmGeneratorExpressionInterpreter& operator=(
221
    cmGeneratorExpressionInterpreter const&) = delete;
222
223
  std::string const& Evaluate(std::string expression,
224
                              std::string const& property);
225
226
protected:
227
  cmGeneratorExpression GeneratorExpression;
228
  std::unique_ptr<cmCompiledGeneratorExpression> CompiledGeneratorExpression;
229
  cmLocalGenerator const* LocalGenerator = nullptr;
230
  std::string Config;
231
  cmGeneratorTarget const* HeadTarget = nullptr;
232
  std::string Language;
233
};