/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 <unordered_map> |
12 | | #include <utility> |
13 | | #include <vector> |
14 | | |
15 | | #include <cm/string_view> |
16 | | |
17 | | #include "cmListFileCache.h" |
18 | | #include "cmLocalGenerator.h" |
19 | | |
20 | | namespace cm { |
21 | | namespace GenEx { |
22 | | struct Context; |
23 | | } |
24 | | } |
25 | | |
26 | | class cmake; |
27 | | class cmCompiledGeneratorExpression; |
28 | | class cmGeneratorTarget; |
29 | | struct cmGeneratorExpressionDAGChecker; |
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 | 26.2k | { |
96 | 26.2k | return input.length() >= 2 && input[0] == '$' && input[1] == '<'; |
97 | 26.2k | } |
98 | | static bool StartsWithGeneratorExpression(char const* input) |
99 | 3.58M | { |
100 | 3.58M | return input && input[0] == '$' && input[1] == '<'; |
101 | 3.58M | } |
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 cmGeneratorExpressionParseCache |
112 | | * \brief Cache of parsed generator expressions, keyed by their input. |
113 | | * |
114 | | * Parsing depends only on the input string, so all |
115 | | * cmCompiledGeneratorExpression instances compiled from the same input |
116 | | * share one immutable parse tree. Each cmCompiledGeneratorExpression |
117 | | * keeps its own evaluation state. |
118 | | */ |
119 | | class cmGeneratorExpressionParseCache |
120 | | { |
121 | | public: |
122 | | struct Entry; |
123 | | |
124 | | cmGeneratorExpressionParseCache(); |
125 | | ~cmGeneratorExpressionParseCache(); |
126 | | |
127 | | cmGeneratorExpressionParseCache(cmGeneratorExpressionParseCache const&) = |
128 | | delete; |
129 | | cmGeneratorExpressionParseCache& operator=( |
130 | | cmGeneratorExpressionParseCache const&) = delete; |
131 | | |
132 | | /** Get the parse tree of the input, or nullptr if the input does not |
133 | | contain any generator expression. */ |
134 | | std::shared_ptr<Entry const> Get(std::string const& input); |
135 | | |
136 | | /** Forget all parse trees. Compiled expressions keep the parse trees |
137 | | they use alive. */ |
138 | 0 | void Clear() { this->Entries.clear(); } |
139 | | |
140 | | private: |
141 | | // Keys refer to the input owned by the entry, so it is not stored twice. |
142 | | std::unordered_map<cm::string_view, std::shared_ptr<Entry const>> Entries; |
143 | | }; |
144 | | |
145 | | class cmCompiledGeneratorExpression |
146 | | { |
147 | | public: |
148 | | ~cmCompiledGeneratorExpression(); |
149 | | |
150 | | cmCompiledGeneratorExpression(cmCompiledGeneratorExpression const&) = delete; |
151 | | cmCompiledGeneratorExpression& operator=( |
152 | | cmCompiledGeneratorExpression const&) = delete; |
153 | | |
154 | | std::string const& Evaluate( |
155 | | cmLocalGenerator const* lg, std::string const& config, |
156 | | cmGeneratorTarget const* headTarget = nullptr) const; |
157 | | |
158 | | std::string const& Evaluate( |
159 | | cm::GenEx::Context const& context, |
160 | | cmGeneratorExpressionDAGChecker* dagChecker, |
161 | | cmGeneratorTarget const* headTarget = nullptr, |
162 | | cmGeneratorTarget const* currentTarget = nullptr) const; |
163 | | |
164 | | /** Get set of targets found during evaluations. */ |
165 | | std::set<cmGeneratorTarget*> const& GetTargets() const |
166 | 552 | { |
167 | 552 | return this->DependTargets; |
168 | 552 | } |
169 | | |
170 | | std::set<std::string> const& GetSeenTargetProperties() const |
171 | 11.3k | { |
172 | 11.3k | return this->SeenTargetProperties; |
173 | 11.3k | } |
174 | | |
175 | | std::set<cmGeneratorTarget const*> const& GetAllTargetsSeen() const |
176 | 552 | { |
177 | 552 | return this->AllTargetsSeen; |
178 | 552 | } |
179 | | |
180 | 0 | std::string const& GetInput() const { return this->Input; } |
181 | | |
182 | 43.2k | cmListFileBacktrace GetBacktrace() const { return this->Backtrace; } |
183 | | bool GetHadContextSensitiveCondition() const |
184 | 40.8k | { |
185 | 40.8k | return this->HadContextSensitiveCondition; |
186 | 40.8k | } |
187 | | bool GetHadHeadSensitiveCondition() const |
188 | 40.4k | { |
189 | 40.4k | return this->HadHeadSensitiveCondition; |
190 | 40.4k | } |
191 | | bool GetHadLinkLanguageSensitiveCondition() const |
192 | 40.4k | { |
193 | 40.4k | return this->HadLinkLanguageSensitiveCondition; |
194 | 40.4k | } |
195 | | std::set<cmGeneratorTarget const*> GetSourceSensitiveTargets() const |
196 | 552 | { |
197 | 552 | return this->SourceSensitiveTargets; |
198 | 552 | } |
199 | | |
200 | | void SetEvaluateForBuildsystem(bool eval) |
201 | 46.7k | { |
202 | 46.7k | this->EvaluateForBuildsystem = eval; |
203 | 46.7k | } |
204 | | |
205 | 8.98k | void SetQuiet(bool quiet) { this->Quiet = quiet; } |
206 | | |
207 | | void GetMaxLanguageStandard(cmGeneratorTarget const* tgt, |
208 | | std::map<std::string, std::string>& mapping); |
209 | | |
210 | | private: |
211 | | cmCompiledGeneratorExpression(cmake& cmakeInstance, |
212 | | cmListFileBacktrace backtrace, |
213 | | std::string input); |
214 | | |
215 | | friend class cmGeneratorExpression; |
216 | | |
217 | | cmListFileBacktrace Backtrace; |
218 | | std::string const Input; |
219 | | // Null if the input does not contain any generator expression. |
220 | | std::shared_ptr<cmGeneratorExpressionParseCache::Entry const> Parsed; |
221 | | bool EvaluateForBuildsystem = false; |
222 | | bool Quiet = false; |
223 | | |
224 | | mutable std::set<cmGeneratorTarget*> DependTargets; |
225 | | mutable std::set<cmGeneratorTarget const*> AllTargetsSeen; |
226 | | mutable std::set<std::string> SeenTargetProperties; |
227 | | mutable std::map<cmGeneratorTarget const*, |
228 | | std::map<std::string, std::string>> |
229 | | MaxLanguageStandard; |
230 | | mutable std::string Output; |
231 | | mutable bool HadContextSensitiveCondition = false; |
232 | | mutable bool HadHeadSensitiveCondition = false; |
233 | | mutable bool HadLinkLanguageSensitiveCondition = false; |
234 | | mutable std::set<cmGeneratorTarget const*> SourceSensitiveTargets; |
235 | | }; |
236 | | |
237 | | class cmGeneratorExpressionInterpreter |
238 | | { |
239 | | public: |
240 | | cmGeneratorExpressionInterpreter(cmLocalGenerator const* localGenerator, |
241 | | std::string config, |
242 | | cmGeneratorTarget const* headTarget, |
243 | | std::string language = std::string()) |
244 | 375 | : GeneratorExpression(*localGenerator->GetCMakeInstance()) |
245 | 375 | , LocalGenerator(localGenerator) |
246 | 375 | , Config(std::move(config)) |
247 | 375 | , HeadTarget(headTarget) |
248 | 375 | , Language(std::move(language)) |
249 | 375 | { |
250 | 375 | } |
251 | | |
252 | | cmGeneratorExpressionInterpreter(cmGeneratorExpressionInterpreter const&) = |
253 | | delete; |
254 | | cmGeneratorExpressionInterpreter& operator=( |
255 | | cmGeneratorExpressionInterpreter const&) = delete; |
256 | | |
257 | | std::string const& Evaluate(std::string expression, |
258 | | std::string const& property); |
259 | | |
260 | | protected: |
261 | | cmGeneratorExpression GeneratorExpression; |
262 | | std::unique_ptr<cmCompiledGeneratorExpression> CompiledGeneratorExpression; |
263 | | cmLocalGenerator const* LocalGenerator = nullptr; |
264 | | std::string Config; |
265 | | cmGeneratorTarget const* HeadTarget = nullptr; |
266 | | std::string Language; |
267 | | }; |