3d38e734af08b33f23c2881a16b71b12422f59f8
[platform/upstream/cmake.git] / Source / cmState.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 #include "cmState.h"
4
5 #include <algorithm>
6 #include <array>
7 #include <cassert>
8 #include <cstdlib>
9 #include <utility>
10
11 #include <cm/memory>
12
13 #include "cmsys/RegularExpression.hxx"
14
15 #include "cmCacheManager.h"
16 #include "cmCommand.h"
17 #include "cmDefinitions.h"
18 #include "cmExecutionStatus.h"
19 #include "cmGlobVerificationManager.h"
20 #include "cmListFileCache.h"
21 #include "cmMakefile.h"
22 #include "cmMessageType.h"
23 #include "cmStatePrivate.h"
24 #include "cmStateSnapshot.h"
25 #include "cmStringAlgorithms.h"
26 #include "cmSystemTools.h"
27 #include "cmake.h"
28
29 cmState::cmState(Mode mode, ProjectKind projectKind)
30   : StateMode(mode)
31   , StateProjectKind(projectKind)
32 {
33   this->CacheManager = cm::make_unique<cmCacheManager>();
34   this->GlobVerificationManager = cm::make_unique<cmGlobVerificationManager>();
35 }
36
37 cmState::~cmState() = default;
38
39 const std::string& cmState::GetTargetTypeName(
40   cmStateEnums::TargetType targetType)
41 {
42 #define MAKE_STATIC_PROP(PROP) static const std::string prop##PROP = #PROP
43   MAKE_STATIC_PROP(STATIC_LIBRARY);
44   MAKE_STATIC_PROP(MODULE_LIBRARY);
45   MAKE_STATIC_PROP(SHARED_LIBRARY);
46   MAKE_STATIC_PROP(OBJECT_LIBRARY);
47   MAKE_STATIC_PROP(EXECUTABLE);
48   MAKE_STATIC_PROP(UTILITY);
49   MAKE_STATIC_PROP(GLOBAL_TARGET);
50   MAKE_STATIC_PROP(INTERFACE_LIBRARY);
51   MAKE_STATIC_PROP(UNKNOWN_LIBRARY);
52   static const std::string propEmpty;
53 #undef MAKE_STATIC_PROP
54
55   switch (targetType) {
56     case cmStateEnums::STATIC_LIBRARY:
57       return propSTATIC_LIBRARY;
58     case cmStateEnums::MODULE_LIBRARY:
59       return propMODULE_LIBRARY;
60     case cmStateEnums::SHARED_LIBRARY:
61       return propSHARED_LIBRARY;
62     case cmStateEnums::OBJECT_LIBRARY:
63       return propOBJECT_LIBRARY;
64     case cmStateEnums::EXECUTABLE:
65       return propEXECUTABLE;
66     case cmStateEnums::UTILITY:
67       return propUTILITY;
68     case cmStateEnums::GLOBAL_TARGET:
69       return propGLOBAL_TARGET;
70     case cmStateEnums::INTERFACE_LIBRARY:
71       return propINTERFACE_LIBRARY;
72     case cmStateEnums::UNKNOWN_LIBRARY:
73       return propUNKNOWN_LIBRARY;
74   }
75   assert(false && "Unexpected target type");
76   return propEmpty;
77 }
78
79 static const std::array<std::string, 7> cmCacheEntryTypes = {
80   { "BOOL", "PATH", "FILEPATH", "STRING", "INTERNAL", "STATIC",
81     "UNINITIALIZED" }
82 };
83
84 const std::string& cmState::CacheEntryTypeToString(
85   cmStateEnums::CacheEntryType type)
86 {
87   if (type < cmStateEnums::BOOL || type > cmStateEnums::UNINITIALIZED) {
88     type = cmStateEnums::UNINITIALIZED;
89   }
90   return cmCacheEntryTypes[type];
91 }
92
93 cmStateEnums::CacheEntryType cmState::StringToCacheEntryType(
94   const std::string& s)
95 {
96   cmStateEnums::CacheEntryType type = cmStateEnums::STRING;
97   StringToCacheEntryType(s, type);
98   return type;
99 }
100
101 bool cmState::StringToCacheEntryType(const std::string& s,
102                                      cmStateEnums::CacheEntryType& type)
103 {
104   for (size_t i = 0; i < cmCacheEntryTypes.size(); ++i) {
105     if (s == cmCacheEntryTypes[i]) {
106       type = static_cast<cmStateEnums::CacheEntryType>(i);
107       return true;
108     }
109   }
110   return false;
111 }
112
113 bool cmState::IsCacheEntryType(std::string const& key)
114 {
115   return std::any_of(
116     cmCacheEntryTypes.begin(), cmCacheEntryTypes.end(),
117     [&key](std::string const& i) -> bool { return key == i; });
118 }
119
120 bool cmState::LoadCache(const std::string& path, bool internal,
121                         std::set<std::string>& excludes,
122                         std::set<std::string>& includes)
123 {
124   return this->CacheManager->LoadCache(path, internal, excludes, includes);
125 }
126
127 bool cmState::SaveCache(const std::string& path, cmMessenger* messenger)
128 {
129   return this->CacheManager->SaveCache(path, messenger);
130 }
131
132 bool cmState::DeleteCache(const std::string& path)
133 {
134   return this->CacheManager->DeleteCache(path);
135 }
136
137 bool cmState::IsCacheLoaded() const
138 {
139   return this->CacheManager->IsCacheLoaded();
140 }
141
142 std::vector<std::string> cmState::GetCacheEntryKeys() const
143 {
144   return this->CacheManager->GetCacheEntryKeys();
145 }
146
147 cmValue cmState::GetCacheEntryValue(std::string const& key) const
148 {
149   return this->CacheManager->GetCacheEntryValue(key);
150 }
151
152 std::string cmState::GetSafeCacheEntryValue(std::string const& key) const
153 {
154   if (cmValue val = this->GetCacheEntryValue(key)) {
155     return *val;
156   }
157   return std::string();
158 }
159
160 cmValue cmState::GetInitializedCacheValue(std::string const& key) const
161 {
162   return this->CacheManager->GetInitializedCacheValue(key);
163 }
164
165 cmStateEnums::CacheEntryType cmState::GetCacheEntryType(
166   std::string const& key) const
167 {
168   return this->CacheManager->GetCacheEntryType(key);
169 }
170
171 void cmState::SetCacheEntryValue(std::string const& key,
172                                  std::string const& value)
173 {
174   this->CacheManager->SetCacheEntryValue(key, value);
175 }
176
177 void cmState::SetCacheEntryProperty(std::string const& key,
178                                     std::string const& propertyName,
179                                     std::string const& value)
180 {
181   this->CacheManager->SetCacheEntryProperty(key, propertyName, value);
182 }
183
184 void cmState::SetCacheEntryBoolProperty(std::string const& key,
185                                         std::string const& propertyName,
186                                         bool value)
187 {
188   this->CacheManager->SetCacheEntryBoolProperty(key, propertyName, value);
189 }
190
191 std::vector<std::string> cmState::GetCacheEntryPropertyList(
192   const std::string& key)
193 {
194   return this->CacheManager->GetCacheEntryPropertyList(key);
195 }
196
197 cmValue cmState::GetCacheEntryProperty(std::string const& key,
198                                        std::string const& propertyName)
199 {
200   return this->CacheManager->GetCacheEntryProperty(key, propertyName);
201 }
202
203 bool cmState::GetCacheEntryPropertyAsBool(std::string const& key,
204                                           std::string const& propertyName)
205 {
206   return this->CacheManager->GetCacheEntryPropertyAsBool(key, propertyName);
207 }
208
209 void cmState::AddCacheEntry(const std::string& key, cmValue value,
210                             const char* helpString,
211                             cmStateEnums::CacheEntryType type)
212 {
213   this->CacheManager->AddCacheEntry(key, value, helpString, type);
214 }
215
216 bool cmState::DoWriteGlobVerifyTarget() const
217 {
218   return this->GlobVerificationManager->DoWriteVerifyTarget();
219 }
220
221 std::string const& cmState::GetGlobVerifyScript() const
222 {
223   return this->GlobVerificationManager->GetVerifyScript();
224 }
225
226 std::string const& cmState::GetGlobVerifyStamp() const
227 {
228   return this->GlobVerificationManager->GetVerifyStamp();
229 }
230
231 bool cmState::SaveVerificationScript(const std::string& path,
232                                      cmMessenger* messenger)
233 {
234   return this->GlobVerificationManager->SaveVerificationScript(path,
235                                                                messenger);
236 }
237
238 void cmState::AddGlobCacheEntry(
239   bool recurse, bool listDirectories, bool followSymlinks,
240   const std::string& relative, const std::string& expression,
241   const std::vector<std::string>& files, const std::string& variable,
242   cmListFileBacktrace const& backtrace, cmMessenger* messenger)
243 {
244   this->GlobVerificationManager->AddCacheEntry(
245     recurse, listDirectories, followSymlinks, relative, expression, files,
246     variable, backtrace, messenger);
247 }
248
249 void cmState::RemoveCacheEntry(std::string const& key)
250 {
251   this->CacheManager->RemoveCacheEntry(key);
252 }
253
254 void cmState::AppendCacheEntryProperty(const std::string& key,
255                                        const std::string& property,
256                                        const std::string& value, bool asString)
257 {
258   this->CacheManager->AppendCacheEntryProperty(key, property, value, asString);
259 }
260
261 void cmState::RemoveCacheEntryProperty(std::string const& key,
262                                        std::string const& propertyName)
263 {
264   this->CacheManager->RemoveCacheEntryProperty(key, propertyName);
265 }
266
267 cmStateSnapshot cmState::Reset()
268 {
269   this->GlobalProperties.Clear();
270   this->PropertyDefinitions = {};
271   this->GlobVerificationManager->Reset();
272
273   cmStateDetail::PositionType pos = this->SnapshotData.Truncate();
274   this->ExecutionListFiles.Truncate();
275
276   {
277     cmLinkedTree<cmStateDetail::BuildsystemDirectoryStateType>::iterator it =
278       this->BuildsystemDirectory.Truncate();
279     it->IncludeDirectories.clear();
280     it->CompileDefinitions.clear();
281     it->CompileOptions.clear();
282     it->LinkOptions.clear();
283     it->LinkDirectories.clear();
284     it->DirectoryEnd = pos;
285     it->NormalTargetNames.clear();
286     it->ImportedTargetNames.clear();
287     it->Properties.Clear();
288     it->Children.clear();
289   }
290
291   this->PolicyStack.Clear();
292   pos->Policies = this->PolicyStack.Root();
293   pos->PolicyRoot = this->PolicyStack.Root();
294   pos->PolicyScope = this->PolicyStack.Root();
295   assert(pos->Policies.IsValid());
296   assert(pos->PolicyRoot.IsValid());
297
298   {
299     std::string srcDir =
300       *cmDefinitions::Get("CMAKE_SOURCE_DIR", pos->Vars, pos->Root);
301     std::string binDir =
302       *cmDefinitions::Get("CMAKE_BINARY_DIR", pos->Vars, pos->Root);
303     this->VarTree.Clear();
304     pos->Vars = this->VarTree.Push(this->VarTree.Root());
305     pos->Parent = this->VarTree.Root();
306     pos->Root = this->VarTree.Root();
307
308     pos->Vars->Set("CMAKE_SOURCE_DIR", srcDir);
309     pos->Vars->Set("CMAKE_BINARY_DIR", binDir);
310   }
311
312   this->DefineProperty("RULE_LAUNCH_COMPILE", cmProperty::DIRECTORY, "", "",
313                        true);
314   this->DefineProperty("RULE_LAUNCH_LINK", cmProperty::DIRECTORY, "", "",
315                        true);
316   this->DefineProperty("RULE_LAUNCH_CUSTOM", cmProperty::DIRECTORY, "", "",
317                        true);
318
319   this->DefineProperty("RULE_LAUNCH_COMPILE", cmProperty::TARGET, "", "",
320                        true);
321   this->DefineProperty("RULE_LAUNCH_LINK", cmProperty::TARGET, "", "", true);
322   this->DefineProperty("RULE_LAUNCH_CUSTOM", cmProperty::TARGET, "", "", true);
323
324   return { this, pos };
325 }
326
327 void cmState::DefineProperty(const std::string& name,
328                              cmProperty::ScopeType scope,
329                              const std::string& ShortDescription,
330                              const std::string& FullDescription, bool chained,
331                              const std::string& initializeFromVariable)
332 {
333   this->PropertyDefinitions.DefineProperty(name, scope, ShortDescription,
334                                            FullDescription, chained,
335                                            initializeFromVariable);
336 }
337
338 cmPropertyDefinition const* cmState::GetPropertyDefinition(
339   const std::string& name, cmProperty::ScopeType scope) const
340 {
341   return this->PropertyDefinitions.GetPropertyDefinition(name, scope);
342 }
343
344 bool cmState::IsPropertyChained(const std::string& name,
345                                 cmProperty::ScopeType scope) const
346 {
347   if (const auto* def = this->GetPropertyDefinition(name, scope)) {
348     return def->IsChained();
349   }
350   return false;
351 }
352
353 void cmState::SetLanguageEnabled(std::string const& l)
354 {
355   auto it = std::lower_bound(this->EnabledLanguages.begin(),
356                              this->EnabledLanguages.end(), l);
357   if (it == this->EnabledLanguages.end() || *it != l) {
358     this->EnabledLanguages.insert(it, l);
359   }
360 }
361
362 bool cmState::GetLanguageEnabled(std::string const& l) const
363 {
364   return std::binary_search(this->EnabledLanguages.begin(),
365                             this->EnabledLanguages.end(), l);
366 }
367
368 std::vector<std::string> cmState::GetEnabledLanguages() const
369 {
370   return this->EnabledLanguages;
371 }
372
373 void cmState::SetEnabledLanguages(std::vector<std::string> const& langs)
374 {
375   this->EnabledLanguages = langs;
376 }
377
378 void cmState::ClearEnabledLanguages()
379 {
380   this->EnabledLanguages.clear();
381 }
382
383 bool cmState::GetIsGeneratorMultiConfig() const
384 {
385   return this->IsGeneratorMultiConfig;
386 }
387
388 void cmState::SetIsGeneratorMultiConfig(bool b)
389 {
390   this->IsGeneratorMultiConfig = b;
391 }
392
393 void cmState::AddBuiltinCommand(std::string const& name,
394                                 std::unique_ptr<cmCommand> command)
395 {
396   this->AddBuiltinCommand(name, cmLegacyCommandWrapper(std::move(command)));
397 }
398
399 void cmState::AddBuiltinCommand(std::string const& name, Command command)
400 {
401   assert(name == cmSystemTools::LowerCase(name));
402   assert(this->BuiltinCommands.find(name) == this->BuiltinCommands.end());
403   this->BuiltinCommands.emplace(name, std::move(command));
404 }
405
406 static bool InvokeBuiltinCommand(cmState::BuiltinCommand command,
407                                  std::vector<cmListFileArgument> const& args,
408                                  cmExecutionStatus& status)
409 {
410   cmMakefile& mf = status.GetMakefile();
411   std::vector<std::string> expandedArguments;
412   if (!mf.ExpandArguments(args, expandedArguments)) {
413     // There was an error expanding arguments.  It was already
414     // reported, so we can skip this command without error.
415     return true;
416   }
417   return command(expandedArguments, status);
418 }
419
420 void cmState::AddBuiltinCommand(std::string const& name,
421                                 BuiltinCommand command)
422 {
423   this->AddBuiltinCommand(
424     name,
425     [command](const std::vector<cmListFileArgument>& args,
426               cmExecutionStatus& status) -> bool {
427       return InvokeBuiltinCommand(command, args, status);
428     });
429 }
430
431 void cmState::AddFlowControlCommand(std::string const& name, Command command)
432 {
433   this->FlowControlCommands.insert(name);
434   this->AddBuiltinCommand(name, std::move(command));
435 }
436
437 void cmState::AddFlowControlCommand(std::string const& name,
438                                     BuiltinCommand command)
439 {
440   this->FlowControlCommands.insert(name);
441   this->AddBuiltinCommand(name, command);
442 }
443
444 void cmState::AddDisallowedCommand(std::string const& name,
445                                    BuiltinCommand command,
446                                    cmPolicies::PolicyID policy,
447                                    const char* message)
448 {
449   this->AddBuiltinCommand(
450     name,
451     [command, policy, message](const std::vector<cmListFileArgument>& args,
452                                cmExecutionStatus& status) -> bool {
453       cmMakefile& mf = status.GetMakefile();
454       switch (mf.GetPolicyStatus(policy)) {
455         case cmPolicies::WARN:
456           mf.IssueMessage(MessageType::AUTHOR_WARNING,
457                           cmPolicies::GetPolicyWarning(policy));
458           CM_FALLTHROUGH;
459         case cmPolicies::OLD:
460           break;
461         case cmPolicies::REQUIRED_IF_USED:
462         case cmPolicies::REQUIRED_ALWAYS:
463         case cmPolicies::NEW:
464           mf.IssueMessage(MessageType::FATAL_ERROR, message);
465           return true;
466       }
467       return InvokeBuiltinCommand(command, args, status);
468     });
469 }
470
471 void cmState::AddUnexpectedCommand(std::string const& name, const char* error)
472 {
473   this->AddBuiltinCommand(
474     name,
475     [name, error](std::vector<cmListFileArgument> const&,
476                   cmExecutionStatus& status) -> bool {
477       cmValue versionValue =
478         status.GetMakefile().GetDefinition("CMAKE_MINIMUM_REQUIRED_VERSION");
479       if (name == "endif" &&
480           (!versionValue || atof(versionValue->c_str()) <= 1.4)) {
481         return true;
482       }
483       status.SetError(error);
484       return false;
485     });
486 }
487
488 void cmState::AddUnexpectedFlowControlCommand(std::string const& name,
489                                               const char* error)
490 {
491   this->FlowControlCommands.insert(name);
492   this->AddUnexpectedCommand(name, error);
493 }
494
495 bool cmState::AddScriptedCommand(std::string const& name, BT<Command> command,
496                                  cmMakefile& mf)
497 {
498   std::string sName = cmSystemTools::LowerCase(name);
499
500   if (this->FlowControlCommands.count(sName)) {
501     mf.GetCMakeInstance()->IssueMessage(
502       MessageType::FATAL_ERROR,
503       cmStrCat("Built-in flow control command \"", sName,
504                "\" cannot be overridden."),
505       command.Backtrace);
506     cmSystemTools::SetFatalErrorOccurred();
507     return false;
508   }
509
510   // if the command already exists, give a new name to the old command.
511   if (Command oldCmd = this->GetCommandByExactName(sName)) {
512     this->ScriptedCommands["_" + sName] = oldCmd;
513   }
514
515   this->ScriptedCommands[sName] = std::move(command.Value);
516   return true;
517 }
518
519 cmState::Command cmState::GetCommand(std::string const& name) const
520 {
521   return this->GetCommandByExactName(cmSystemTools::LowerCase(name));
522 }
523
524 cmState::Command cmState::GetCommandByExactName(std::string const& name) const
525 {
526   auto pos = this->ScriptedCommands.find(name);
527   if (pos != this->ScriptedCommands.end()) {
528     return pos->second;
529   }
530   pos = this->BuiltinCommands.find(name);
531   if (pos != this->BuiltinCommands.end()) {
532     return pos->second;
533   }
534   return nullptr;
535 }
536
537 std::vector<std::string> cmState::GetCommandNames() const
538 {
539   std::vector<std::string> commandNames;
540   commandNames.reserve(this->BuiltinCommands.size() +
541                        this->ScriptedCommands.size());
542   for (auto const& bc : this->BuiltinCommands) {
543     commandNames.push_back(bc.first);
544   }
545   for (auto const& sc : this->ScriptedCommands) {
546     commandNames.push_back(sc.first);
547   }
548   std::sort(commandNames.begin(), commandNames.end());
549   commandNames.erase(std::unique(commandNames.begin(), commandNames.end()),
550                      commandNames.end());
551   return commandNames;
552 }
553
554 void cmState::RemoveBuiltinCommand(std::string const& name)
555 {
556   assert(name == cmSystemTools::LowerCase(name));
557   this->BuiltinCommands.erase(name);
558 }
559
560 void cmState::RemoveUserDefinedCommands()
561 {
562   this->ScriptedCommands.clear();
563 }
564
565 void cmState::SetGlobalProperty(const std::string& prop, const char* value)
566 {
567   this->GlobalProperties.SetProperty(prop, value);
568 }
569 void cmState::SetGlobalProperty(const std::string& prop, cmValue value)
570 {
571   this->GlobalProperties.SetProperty(prop, value);
572 }
573
574 void cmState::AppendGlobalProperty(const std::string& prop,
575                                    const std::string& value, bool asString)
576 {
577   this->GlobalProperties.AppendProperty(prop, value, asString);
578 }
579
580 cmValue cmState::GetGlobalProperty(const std::string& prop)
581 {
582   if (prop == "CACHE_VARIABLES") {
583     std::vector<std::string> cacheKeys = this->GetCacheEntryKeys();
584     this->SetGlobalProperty("CACHE_VARIABLES", cmJoin(cacheKeys, ";").c_str());
585   } else if (prop == "COMMANDS") {
586     std::vector<std::string> commands = this->GetCommandNames();
587     this->SetGlobalProperty("COMMANDS", cmJoin(commands, ";").c_str());
588   } else if (prop == "IN_TRY_COMPILE") {
589     this->SetGlobalProperty(
590       "IN_TRY_COMPILE",
591       this->StateProjectKind == ProjectKind::TryCompile ? "1" : "0");
592   } else if (prop == "GENERATOR_IS_MULTI_CONFIG") {
593     this->SetGlobalProperty("GENERATOR_IS_MULTI_CONFIG",
594                             this->IsGeneratorMultiConfig ? "1" : "0");
595   } else if (prop == "ENABLED_LANGUAGES") {
596     std::string langs;
597     langs = cmJoin(this->EnabledLanguages, ";");
598     this->SetGlobalProperty("ENABLED_LANGUAGES", langs.c_str());
599   } else if (prop == "CMAKE_ROLE") {
600     std::string mode = this->GetModeString();
601     this->SetGlobalProperty("CMAKE_ROLE", mode.c_str());
602   }
603 #define STRING_LIST_ELEMENT(F) ";" #F
604   if (prop == "CMAKE_C_KNOWN_FEATURES") {
605     static const std::string s_out(
606       &FOR_EACH_C_FEATURE(STRING_LIST_ELEMENT)[1]);
607     return cmValue(s_out);
608   }
609   if (prop == "CMAKE_C90_KNOWN_FEATURES") {
610     static const std::string s_out(
611       &FOR_EACH_C90_FEATURE(STRING_LIST_ELEMENT)[1]);
612     return cmValue(s_out);
613   }
614   if (prop == "CMAKE_C99_KNOWN_FEATURES") {
615     static const std::string s_out(
616       &FOR_EACH_C99_FEATURE(STRING_LIST_ELEMENT)[1]);
617     return cmValue(s_out);
618   }
619   if (prop == "CMAKE_C11_KNOWN_FEATURES") {
620     static const std::string s_out(
621       &FOR_EACH_C11_FEATURE(STRING_LIST_ELEMENT)[1]);
622     return cmValue(s_out);
623   }
624   if (prop == "CMAKE_CXX_KNOWN_FEATURES") {
625     static const std::string s_out(
626       &FOR_EACH_CXX_FEATURE(STRING_LIST_ELEMENT)[1]);
627     return cmValue(s_out);
628   }
629   if (prop == "CMAKE_CXX98_KNOWN_FEATURES") {
630     static const std::string s_out(
631       &FOR_EACH_CXX98_FEATURE(STRING_LIST_ELEMENT)[1]);
632     return cmValue(s_out);
633   }
634   if (prop == "CMAKE_CXX11_KNOWN_FEATURES") {
635     static const std::string s_out(
636       &FOR_EACH_CXX11_FEATURE(STRING_LIST_ELEMENT)[1]);
637     return cmValue(s_out);
638   }
639   if (prop == "CMAKE_CXX14_KNOWN_FEATURES") {
640     static const std::string s_out(
641       &FOR_EACH_CXX14_FEATURE(STRING_LIST_ELEMENT)[1]);
642     return cmValue(s_out);
643   }
644   if (prop == "CMAKE_CUDA_KNOWN_FEATURES") {
645     static const std::string s_out(
646       &FOR_EACH_CUDA_FEATURE(STRING_LIST_ELEMENT)[1]);
647     return cmValue(s_out);
648   }
649
650 #undef STRING_LIST_ELEMENT
651   return this->GlobalProperties.GetPropertyValue(prop);
652 }
653
654 bool cmState::GetGlobalPropertyAsBool(const std::string& prop)
655 {
656   return cmIsOn(this->GetGlobalProperty(prop));
657 }
658
659 void cmState::SetSourceDirectory(std::string const& sourceDirectory)
660 {
661   this->SourceDirectory = sourceDirectory;
662   cmSystemTools::ConvertToUnixSlashes(this->SourceDirectory);
663 }
664
665 std::string const& cmState::GetSourceDirectory() const
666 {
667   return this->SourceDirectory;
668 }
669
670 void cmState::SetBinaryDirectory(std::string const& binaryDirectory)
671 {
672   this->BinaryDirectory = binaryDirectory;
673   cmSystemTools::ConvertToUnixSlashes(this->BinaryDirectory);
674 }
675
676 void cmState::SetWindowsShell(bool windowsShell)
677 {
678   this->WindowsShell = windowsShell;
679 }
680
681 bool cmState::UseWindowsShell() const
682 {
683   return this->WindowsShell;
684 }
685
686 void cmState::SetWindowsVSIDE(bool windowsVSIDE)
687 {
688   this->WindowsVSIDE = windowsVSIDE;
689 }
690
691 bool cmState::UseWindowsVSIDE() const
692 {
693   return this->WindowsVSIDE;
694 }
695
696 void cmState::SetGhsMultiIDE(bool ghsMultiIDE)
697 {
698   this->GhsMultiIDE = ghsMultiIDE;
699 }
700
701 bool cmState::UseGhsMultiIDE() const
702 {
703   return this->GhsMultiIDE;
704 }
705
706 void cmState::SetWatcomWMake(bool watcomWMake)
707 {
708   this->WatcomWMake = watcomWMake;
709 }
710
711 bool cmState::UseWatcomWMake() const
712 {
713   return this->WatcomWMake;
714 }
715
716 void cmState::SetMinGWMake(bool minGWMake)
717 {
718   this->MinGWMake = minGWMake;
719 }
720
721 bool cmState::UseMinGWMake() const
722 {
723   return this->MinGWMake;
724 }
725
726 void cmState::SetNMake(bool nMake)
727 {
728   this->NMake = nMake;
729 }
730
731 bool cmState::UseNMake() const
732 {
733   return this->NMake;
734 }
735
736 void cmState::SetMSYSShell(bool mSYSShell)
737 {
738   this->MSYSShell = mSYSShell;
739 }
740
741 bool cmState::UseMSYSShell() const
742 {
743   return this->MSYSShell;
744 }
745
746 void cmState::SetNinjaMulti(bool ninjaMulti)
747 {
748   this->NinjaMulti = ninjaMulti;
749 }
750
751 bool cmState::UseNinjaMulti() const
752 {
753   return this->NinjaMulti;
754 }
755
756 unsigned int cmState::GetCacheMajorVersion() const
757 {
758   return this->CacheManager->GetCacheMajorVersion();
759 }
760
761 unsigned int cmState::GetCacheMinorVersion() const
762 {
763   return this->CacheManager->GetCacheMinorVersion();
764 }
765
766 cmState::Mode cmState::GetMode() const
767 {
768   return this->StateMode;
769 }
770
771 std::string cmState::GetModeString() const
772 {
773   return ModeToString(this->StateMode);
774 }
775
776 std::string cmState::ModeToString(cmState::Mode mode)
777 {
778   switch (mode) {
779     case Project:
780       return "PROJECT";
781     case Script:
782       return "SCRIPT";
783     case FindPackage:
784       return "FIND_PACKAGE";
785     case CTest:
786       return "CTEST";
787     case CPack:
788       return "CPACK";
789     case Unknown:
790       return "UNKNOWN";
791   }
792   return "UNKNOWN";
793 }
794
795 cmState::ProjectKind cmState::GetProjectKind() const
796 {
797   return this->StateProjectKind;
798 }
799
800 std::string const& cmState::GetBinaryDirectory() const
801 {
802   return this->BinaryDirectory;
803 }
804
805 cmStateSnapshot cmState::CreateBaseSnapshot()
806 {
807   cmStateDetail::PositionType pos =
808     this->SnapshotData.Push(this->SnapshotData.Root());
809   pos->DirectoryParent = this->SnapshotData.Root();
810   pos->ScopeParent = this->SnapshotData.Root();
811   pos->SnapshotType = cmStateEnums::BaseType;
812   pos->Keep = true;
813   pos->BuildSystemDirectory =
814     this->BuildsystemDirectory.Push(this->BuildsystemDirectory.Root());
815   pos->ExecutionListFile =
816     this->ExecutionListFiles.Push(this->ExecutionListFiles.Root());
817   pos->IncludeDirectoryPosition = 0;
818   pos->CompileDefinitionsPosition = 0;
819   pos->CompileOptionsPosition = 0;
820   pos->LinkOptionsPosition = 0;
821   pos->LinkDirectoriesPosition = 0;
822   pos->BuildSystemDirectory->DirectoryEnd = pos;
823   pos->Policies = this->PolicyStack.Root();
824   pos->PolicyRoot = this->PolicyStack.Root();
825   pos->PolicyScope = this->PolicyStack.Root();
826   assert(pos->Policies.IsValid());
827   assert(pos->PolicyRoot.IsValid());
828   pos->Vars = this->VarTree.Push(this->VarTree.Root());
829   assert(pos->Vars.IsValid());
830   pos->Parent = this->VarTree.Root();
831   pos->Root = this->VarTree.Root();
832   return { this, pos };
833 }
834
835 cmStateSnapshot cmState::CreateBuildsystemDirectorySnapshot(
836   cmStateSnapshot const& originSnapshot)
837 {
838   assert(originSnapshot.IsValid());
839   cmStateDetail::PositionType pos =
840     this->SnapshotData.Push(originSnapshot.Position);
841   pos->DirectoryParent = originSnapshot.Position;
842   pos->ScopeParent = originSnapshot.Position;
843   pos->SnapshotType = cmStateEnums::BuildsystemDirectoryType;
844   pos->Keep = true;
845   pos->BuildSystemDirectory = this->BuildsystemDirectory.Push(
846     originSnapshot.Position->BuildSystemDirectory);
847   pos->ExecutionListFile =
848     this->ExecutionListFiles.Push(originSnapshot.Position->ExecutionListFile);
849   pos->BuildSystemDirectory->DirectoryEnd = pos;
850   pos->Policies = originSnapshot.Position->Policies;
851   pos->PolicyRoot = originSnapshot.Position->Policies;
852   pos->PolicyScope = originSnapshot.Position->Policies;
853   assert(pos->Policies.IsValid());
854   assert(pos->PolicyRoot.IsValid());
855
856   cmLinkedTree<cmDefinitions>::iterator origin = originSnapshot.Position->Vars;
857   pos->Parent = origin;
858   pos->Root = origin;
859   pos->Vars = this->VarTree.Push(origin);
860
861   cmStateSnapshot snapshot = cmStateSnapshot(this, pos);
862   originSnapshot.Position->BuildSystemDirectory->Children.push_back(snapshot);
863   snapshot.SetDefaultDefinitions();
864   snapshot.InitializeFromParent();
865   snapshot.SetDirectoryDefinitions();
866   return snapshot;
867 }
868
869 cmStateSnapshot cmState::CreateDeferCallSnapshot(
870   cmStateSnapshot const& originSnapshot, std::string const& fileName)
871 {
872   cmStateDetail::PositionType pos =
873     this->SnapshotData.Push(originSnapshot.Position, *originSnapshot.Position);
874   pos->SnapshotType = cmStateEnums::DeferCallType;
875   pos->Keep = false;
876   pos->ExecutionListFile = this->ExecutionListFiles.Push(
877     originSnapshot.Position->ExecutionListFile, fileName);
878   assert(originSnapshot.Position->Vars.IsValid());
879   pos->BuildSystemDirectory->DirectoryEnd = pos;
880   pos->PolicyScope = originSnapshot.Position->Policies;
881   return { this, pos };
882 }
883
884 cmStateSnapshot cmState::CreateFunctionCallSnapshot(
885   cmStateSnapshot const& originSnapshot, std::string const& fileName)
886 {
887   cmStateDetail::PositionType pos =
888     this->SnapshotData.Push(originSnapshot.Position, *originSnapshot.Position);
889   pos->ScopeParent = originSnapshot.Position;
890   pos->SnapshotType = cmStateEnums::FunctionCallType;
891   pos->Keep = false;
892   pos->ExecutionListFile = this->ExecutionListFiles.Push(
893     originSnapshot.Position->ExecutionListFile, fileName);
894   pos->BuildSystemDirectory->DirectoryEnd = pos;
895   pos->PolicyScope = originSnapshot.Position->Policies;
896   assert(originSnapshot.Position->Vars.IsValid());
897   cmLinkedTree<cmDefinitions>::iterator origin = originSnapshot.Position->Vars;
898   pos->Parent = origin;
899   pos->Vars = this->VarTree.Push(origin);
900   return { this, pos };
901 }
902
903 cmStateSnapshot cmState::CreateMacroCallSnapshot(
904   cmStateSnapshot const& originSnapshot, std::string const& fileName)
905 {
906   cmStateDetail::PositionType pos =
907     this->SnapshotData.Push(originSnapshot.Position, *originSnapshot.Position);
908   pos->SnapshotType = cmStateEnums::MacroCallType;
909   pos->Keep = false;
910   pos->ExecutionListFile = this->ExecutionListFiles.Push(
911     originSnapshot.Position->ExecutionListFile, fileName);
912   assert(originSnapshot.Position->Vars.IsValid());
913   pos->BuildSystemDirectory->DirectoryEnd = pos;
914   pos->PolicyScope = originSnapshot.Position->Policies;
915   return { this, pos };
916 }
917
918 cmStateSnapshot cmState::CreateIncludeFileSnapshot(
919   cmStateSnapshot const& originSnapshot, std::string const& fileName)
920 {
921   cmStateDetail::PositionType pos =
922     this->SnapshotData.Push(originSnapshot.Position, *originSnapshot.Position);
923   pos->SnapshotType = cmStateEnums::IncludeFileType;
924   pos->Keep = true;
925   pos->ExecutionListFile = this->ExecutionListFiles.Push(
926     originSnapshot.Position->ExecutionListFile, fileName);
927   assert(originSnapshot.Position->Vars.IsValid());
928   pos->BuildSystemDirectory->DirectoryEnd = pos;
929   pos->PolicyScope = originSnapshot.Position->Policies;
930   return { this, pos };
931 }
932
933 cmStateSnapshot cmState::CreateVariableScopeSnapshot(
934   cmStateSnapshot const& originSnapshot)
935 {
936   cmStateDetail::PositionType pos =
937     this->SnapshotData.Push(originSnapshot.Position, *originSnapshot.Position);
938   pos->ScopeParent = originSnapshot.Position;
939   pos->SnapshotType = cmStateEnums::VariableScopeType;
940   pos->Keep = false;
941   pos->PolicyScope = originSnapshot.Position->Policies;
942   assert(originSnapshot.Position->Vars.IsValid());
943
944   cmLinkedTree<cmDefinitions>::iterator origin = originSnapshot.Position->Vars;
945   pos->Parent = origin;
946   pos->Vars = this->VarTree.Push(origin);
947   assert(pos->Vars.IsValid());
948   return { this, pos };
949 }
950
951 cmStateSnapshot cmState::CreateInlineListFileSnapshot(
952   cmStateSnapshot const& originSnapshot, std::string const& fileName)
953 {
954   cmStateDetail::PositionType pos =
955     this->SnapshotData.Push(originSnapshot.Position, *originSnapshot.Position);
956   pos->SnapshotType = cmStateEnums::InlineListFileType;
957   pos->Keep = true;
958   pos->ExecutionListFile = this->ExecutionListFiles.Push(
959     originSnapshot.Position->ExecutionListFile, fileName);
960   pos->BuildSystemDirectory->DirectoryEnd = pos;
961   pos->PolicyScope = originSnapshot.Position->Policies;
962   return { this, pos };
963 }
964
965 cmStateSnapshot cmState::CreatePolicyScopeSnapshot(
966   cmStateSnapshot const& originSnapshot)
967 {
968   cmStateDetail::PositionType pos =
969     this->SnapshotData.Push(originSnapshot.Position, *originSnapshot.Position);
970   pos->SnapshotType = cmStateEnums::PolicyScopeType;
971   pos->Keep = false;
972   pos->BuildSystemDirectory->DirectoryEnd = pos;
973   pos->PolicyScope = originSnapshot.Position->Policies;
974   return { this, pos };
975 }
976
977 cmStateSnapshot cmState::Pop(cmStateSnapshot const& originSnapshot)
978 {
979   cmStateDetail::PositionType pos = originSnapshot.Position;
980   cmStateDetail::PositionType prevPos = pos;
981   ++prevPos;
982   prevPos->IncludeDirectoryPosition =
983     prevPos->BuildSystemDirectory->IncludeDirectories.size();
984   prevPos->CompileDefinitionsPosition =
985     prevPos->BuildSystemDirectory->CompileDefinitions.size();
986   prevPos->CompileOptionsPosition =
987     prevPos->BuildSystemDirectory->CompileOptions.size();
988   prevPos->LinkOptionsPosition =
989     prevPos->BuildSystemDirectory->LinkOptions.size();
990   prevPos->LinkDirectoriesPosition =
991     prevPos->BuildSystemDirectory->LinkDirectories.size();
992   prevPos->BuildSystemDirectory->DirectoryEnd = prevPos;
993
994   if (!pos->Keep && this->SnapshotData.IsLast(pos)) {
995     if (pos->Vars != prevPos->Vars) {
996       assert(this->VarTree.IsLast(pos->Vars));
997       this->VarTree.Pop(pos->Vars);
998     }
999     if (pos->ExecutionListFile != prevPos->ExecutionListFile) {
1000       assert(this->ExecutionListFiles.IsLast(pos->ExecutionListFile));
1001       this->ExecutionListFiles.Pop(pos->ExecutionListFile);
1002     }
1003     this->SnapshotData.Pop(pos);
1004   }
1005
1006   return { this, prevPos };
1007 }
1008
1009 static bool ParseEntryWithoutType(const std::string& entry, std::string& var,
1010                                   std::string& value)
1011 {
1012   // input line is:         key=value
1013   static cmsys::RegularExpression reg(
1014     "^([^=]*)=(.*[^\r\t ]|[\r\t ]*)[\r\t ]*$");
1015   // input line is:         "key"=value
1016   static cmsys::RegularExpression regQuoted(
1017     "^\"([^\"]*)\"=(.*[^\r\t ]|[\r\t ]*)[\r\t ]*$");
1018   bool flag = false;
1019   if (regQuoted.find(entry)) {
1020     var = regQuoted.match(1);
1021     value = regQuoted.match(2);
1022     flag = true;
1023   } else if (reg.find(entry)) {
1024     var = reg.match(1);
1025     value = reg.match(2);
1026     flag = true;
1027   }
1028
1029   // if value is enclosed in single quotes ('foo') then remove them
1030   // it is used to enclose trailing space or tab
1031   if (flag && value.size() >= 2 && value.front() == '\'' &&
1032       value.back() == '\'') {
1033     value = value.substr(1, value.size() - 2);
1034   }
1035
1036   return flag;
1037 }
1038
1039 bool cmState::ParseCacheEntry(const std::string& entry, std::string& var,
1040                               std::string& value,
1041                               cmStateEnums::CacheEntryType& type)
1042 {
1043   // input line is:         key:type=value
1044   static cmsys::RegularExpression reg(
1045     "^([^=:]*):([^=]*)=(.*[^\r\t ]|[\r\t ]*)[\r\t ]*$");
1046   // input line is:         "key":type=value
1047   static cmsys::RegularExpression regQuoted(
1048     "^\"([^\"]*)\":([^=]*)=(.*[^\r\t ]|[\r\t ]*)[\r\t ]*$");
1049   bool flag = false;
1050   if (regQuoted.find(entry)) {
1051     var = regQuoted.match(1);
1052     type = cmState::StringToCacheEntryType(regQuoted.match(2));
1053     value = regQuoted.match(3);
1054     flag = true;
1055   } else if (reg.find(entry)) {
1056     var = reg.match(1);
1057     type = cmState::StringToCacheEntryType(reg.match(2));
1058     value = reg.match(3);
1059     flag = true;
1060   }
1061
1062   // if value is enclosed in single quotes ('foo') then remove them
1063   // it is used to enclose trailing space or tab
1064   if (flag && value.size() >= 2 && value.front() == '\'' &&
1065       value.back() == '\'') {
1066     value = value.substr(1, value.size() - 2);
1067   }
1068
1069   if (!flag) {
1070     return ParseEntryWithoutType(entry, var, value);
1071   }
1072
1073   return flag;
1074 }
1075
1076 cmState::Command cmState::GetDependencyProviderCommand(
1077   cmDependencyProvider::Method method) const
1078 {
1079   return (this->DependencyProvider &&
1080           this->DependencyProvider->SupportsMethod(method))
1081     ? this->GetCommand(this->DependencyProvider->GetCommand())
1082     : Command{};
1083 }