/src/CMake/Source/cmGeneratorFileSet.cxx
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 | | #include "cmGeneratorFileSet.h" |
4 | | |
5 | | #include <algorithm> |
6 | | #include <map> |
7 | | #include <unordered_map> |
8 | | #include <unordered_set> |
9 | | #include <utility> |
10 | | #include <vector> |
11 | | |
12 | | #include <cm/memory> |
13 | | #include <cm/optional> |
14 | | #include <cm/string_view> |
15 | | #include <cmext/string_view> |
16 | | |
17 | | #include "cmAlgorithms.h" |
18 | | #include "cmEvaluatedTargetProperty.h" |
19 | | #include "cmFileSet.h" |
20 | | #include "cmGenExContext.h" |
21 | | #include "cmGeneratorExpression.h" |
22 | | #include "cmGeneratorExpressionDAGChecker.h" |
23 | | #include "cmGeneratorTarget.h" |
24 | | #include "cmList.h" |
25 | | #include "cmListFileCache.h" |
26 | | #include "cmLocalGenerator.h" |
27 | | #include "cmMakefile.h" |
28 | | #include "cmMessageType.h" |
29 | | #include "cmStringAlgorithms.h" |
30 | | #include "cmSystemTools.h" |
31 | | #include "cmake.h" |
32 | | |
33 | | class cmLinkItem; |
34 | | |
35 | | namespace { |
36 | | class FileSetPropertyEntry : public cm::TargetPropertyEntry |
37 | | { |
38 | | public: |
39 | | FileSetPropertyEntry( |
40 | | std::vector<std::string> dirs, bool contextSensitiveDirs, |
41 | | std::unique_ptr<cmCompiledGeneratorExpression> const& cge, |
42 | | cmGeneratorFileSet const* fileSet, cmLinkItem const& item = NoLinkItem) |
43 | 0 | : cm::TargetPropertyEntry(item) |
44 | 0 | , BaseDirs(std::move(dirs)) |
45 | 0 | , ContextSensitiveDirs(contextSensitiveDirs) |
46 | 0 | , Cge(cge) |
47 | 0 | , FileSet(fileSet) |
48 | 0 | { |
49 | 0 | } |
50 | | |
51 | | static std::unique_ptr<cm::TargetPropertyEntry> CreateFileSetEntry( |
52 | | std::vector<std::string> dirs, bool contextSensitiveDirs, |
53 | | std::unique_ptr<cmCompiledGeneratorExpression> const& cge, |
54 | | cmGeneratorFileSet const* fileSet, cmLinkItem const& item = NoLinkItem) |
55 | 0 | { |
56 | 0 | return cm::make_unique<FileSetPropertyEntry>( |
57 | 0 | std::move(dirs), contextSensitiveDirs, cge, fileSet, item); |
58 | 0 | } |
59 | | |
60 | | std::string const& Evaluate( |
61 | | cm::GenEx::Context const& context, cmGeneratorTarget const* headTarget, |
62 | | cmGeneratorExpressionDAGChecker* dagChecker) const override |
63 | 0 | { |
64 | 0 | std::map<std::string, std::vector<std::string>> filesPerDir; |
65 | 0 | this->FileSet->EvaluateFileEntry(this->BaseDirs, filesPerDir, this->Cge, |
66 | 0 | context, headTarget, dagChecker); |
67 | |
|
68 | 0 | std::vector<std::string> files; |
69 | 0 | for (auto const& it : filesPerDir) { |
70 | 0 | files.insert(files.end(), it.second.begin(), it.second.end()); |
71 | 0 | } |
72 | |
|
73 | 0 | this->Value = cmList::to_string(files); |
74 | 0 | return Value; |
75 | 0 | } |
76 | | |
77 | | cmListFileBacktrace GetBacktrace() const override |
78 | 0 | { |
79 | 0 | return this->Cge->GetBacktrace(); |
80 | 0 | } |
81 | | |
82 | | std::string const& GetInput() const override |
83 | 0 | { |
84 | 0 | return this->Cge->GetInput(); |
85 | 0 | } |
86 | | |
87 | | bool GetHadContextSensitiveCondition() const override |
88 | 0 | { |
89 | 0 | return this->ContextSensitiveDirs || |
90 | 0 | this->Cge->GetHadContextSensitiveCondition(); |
91 | 0 | } |
92 | | |
93 | | private: |
94 | | std::vector<std::string> const BaseDirs; |
95 | | bool const ContextSensitiveDirs; |
96 | | std::unique_ptr<cmCompiledGeneratorExpression> const& Cge; |
97 | | cmGeneratorFileSet const* FileSet; |
98 | | mutable std::string Value; |
99 | | }; |
100 | | |
101 | | void CreatePropertyGeneratorExpressions( |
102 | | cmake& cmakeInstance, cmBTStringRange entries, |
103 | | std::vector<std::unique_ptr<cm::TargetPropertyEntry>>& items) |
104 | 35.5k | { |
105 | 35.5k | for (auto const& entry : entries) { |
106 | 0 | items.emplace_back( |
107 | 0 | cm::TargetPropertyEntry::Create(cmakeInstance, entry, false)); |
108 | 0 | } |
109 | 35.5k | } |
110 | | |
111 | | enum class OptionsParse |
112 | | { |
113 | | None, |
114 | | Shell |
115 | | }; |
116 | | |
117 | | std::vector<BT<std::string>> ProcessOptions( |
118 | | cm::EvaluatedTargetPropertyEntries const& entries, |
119 | | OptionsParse parse = OptionsParse::None) |
120 | 0 | { |
121 | 0 | std::vector<BT<std::string>> options; |
122 | 0 | std::unordered_set<std::string> uniqueOptions; |
123 | |
|
124 | 0 | for (cm::EvaluatedTargetPropertyEntry const& entry : entries.Entries) { |
125 | 0 | for (std::string const& opt : entry.Values) { |
126 | 0 | if (uniqueOptions.insert(opt).second) { |
127 | 0 | if (parse == OptionsParse::Shell && |
128 | 0 | cmHasLiteralPrefix(opt, "SHELL:")) { |
129 | 0 | std::vector<std::string> tmp; |
130 | 0 | cmSystemTools::ParseUnixCommandLine(opt.c_str() + 6, tmp); |
131 | 0 | for (std::string& o : tmp) { |
132 | 0 | options.emplace_back(std::move(o), entry.Backtrace); |
133 | 0 | } |
134 | 0 | } else { |
135 | 0 | options.emplace_back(opt, entry.Backtrace); |
136 | 0 | } |
137 | 0 | } |
138 | 0 | } |
139 | 0 | } |
140 | 0 | return options; |
141 | 0 | } |
142 | | std::vector<BT<std::string>> ProcessIncludes( |
143 | | cmGeneratorTarget const* target, std::string const& fileSetName, |
144 | | cm::string_view property, cm::EvaluatedTargetPropertyEntries& entries) |
145 | 0 | { |
146 | 0 | std::vector<BT<std::string>> includes; |
147 | 0 | std::unordered_set<std::string> uniqueIncludes; |
148 | |
|
149 | 0 | for (cm::EvaluatedTargetPropertyEntry& entry : entries.Entries) { |
150 | 0 | for (std::string& include : entry.Values) { |
151 | 0 | if (!cmValue::IsOff(include)) { |
152 | 0 | cmSystemTools::ConvertToUnixSlashes(include); |
153 | 0 | } |
154 | |
|
155 | 0 | if (!cmSystemTools::FileIsFullPath(include)) { |
156 | 0 | target->GetLocalGenerator()->IssueMessage( |
157 | 0 | MessageType::FATAL_ERROR, |
158 | 0 | cmStrCat("File set \"", fileSetName, "\" from the target \"", |
159 | 0 | target->GetName(), "\" contains relative path in its ", |
160 | 0 | property, ":\n \"", include, '"')); |
161 | 0 | return includes; |
162 | 0 | } |
163 | | |
164 | 0 | if (uniqueIncludes.insert(include).second) { |
165 | 0 | includes.emplace_back(include, entry.Backtrace); |
166 | 0 | } |
167 | 0 | } |
168 | 0 | } |
169 | 0 | return includes; |
170 | 0 | } |
171 | | } |
172 | | |
173 | | // |
174 | | // Class cmGeneratorFileSet |
175 | | // |
176 | | cmGeneratorFileSet::cmGeneratorFileSet( |
177 | | cmGeneratorTarget const* target, cmFileSet const* fileSet, |
178 | | cm::FileSetMetadata::FileSetDomain domain) |
179 | 5.92k | : Target(target) |
180 | 5.92k | , FileSet(fileSet) |
181 | 5.92k | , Domain(domain) |
182 | 5.92k | { |
183 | 5.92k | auto& cmake = *target->GetLocalGenerator()->GetCMakeInstance(); |
184 | | |
185 | 5.92k | CreatePropertyGeneratorExpressions(cmake, fileSet->GetIncludeDirectories(), |
186 | 5.92k | this->IncludeDirectories); |
187 | 5.92k | CreatePropertyGeneratorExpressions(cmake, |
188 | 5.92k | fileSet->GetInterfaceIncludeDirectories(), |
189 | 5.92k | this->InterfaceIncludeDirectories); |
190 | | |
191 | 5.92k | CreatePropertyGeneratorExpressions(cmake, fileSet->GetCompileOptions(), |
192 | 5.92k | this->CompileOptions); |
193 | 5.92k | CreatePropertyGeneratorExpressions(cmake, |
194 | 5.92k | fileSet->GetInterfaceCompileOptions(), |
195 | 5.92k | this->InterfaceCompileOptions); |
196 | | |
197 | 5.92k | CreatePropertyGeneratorExpressions(cmake, fileSet->GetCompileDefinitions(), |
198 | 5.92k | this->CompileDefinitions); |
199 | 5.92k | CreatePropertyGeneratorExpressions(cmake, |
200 | 5.92k | fileSet->GetInterfaceCompileDefinitions(), |
201 | 5.92k | this->InterfaceCompileDefinitions); |
202 | 5.92k | } |
203 | | |
204 | | std::string const& cmGeneratorFileSet::GetName() const |
205 | 0 | { |
206 | 0 | return this->FileSet->GetName(); |
207 | 0 | } |
208 | | std::string const& cmGeneratorFileSet::GetType() const |
209 | 5.92k | { |
210 | 5.92k | return this->FileSet->GetType(); |
211 | 5.92k | } |
212 | | cm::FileSetMetadata::Visibility cmGeneratorFileSet::GetVisibility() const |
213 | 0 | { |
214 | 0 | return this->FileSet->GetVisibility(); |
215 | 0 | } |
216 | | |
217 | | bool cmGeneratorFileSet::IsForSelf() const |
218 | 0 | { |
219 | 0 | return this->FileSet->IsForSelf(); |
220 | 0 | } |
221 | | bool cmGeneratorFileSet::IsForInterface() const |
222 | 0 | { |
223 | 0 | return this->FileSet->IsForInterface(); |
224 | 0 | } |
225 | | bool cmGeneratorFileSet::CanBeIncluded() const |
226 | 0 | { |
227 | 0 | return this->FileSet->CanBeIncluded(); |
228 | 0 | } |
229 | | |
230 | | cmValue cmGeneratorFileSet::GetProperty(std::string const& prop) const |
231 | 535 | { |
232 | 535 | return this->FileSet->GetProperty(prop); |
233 | 535 | } |
234 | | |
235 | | std::vector<BT<std::string>> cmGeneratorFileSet::GetIncludeDirectories( |
236 | | std::string const& config, std::string const& lang) const |
237 | 0 | { |
238 | 0 | ConfigAndLanguage cacheKey(config, lang); |
239 | 0 | { |
240 | 0 | auto it = this->IncludeDirectoriesCache.find(cacheKey); |
241 | 0 | if (it != this->IncludeDirectoriesCache.end()) { |
242 | 0 | return it->second; |
243 | 0 | } |
244 | 0 | } |
245 | | |
246 | 0 | cm::GenEx::Context context(this->Target->GetLocalGenerator(), config, lang); |
247 | 0 | cmGeneratorExpressionDAGChecker dagChecker{ |
248 | 0 | this->Target, "INCLUDE_DIRECTORIES", nullptr, nullptr, context, |
249 | 0 | }; |
250 | |
|
251 | 0 | cm::EvaluatedTargetPropertyEntries entries = |
252 | 0 | cm::EvaluateTargetPropertyEntries(this->Target, context, &dagChecker, |
253 | 0 | this->IncludeDirectories); |
254 | 0 | auto includes = ProcessIncludes(this->Target, this->GetName(), |
255 | 0 | "INCLUDE_DIRECTORIES"_s, entries); |
256 | 0 | this->IncludeDirectoriesCache.emplace(cacheKey, includes); |
257 | |
|
258 | 0 | return includes; |
259 | 0 | } |
260 | | std::vector<BT<std::string>> |
261 | | cmGeneratorFileSet::GetInterfaceIncludeDirectories( |
262 | | std::string const& config, std::string const& lang) const |
263 | 0 | { |
264 | 0 | ConfigAndLanguage cacheKey(config, lang); |
265 | 0 | { |
266 | 0 | auto it = this->InterfaceIncludeDirectoriesCache.find(cacheKey); |
267 | 0 | if (it != this->InterfaceIncludeDirectoriesCache.end()) { |
268 | 0 | return it->second; |
269 | 0 | } |
270 | 0 | } |
271 | | |
272 | 0 | cm::GenEx::Context context(this->Target->GetLocalGenerator(), config, lang); |
273 | 0 | cmGeneratorExpressionDAGChecker dagChecker{ |
274 | 0 | this->Target, "INCLUDE_DIRECTORIES", nullptr, nullptr, context, |
275 | 0 | }; |
276 | |
|
277 | 0 | cm::EvaluatedTargetPropertyEntries entries = |
278 | 0 | cm::EvaluateTargetPropertyEntries(this->Target, context, &dagChecker, |
279 | 0 | this->InterfaceIncludeDirectories); |
280 | 0 | auto includes = ProcessIncludes(this->Target, this->GetName(), |
281 | 0 | "INTERFACE_INCLUDE_DIRECTORIES"_s, entries); |
282 | 0 | this->InterfaceIncludeDirectoriesCache.emplace(cacheKey, includes); |
283 | |
|
284 | 0 | return includes; |
285 | 0 | } |
286 | | |
287 | | std::vector<BT<std::string>> cmGeneratorFileSet::GetCompileOptions( |
288 | | std::string const& config, std::string const& language) const |
289 | 0 | { |
290 | 0 | ConfigAndLanguage cacheKey(config, language); |
291 | 0 | { |
292 | 0 | auto it = this->CompileOptionsCache.find(cacheKey); |
293 | 0 | if (it != this->CompileOptionsCache.end()) { |
294 | 0 | return it->second; |
295 | 0 | } |
296 | 0 | } |
297 | | |
298 | 0 | cm::GenEx::Context context(this->Target->GetLocalGenerator(), config, |
299 | 0 | language); |
300 | 0 | cmGeneratorExpressionDAGChecker dagChecker{ |
301 | 0 | this->Target, "COMPILE_OPTIONS", nullptr, nullptr, context, |
302 | 0 | }; |
303 | |
|
304 | 0 | cm::EvaluatedTargetPropertyEntries entries = |
305 | 0 | cm::EvaluateTargetPropertyEntries(this->Target, context, &dagChecker, |
306 | 0 | this->CompileOptions); |
307 | 0 | auto options = ProcessOptions(entries, OptionsParse::Shell); |
308 | 0 | this->CompileOptionsCache.emplace(cacheKey, options); |
309 | |
|
310 | 0 | return options; |
311 | 0 | } |
312 | | std::vector<BT<std::string>> cmGeneratorFileSet::GetInterfaceCompileOptions( |
313 | | std::string const& config, std::string const& language) const |
314 | 0 | { |
315 | 0 | ConfigAndLanguage cacheKey(config, language); |
316 | 0 | { |
317 | 0 | auto it = this->InterfaceCompileOptionsCache.find(cacheKey); |
318 | 0 | if (it != this->InterfaceCompileOptionsCache.end()) { |
319 | 0 | return it->second; |
320 | 0 | } |
321 | 0 | } |
322 | | |
323 | 0 | cm::GenEx::Context context(this->Target->GetLocalGenerator(), config, |
324 | 0 | language); |
325 | 0 | cmGeneratorExpressionDAGChecker dagChecker{ |
326 | 0 | this->Target, "COMPILE_OPTIONS", nullptr, nullptr, context, |
327 | 0 | }; |
328 | |
|
329 | 0 | cm::EvaluatedTargetPropertyEntries entries = |
330 | 0 | cm::EvaluateTargetPropertyEntries(this->Target, context, &dagChecker, |
331 | 0 | this->InterfaceCompileOptions); |
332 | 0 | auto options = ProcessOptions(entries, OptionsParse::Shell); |
333 | 0 | this->InterfaceCompileOptionsCache.emplace(cacheKey, options); |
334 | |
|
335 | 0 | return options; |
336 | 0 | } |
337 | | |
338 | | std::vector<BT<std::string>> cmGeneratorFileSet::GetCompileDefinitions( |
339 | | std::string const& config, std::string const& language) const |
340 | 0 | { |
341 | 0 | ConfigAndLanguage cacheKey(config, language); |
342 | 0 | { |
343 | 0 | auto it = this->CompileDefinitionsCache.find(cacheKey); |
344 | 0 | if (it != this->CompileDefinitionsCache.end()) { |
345 | 0 | return it->second; |
346 | 0 | } |
347 | 0 | } |
348 | | |
349 | 0 | cm::GenEx::Context context(this->Target->GetLocalGenerator(), config, |
350 | 0 | language); |
351 | 0 | cmGeneratorExpressionDAGChecker dagChecker{ |
352 | 0 | this->Target, "COMPILE_DEFINITIONS", nullptr, nullptr, context, |
353 | 0 | }; |
354 | |
|
355 | 0 | cm::EvaluatedTargetPropertyEntries entries = |
356 | 0 | cm::EvaluateTargetPropertyEntries(this->Target, context, &dagChecker, |
357 | 0 | this->CompileDefinitions); |
358 | 0 | auto defines = ProcessOptions(entries); |
359 | 0 | this->CompileDefinitionsCache.emplace(cacheKey, defines); |
360 | |
|
361 | 0 | return defines; |
362 | 0 | } |
363 | | std::vector<BT<std::string>> |
364 | | cmGeneratorFileSet::GetInterfaceCompileDefinitions( |
365 | | std::string const& config, std::string const& language) const |
366 | 0 | { |
367 | 0 | ConfigAndLanguage cacheKey(config, language); |
368 | 0 | { |
369 | 0 | auto it = this->InterfaceCompileDefinitionsCache.find(cacheKey); |
370 | 0 | if (it != this->InterfaceCompileDefinitionsCache.end()) { |
371 | 0 | return it->second; |
372 | 0 | } |
373 | 0 | } |
374 | | |
375 | 0 | cm::GenEx::Context context(this->Target->GetLocalGenerator(), config, |
376 | 0 | language); |
377 | 0 | cmGeneratorExpressionDAGChecker dagChecker{ |
378 | 0 | this->Target, "COMPILE_DEFINITIONS", nullptr, nullptr, context, |
379 | 0 | }; |
380 | |
|
381 | 0 | cm::EvaluatedTargetPropertyEntries entries = |
382 | 0 | cm::EvaluateTargetPropertyEntries(this->Target, context, &dagChecker, |
383 | 0 | this->InterfaceCompileDefinitions); |
384 | 0 | auto defines = ProcessOptions(entries); |
385 | 0 | this->InterfaceCompileDefinitionsCache.emplace(cacheKey, defines); |
386 | |
|
387 | 0 | return defines; |
388 | 0 | } |
389 | | |
390 | | std::vector<BT<std::string>> const& cmGeneratorFileSet::GetDirectoryEntries() |
391 | | const |
392 | 0 | { |
393 | 0 | return this->FileSet->GetDirectoryEntries(); |
394 | 0 | } |
395 | | |
396 | | std::vector<BT<std::string>> const& cmGeneratorFileSet::GetFileEntries() const |
397 | 0 | { |
398 | 0 | return this->FileSet->GetFileEntries(); |
399 | 0 | } |
400 | | |
401 | | std::vector<std::unique_ptr<cmCompiledGeneratorExpression>> const& |
402 | | cmGeneratorFileSet::CompileFileEntries() const |
403 | 0 | { |
404 | 0 | std::unordered_set<std::string> uniqueSrcs; |
405 | |
|
406 | 0 | if (this->CompiledFileEntries.empty() && |
407 | 0 | !this->FileSet->GetFileEntries().empty()) { |
408 | 0 | for (auto const& entry : this->FileSet->GetFileEntries()) { |
409 | 0 | for (auto const& ex : cmList{ entry.Value }) { |
410 | 0 | if (uniqueSrcs.insert(ex).second) { |
411 | 0 | cmGeneratorExpression ge( |
412 | 0 | *this->FileSet->GetMakefile()->GetCMakeInstance(), |
413 | 0 | entry.Backtrace); |
414 | 0 | auto cge = ge.Parse(ex); |
415 | 0 | this->CompiledFileEntries.push_back(std::move(cge)); |
416 | 0 | } |
417 | 0 | } |
418 | 0 | } |
419 | 0 | } |
420 | |
|
421 | 0 | return this->CompiledFileEntries; |
422 | 0 | } |
423 | | |
424 | | std::vector<std::unique_ptr<cmCompiledGeneratorExpression>> const& |
425 | | cmGeneratorFileSet::CompileDirectoryEntries() const |
426 | 0 | { |
427 | 0 | if (this->CompiledDirectoryEntries.empty() && |
428 | 0 | !this->FileSet->GetDirectoryEntries().empty()) { |
429 | 0 | for (auto const& entry : this->FileSet->GetDirectoryEntries()) { |
430 | 0 | for (auto const& ex : cmList{ entry.Value }) { |
431 | 0 | cmGeneratorExpression ge( |
432 | 0 | *this->FileSet->GetMakefile()->GetCMakeInstance(), entry.Backtrace); |
433 | 0 | auto cge = ge.Parse(ex); |
434 | 0 | this->CompiledDirectoryEntries.push_back(std::move(cge)); |
435 | 0 | } |
436 | 0 | } |
437 | 0 | } |
438 | |
|
439 | 0 | return this->CompiledDirectoryEntries; |
440 | 0 | } |
441 | | |
442 | | std::vector<std::string> cmGeneratorFileSet::EvaluateDirectoryEntries( |
443 | | std::vector<std::unique_ptr<cmCompiledGeneratorExpression>> const& cges, |
444 | | cm::GenEx::Context const& context, cmGeneratorTarget const* target, |
445 | | cmGeneratorExpressionDAGChecker* dagChecker) const |
446 | 0 | { |
447 | 0 | struct DirCacheEntry |
448 | 0 | { |
449 | 0 | std::string collapsedDir; |
450 | 0 | cm::optional<cmSystemTools::FileId> fileId; |
451 | 0 | }; |
452 | |
|
453 | 0 | std::unordered_map<std::string, DirCacheEntry> dirCache; |
454 | 0 | std::vector<std::string> result; |
455 | 0 | for (auto const& cge : cges) { |
456 | 0 | auto entry = cge->Evaluate(context, dagChecker, target); |
457 | 0 | cmList dirs{ entry }; |
458 | 0 | for (std::string dir : dirs) { |
459 | 0 | if (!cmSystemTools::FileIsFullPath(dir)) { |
460 | 0 | dir = cmStrCat(context.LG->GetCurrentSourceDirectory(), '/', |
461 | 0 | std::move(dir)); |
462 | 0 | } |
463 | |
|
464 | 0 | auto dirCacheResult = dirCache.emplace(dir, DirCacheEntry()); |
465 | 0 | auto& dirCacheEntry = dirCacheResult.first->second; |
466 | 0 | auto const isNewCacheEntry = dirCacheResult.second; |
467 | |
|
468 | 0 | if (isNewCacheEntry) { |
469 | 0 | cmSystemTools::FileId fileId; |
470 | 0 | auto isFileIdValid = cmSystemTools::GetFileId(dir, fileId); |
471 | 0 | dirCacheEntry.collapsedDir = cmSystemTools::CollapseFullPath(dir); |
472 | 0 | dirCacheEntry.fileId = |
473 | 0 | isFileIdValid ? cm::optional<decltype(fileId)>(fileId) : cm::nullopt; |
474 | 0 | } |
475 | |
|
476 | 0 | for (auto const& priorDir : result) { |
477 | 0 | auto priorDirCacheEntry = dirCache.at(priorDir); |
478 | 0 | bool sameFile = dirCacheEntry.fileId.has_value() && |
479 | 0 | priorDirCacheEntry.fileId.has_value() && |
480 | 0 | (*dirCacheEntry.fileId == *priorDirCacheEntry.fileId); |
481 | 0 | if (!sameFile && |
482 | 0 | (cmSystemTools::IsSubDirectory(dirCacheEntry.collapsedDir, |
483 | 0 | priorDirCacheEntry.collapsedDir) || |
484 | 0 | cmSystemTools::IsSubDirectory(priorDirCacheEntry.collapsedDir, |
485 | 0 | dirCacheEntry.collapsedDir))) { |
486 | 0 | context.LG->GetCMakeInstance()->IssueMessage( |
487 | 0 | MessageType::FATAL_ERROR, |
488 | 0 | cmStrCat( |
489 | 0 | "Base directories in file set cannot be subdirectories of each " |
490 | 0 | "other:\n ", |
491 | 0 | priorDir, "\n ", dir), |
492 | 0 | cge->GetBacktrace()); |
493 | 0 | return {}; |
494 | 0 | } |
495 | 0 | } |
496 | 0 | result.push_back(dir); |
497 | 0 | } |
498 | 0 | } |
499 | 0 | return result; |
500 | 0 | } |
501 | | |
502 | | void cmGeneratorFileSet::EvaluateFileEntry( |
503 | | std::vector<std::string> const& dirs, EvaluateFileEntryFunction handler, |
504 | | std::unique_ptr<cmCompiledGeneratorExpression> const& cge, |
505 | | cm::GenEx::Context const& context, cmGeneratorTarget const* target, |
506 | | cmGeneratorExpressionDAGChecker* dagChecker) const |
507 | 0 | { |
508 | 0 | auto files = cge->Evaluate(context, dagChecker, target); |
509 | 0 | for (std::string file : cmList{ files }) { |
510 | 0 | if (!cmSystemTools::FileIsFullPath(file)) { |
511 | 0 | file = cmStrCat(context.LG->GetCurrentSourceDirectory(), '/', |
512 | 0 | std::move(file)); |
513 | 0 | } |
514 | 0 | auto collapsedFile = cmSystemTools::CollapseFullPath(file); |
515 | 0 | std::string baseDir; |
516 | 0 | std::string relPath; |
517 | 0 | for (auto const& dir : dirs) { |
518 | 0 | auto collapsedDir = cmSystemTools::CollapseFullPath(dir); |
519 | 0 | if (cmSystemTools::IsSubDirectory(collapsedFile, collapsedDir)) { |
520 | 0 | baseDir = collapsedDir; |
521 | 0 | relPath = cmSystemTools::RelativePath(collapsedDir, collapsedFile); |
522 | 0 | break; |
523 | 0 | } |
524 | 0 | } |
525 | 0 | if (baseDir.empty()) { |
526 | 0 | context.LG->GetCMakeInstance()->IssueMessage( |
527 | 0 | MessageType::FATAL_ERROR, |
528 | 0 | cmStrCat("File:\n ", file, |
529 | 0 | "\nmust be in one of the file set's base directories:", |
530 | 0 | cmWrap("\n ", dirs, "", "")), |
531 | 0 | cge->GetBacktrace()); |
532 | 0 | return; |
533 | 0 | } |
534 | | |
535 | 0 | handler(std::move(baseDir), std::move(relPath), std::move(file)); |
536 | 0 | } |
537 | 0 | } |
538 | | |
539 | | void cmGeneratorFileSet::EvaluateFileEntry( |
540 | | std::vector<std::string> const& dirs, FileMap& filesPerDir, |
541 | | std::unique_ptr<cmCompiledGeneratorExpression> const& cge, |
542 | | cm::GenEx::Context const& context, cmGeneratorTarget const* target, |
543 | | cmGeneratorExpressionDAGChecker* dagChecker) const |
544 | 0 | { |
545 | 0 | auto handler = [&filesPerDir](std::string&& /*baseDir*/, |
546 | 0 | std::string&& relPath, std::string&& file) { |
547 | 0 | std::string relDir = cmSystemTools::GetParentDirectory(relPath); |
548 | 0 | filesPerDir[std::move(relDir)].emplace_back(std::move(file)); |
549 | 0 | }; |
550 | 0 | this->EvaluateFileEntry(dirs, handler, cge, context, target, dagChecker); |
551 | 0 | } |
552 | | |
553 | | namespace { |
554 | | bool EntryIsContextSensitive( |
555 | | std::unique_ptr<cmCompiledGeneratorExpression> const& cge) |
556 | 0 | { |
557 | 0 | return cge->GetHadContextSensitiveCondition(); |
558 | 0 | } |
559 | | } |
560 | | |
561 | | std::vector<std::unique_ptr<cm::TargetPropertyEntry>> |
562 | | cmGeneratorFileSet::GetSources( |
563 | | cm::GenEx::Context const& context, cmGeneratorTarget const* target, |
564 | | cmGeneratorExpressionDAGChecker* dagChecker) const |
565 | 0 | { |
566 | 0 | std::vector<std::unique_ptr<TargetPropertyEntry>> entries; |
567 | |
|
568 | 0 | auto directories = this->GetDirectories(context, target, dagChecker); |
569 | 0 | bool contextSensitive = directories.second; |
570 | |
|
571 | 0 | for (auto const& entry : this->CompileFileEntries()) { |
572 | 0 | auto propEntry = FileSetPropertyEntry::CreateFileSetEntry( |
573 | 0 | directories.first, contextSensitive, entry, this); |
574 | 0 | entries.push_back(std::move(propEntry)); |
575 | 0 | } |
576 | |
|
577 | 0 | return entries; |
578 | 0 | } |
579 | | |
580 | | std::pair<std::vector<std::string>, bool> cmGeneratorFileSet::GetDirectories( |
581 | | cm::GenEx::Context const& context, cmGeneratorTarget const* target, |
582 | | cmGeneratorExpressionDAGChecker* dagChecker) const |
583 | 0 | { |
584 | 0 | auto const& directoryEntries = this->CompileDirectoryEntries(); |
585 | 0 | auto directories = this->EvaluateDirectoryEntries(directoryEntries, context, |
586 | 0 | target, dagChecker); |
587 | 0 | bool contextSensitive = std::any_of( |
588 | 0 | directoryEntries.begin(), directoryEntries.end(), EntryIsContextSensitive); |
589 | |
|
590 | 0 | return std::make_pair(std::move(directories), contextSensitive); |
591 | 0 | } |
592 | | |
593 | | std::pair<cmGeneratorFileSet::FileMap, bool> cmGeneratorFileSet::GetFiles( |
594 | | cm::GenEx::Context const& context, cmGeneratorTarget const* target, |
595 | | cmGeneratorExpressionDAGChecker* dagChecker) const |
596 | 0 | { |
597 | 0 | auto directories = this->GetDirectories(context, target, dagChecker); |
598 | |
|
599 | 0 | auto const& fileEntries = this->CompileFileEntries(); |
600 | 0 | std::map<std::string, std::vector<std::string>> files; |
601 | 0 | for (auto const& entry : fileEntries) { |
602 | 0 | this->EvaluateFileEntry(directories.first, files, entry, context, target, |
603 | 0 | dagChecker); |
604 | 0 | } |
605 | 0 | bool contextSensitive = directories.second || |
606 | 0 | std::any_of(fileEntries.begin(), fileEntries.end(), |
607 | 0 | EntryIsContextSensitive); |
608 | |
|
609 | 0 | return std::make_pair(std::move(files), contextSensitive); |
610 | 0 | } |
611 | | |
612 | | bool cmGeneratorFileSet::EvaluateFiles( |
613 | | cm::GenEx::Context const& context, cmGeneratorTarget const* target, |
614 | | EvaluateFileEntryFunction callback, |
615 | | cmGeneratorExpressionDAGChecker* dagChecker) const |
616 | 0 | { |
617 | 0 | auto directories = this->GetDirectories(context, target, dagChecker); |
618 | |
|
619 | 0 | auto const& fileEntries = this->CompileFileEntries(); |
620 | 0 | for (auto const& entry : fileEntries) { |
621 | 0 | this->EvaluateFileEntry(directories.first, callback, entry, context, |
622 | 0 | target, dagChecker); |
623 | 0 | } |
624 | 0 | return directories.second || |
625 | 0 | std::any_of(fileEntries.begin(), fileEntries.end(), |
626 | 0 | EntryIsContextSensitive); |
627 | 0 | } |