resolve cyclic dependency with zstd
[platform/upstream/cmake.git] / Source / cmStateDirectory.cxx
1 /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
2    file Copyright.txt or https://cmake.org/licensing for details.  */
3
4 #include "cmStateDirectory.h"
5
6 #include <algorithm>
7 #include <cassert>
8 #include <vector>
9
10 #include <cm/iterator>
11 #include <cm/string_view>
12 #include <cmext/algorithm>
13 #include <cmext/string_view>
14
15 #include "cmAlgorithms.h"
16 #include "cmListFileCache.h"
17 #include "cmProperty.h"
18 #include "cmPropertyMap.h"
19 #include "cmRange.h"
20 #include "cmState.h"
21 #include "cmStatePrivate.h"
22 #include "cmStateTypes.h"
23 #include "cmStringAlgorithms.h"
24 #include "cmSystemTools.h"
25 #include "cmValue.h"
26
27 static std::string const kBINARY_DIR = "BINARY_DIR";
28 static std::string const kBUILDSYSTEM_TARGETS = "BUILDSYSTEM_TARGETS";
29 static std::string const kSOURCE_DIR = "SOURCE_DIR";
30 static std::string const kSUBDIRECTORIES = "SUBDIRECTORIES";
31
32 std::string const& cmStateDirectory::GetCurrentSource() const
33 {
34   return this->DirectoryState->Location;
35 }
36
37 void cmStateDirectory::SetCurrentSource(std::string const& dir)
38 {
39   std::string& loc = this->DirectoryState->Location;
40   loc = dir;
41   cmSystemTools::ConvertToUnixSlashes(loc);
42   loc = cmSystemTools::CollapseFullPath(loc);
43   this->Snapshot_.SetDefinition("CMAKE_CURRENT_SOURCE_DIR", loc);
44 }
45
46 std::string const& cmStateDirectory::GetCurrentBinary() const
47 {
48   return this->DirectoryState->OutputLocation;
49 }
50
51 void cmStateDirectory::SetCurrentBinary(std::string const& dir)
52 {
53   std::string& loc = this->DirectoryState->OutputLocation;
54   loc = dir;
55   cmSystemTools::ConvertToUnixSlashes(loc);
56   loc = cmSystemTools::CollapseFullPath(loc);
57   this->Snapshot_.SetDefinition("CMAKE_CURRENT_BINARY_DIR", loc);
58 }
59
60 cmStateDirectory::cmStateDirectory(
61   cmLinkedTree<cmStateDetail::BuildsystemDirectoryStateType>::iterator iter,
62   const cmStateSnapshot& snapshot)
63   : DirectoryState(iter)
64   , Snapshot_(snapshot)
65 {
66 }
67
68 template <typename T, typename U>
69 cmBTStringRange GetPropertyContent(T const& content, U contentEndPosition)
70 {
71   auto end = content.begin() + contentEndPosition;
72
73   auto rbegin = cm::make_reverse_iterator(end);
74   rbegin = std::find(rbegin, content.rend(), cmPropertySentinal);
75
76   return cmMakeRange(rbegin.base(), end);
77 }
78
79 template <typename T, typename U>
80 void AppendEntry(T& content, U& endContentPosition,
81                  const BT<std::string>& value)
82 {
83   if (value.Value.empty()) {
84     return;
85   }
86
87   assert(endContentPosition == content.size());
88
89   content.push_back(value);
90
91   endContentPosition = content.size();
92 }
93
94 template <typename T, typename U>
95 void SetContent(T& content, U& endContentPosition, const BT<std::string>& vec)
96 {
97   assert(endContentPosition == content.size());
98
99   content.resize(content.size() + 2);
100
101   content.back() = vec;
102
103   endContentPosition = content.size();
104 }
105
106 template <typename T, typename U>
107 void ClearContent(T& content, U& endContentPosition)
108 {
109   assert(endContentPosition == content.size());
110
111   content.resize(content.size() + 1);
112
113   endContentPosition = content.size();
114 }
115
116 cmBTStringRange cmStateDirectory::GetIncludeDirectoriesEntries() const
117 {
118   return GetPropertyContent(
119     this->DirectoryState->IncludeDirectories,
120     this->Snapshot_.Position->IncludeDirectoryPosition);
121 }
122
123 void cmStateDirectory::AppendIncludeDirectoriesEntry(
124   const BT<std::string>& vec)
125 {
126   AppendEntry(this->DirectoryState->IncludeDirectories,
127               this->Snapshot_.Position->IncludeDirectoryPosition, vec);
128 }
129
130 void cmStateDirectory::PrependIncludeDirectoriesEntry(
131   const BT<std::string>& vec)
132 {
133   auto entryEnd = this->DirectoryState->IncludeDirectories.begin() +
134     this->Snapshot_.Position->IncludeDirectoryPosition;
135
136   auto rend = this->DirectoryState->IncludeDirectories.rend();
137   auto rbegin = cm::make_reverse_iterator(entryEnd);
138   rbegin = std::find(rbegin, rend, cmPropertySentinal);
139
140   auto entryIt = rbegin.base();
141
142   this->DirectoryState->IncludeDirectories.insert(entryIt, vec);
143
144   this->Snapshot_.Position->IncludeDirectoryPosition =
145     this->DirectoryState->IncludeDirectories.size();
146 }
147
148 void cmStateDirectory::SetIncludeDirectories(const BT<std::string>& vec)
149 {
150   SetContent(this->DirectoryState->IncludeDirectories,
151              this->Snapshot_.Position->IncludeDirectoryPosition, vec);
152 }
153
154 void cmStateDirectory::ClearIncludeDirectories()
155 {
156   ClearContent(this->DirectoryState->IncludeDirectories,
157                this->Snapshot_.Position->IncludeDirectoryPosition);
158 }
159
160 cmBTStringRange cmStateDirectory::GetCompileDefinitionsEntries() const
161 {
162   return GetPropertyContent(
163     this->DirectoryState->CompileDefinitions,
164     this->Snapshot_.Position->CompileDefinitionsPosition);
165 }
166
167 void cmStateDirectory::AppendCompileDefinitionsEntry(
168   const BT<std::string>& vec)
169 {
170   AppendEntry(this->DirectoryState->CompileDefinitions,
171               this->Snapshot_.Position->CompileDefinitionsPosition, vec);
172 }
173
174 void cmStateDirectory::SetCompileDefinitions(const BT<std::string>& vec)
175 {
176   SetContent(this->DirectoryState->CompileDefinitions,
177              this->Snapshot_.Position->CompileDefinitionsPosition, vec);
178 }
179
180 void cmStateDirectory::ClearCompileDefinitions()
181 {
182   ClearContent(this->DirectoryState->CompileDefinitions,
183                this->Snapshot_.Position->CompileDefinitionsPosition);
184 }
185
186 cmBTStringRange cmStateDirectory::GetCompileOptionsEntries() const
187 {
188   return GetPropertyContent(this->DirectoryState->CompileOptions,
189                             this->Snapshot_.Position->CompileOptionsPosition);
190 }
191
192 void cmStateDirectory::AppendCompileOptionsEntry(const BT<std::string>& vec)
193 {
194   AppendEntry(this->DirectoryState->CompileOptions,
195               this->Snapshot_.Position->CompileOptionsPosition, vec);
196 }
197
198 void cmStateDirectory::SetCompileOptions(const BT<std::string>& vec)
199 {
200   SetContent(this->DirectoryState->CompileOptions,
201              this->Snapshot_.Position->CompileOptionsPosition, vec);
202 }
203
204 void cmStateDirectory::ClearCompileOptions()
205 {
206   ClearContent(this->DirectoryState->CompileOptions,
207                this->Snapshot_.Position->CompileOptionsPosition);
208 }
209
210 cmBTStringRange cmStateDirectory::GetLinkOptionsEntries() const
211 {
212   return GetPropertyContent(this->DirectoryState->LinkOptions,
213                             this->Snapshot_.Position->LinkOptionsPosition);
214 }
215
216 void cmStateDirectory::AppendLinkOptionsEntry(const BT<std::string>& vec)
217 {
218   AppendEntry(this->DirectoryState->LinkOptions,
219               this->Snapshot_.Position->LinkOptionsPosition, vec);
220 }
221
222 void cmStateDirectory::SetLinkOptions(const BT<std::string>& vec)
223 {
224   SetContent(this->DirectoryState->LinkOptions,
225              this->Snapshot_.Position->LinkOptionsPosition, vec);
226 }
227
228 void cmStateDirectory::ClearLinkOptions()
229 {
230   ClearContent(this->DirectoryState->LinkOptions,
231                this->Snapshot_.Position->LinkOptionsPosition);
232 }
233
234 cmBTStringRange cmStateDirectory::GetLinkDirectoriesEntries() const
235 {
236   return GetPropertyContent(this->DirectoryState->LinkDirectories,
237                             this->Snapshot_.Position->LinkDirectoriesPosition);
238 }
239
240 void cmStateDirectory::AppendLinkDirectoriesEntry(const BT<std::string>& vec)
241 {
242   AppendEntry(this->DirectoryState->LinkDirectories,
243               this->Snapshot_.Position->LinkDirectoriesPosition, vec);
244 }
245 void cmStateDirectory::PrependLinkDirectoriesEntry(const BT<std::string>& vec)
246 {
247   auto entryEnd = this->DirectoryState->LinkDirectories.begin() +
248     this->Snapshot_.Position->LinkDirectoriesPosition;
249
250   auto rend = this->DirectoryState->LinkDirectories.rend();
251   auto rbegin = cm::make_reverse_iterator(entryEnd);
252   rbegin = std::find(rbegin, rend, cmPropertySentinal);
253
254   auto entryIt = rbegin.base();
255
256   this->DirectoryState->LinkDirectories.insert(entryIt, vec);
257
258   this->Snapshot_.Position->LinkDirectoriesPosition =
259     this->DirectoryState->LinkDirectories.size();
260 }
261
262 void cmStateDirectory::SetLinkDirectories(const BT<std::string>& vec)
263 {
264   SetContent(this->DirectoryState->LinkDirectories,
265              this->Snapshot_.Position->LinkDirectoriesPosition, vec);
266 }
267
268 void cmStateDirectory::ClearLinkDirectories()
269 {
270   ClearContent(this->DirectoryState->LinkDirectories,
271                this->Snapshot_.Position->LinkDirectoriesPosition);
272 }
273
274 template <typename ValueType>
275 void cmStateDirectory::StoreProperty(const std::string& prop, ValueType value,
276                                      cmListFileBacktrace const& lfbt)
277 {
278   if (prop == "INCLUDE_DIRECTORIES") {
279     if (!value) {
280       this->ClearIncludeDirectories();
281       return;
282     }
283     this->SetIncludeDirectories(BT<std::string>(value, lfbt));
284     return;
285   }
286   if (prop == "COMPILE_OPTIONS") {
287     if (!value) {
288       this->ClearCompileOptions();
289       return;
290     }
291     this->SetCompileOptions(BT<std::string>(value, lfbt));
292     return;
293   }
294   if (prop == "COMPILE_DEFINITIONS") {
295     if (!value) {
296       this->ClearCompileDefinitions();
297       return;
298     }
299     this->SetCompileDefinitions(BT<std::string>(value, lfbt));
300     return;
301   }
302   if (prop == "LINK_OPTIONS") {
303     if (!value) {
304       this->ClearLinkOptions();
305       return;
306     }
307     this->SetLinkOptions(BT<std::string>(value, lfbt));
308     return;
309   }
310   if (prop == "LINK_DIRECTORIES") {
311     if (!value) {
312       this->ClearLinkDirectories();
313       return;
314     }
315     this->SetLinkDirectories(BT<std::string>(value, lfbt));
316     return;
317   }
318
319   this->DirectoryState->Properties.SetProperty(prop, value);
320 }
321
322 void cmStateDirectory::SetProperty(const std::string& prop, const char* value,
323                                    cmListFileBacktrace const& lfbt)
324 {
325   this->StoreProperty(prop, value, lfbt);
326 }
327 void cmStateDirectory::SetProperty(const std::string& prop, cmValue value,
328                                    cmListFileBacktrace const& lfbt)
329 {
330   this->StoreProperty(prop, value, lfbt);
331 }
332
333 void cmStateDirectory::AppendProperty(const std::string& prop,
334                                       const std::string& value, bool asString,
335                                       cmListFileBacktrace const& lfbt)
336 {
337   if (prop == "INCLUDE_DIRECTORIES") {
338     this->AppendIncludeDirectoriesEntry(BT<std::string>(value, lfbt));
339     return;
340   }
341   if (prop == "COMPILE_OPTIONS") {
342     this->AppendCompileOptionsEntry(BT<std::string>(value, lfbt));
343     return;
344   }
345   if (prop == "COMPILE_DEFINITIONS") {
346     this->AppendCompileDefinitionsEntry(BT<std::string>(value, lfbt));
347     return;
348   }
349   if (prop == "LINK_OPTIONS") {
350     this->AppendLinkOptionsEntry(BT<std::string>(value, lfbt));
351     return;
352   }
353   if (prop == "LINK_DIRECTORIES") {
354     this->AppendLinkDirectoriesEntry(BT<std::string>(value, lfbt));
355     return;
356   }
357
358   this->DirectoryState->Properties.AppendProperty(prop, value, asString);
359 }
360
361 cmValue cmStateDirectory::GetProperty(const std::string& prop) const
362 {
363   const bool chain =
364     this->Snapshot_.State->IsPropertyChained(prop, cmProperty::DIRECTORY);
365   return this->GetProperty(prop, chain);
366 }
367
368 cmValue cmStateDirectory::GetProperty(const std::string& prop,
369                                       bool chain) const
370 {
371   static std::string output;
372   output.clear();
373   if (prop == "PARENT_DIRECTORY") {
374     cmStateSnapshot parent = this->Snapshot_.GetBuildsystemDirectoryParent();
375     if (parent.IsValid()) {
376       return cmValue(parent.GetDirectory().GetCurrentSource());
377     }
378     return cmValue(output);
379   }
380   if (prop == kBINARY_DIR) {
381     output = this->GetCurrentBinary();
382     return cmValue(output);
383   }
384   if (prop == kSOURCE_DIR) {
385     output = this->GetCurrentSource();
386     return cmValue(output);
387   }
388   if (prop == kSUBDIRECTORIES) {
389     std::vector<std::string> child_dirs;
390     std::vector<cmStateSnapshot> const& children =
391       this->DirectoryState->Children;
392     child_dirs.reserve(children.size());
393     for (cmStateSnapshot const& ci : children) {
394       child_dirs.push_back(ci.GetDirectory().GetCurrentSource());
395     }
396     output = cmJoin(child_dirs, ";");
397     return cmValue(output);
398   }
399   if (prop == kBUILDSYSTEM_TARGETS) {
400     output = cmJoin(this->DirectoryState->NormalTargetNames, ";");
401     return cmValue(output);
402   }
403   if (prop == "IMPORTED_TARGETS"_s) {
404     output = cmJoin(this->DirectoryState->ImportedTargetNames, ";");
405     return cmValue(output);
406   }
407
408   if (prop == "LISTFILE_STACK") {
409     std::vector<std::string> listFiles;
410     cmStateSnapshot snp = this->Snapshot_;
411     while (snp.IsValid()) {
412       listFiles.push_back(snp.GetExecutionListFile());
413       snp = snp.GetCallStackParent();
414     }
415     std::reverse(listFiles.begin(), listFiles.end());
416     output = cmJoin(listFiles, ";");
417     return cmValue(output);
418   }
419   if (prop == "CACHE_VARIABLES") {
420     output = cmJoin(this->Snapshot_.State->GetCacheEntryKeys(), ";");
421     return cmValue(output);
422   }
423   if (prop == "VARIABLES") {
424     std::vector<std::string> res = this->Snapshot_.ClosureKeys();
425     cm::append(res, this->Snapshot_.State->GetCacheEntryKeys());
426     std::sort(res.begin(), res.end());
427     output = cmJoin(res, ";");
428     return cmValue(output);
429   }
430   if (prop == "INCLUDE_DIRECTORIES") {
431     output = cmJoin(this->GetIncludeDirectoriesEntries(), ";");
432     return cmValue(output);
433   }
434   if (prop == "COMPILE_OPTIONS") {
435     output = cmJoin(this->GetCompileOptionsEntries(), ";");
436     return cmValue(output);
437   }
438   if (prop == "COMPILE_DEFINITIONS") {
439     output = cmJoin(this->GetCompileDefinitionsEntries(), ";");
440     return cmValue(output);
441   }
442   if (prop == "LINK_OPTIONS") {
443     output = cmJoin(this->GetLinkOptionsEntries(), ";");
444     return cmValue(output);
445   }
446   if (prop == "LINK_DIRECTORIES") {
447     output = cmJoin(this->GetLinkDirectoriesEntries(), ";");
448     return cmValue(output);
449   }
450
451   cmValue retVal = this->DirectoryState->Properties.GetPropertyValue(prop);
452   if (!retVal && chain) {
453     cmStateSnapshot parentSnapshot =
454       this->Snapshot_.GetBuildsystemDirectoryParent();
455     if (parentSnapshot.IsValid()) {
456       return parentSnapshot.GetDirectory().GetProperty(prop, chain);
457     }
458     return this->Snapshot_.State->GetGlobalProperty(prop);
459   }
460
461   return retVal;
462 }
463
464 bool cmStateDirectory::GetPropertyAsBool(const std::string& prop) const
465 {
466   return cmIsOn(this->GetProperty(prop));
467 }
468
469 std::vector<std::string> cmStateDirectory::GetPropertyKeys() const
470 {
471   return this->DirectoryState->Properties.GetKeys();
472 }
473
474 void cmStateDirectory::AddNormalTargetName(std::string const& name)
475 {
476   this->DirectoryState->NormalTargetNames.push_back(name);
477 }
478
479 void cmStateDirectory::AddImportedTargetName(std::string const& name)
480 {
481   this->DirectoryState->ImportedTargetNames.emplace_back(name);
482 }