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