cmState.cxx 32 KB

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