cmState.cxx 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524
  1. /*============================================================================
  2. CMake - Cross Platform Makefile Generator
  3. Copyright 2015 Stephen Kelly <[email protected]>
  4. Distributed under the OSI-approved BSD License (the "License");
  5. see accompanying file Copyright.txt for details.
  6. This software is distributed WITHOUT ANY WARRANTY; without even the
  7. implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  8. See the License for more information.
  9. ============================================================================*/
  10. #include "cmState.h"
  11. #include "cmake.h"
  12. #include "cmCacheManager.h"
  13. #include "cmCommand.h"
  14. #include "cmAlgorithms.h"
  15. #include <assert.h>
  16. cmState::cmState(cmake* cm)
  17. : CMakeInstance(cm),
  18. IsInTryCompile(false)
  19. {
  20. this->Initialize();
  21. }
  22. cmState::~cmState()
  23. {
  24. cmDeleteAll(this->Commands);
  25. }
  26. const char* cmCacheEntryTypes[] =
  27. { "BOOL",
  28. "PATH",
  29. "FILEPATH",
  30. "STRING",
  31. "INTERNAL",
  32. "STATIC",
  33. "UNINITIALIZED",
  34. 0
  35. };
  36. const char*
  37. cmState::CacheEntryTypeToString(cmState::CacheEntryType type)
  38. {
  39. if ( type > 6 )
  40. {
  41. return cmCacheEntryTypes[6];
  42. }
  43. return cmCacheEntryTypes[type];
  44. }
  45. cmState::CacheEntryType
  46. cmState::StringToCacheEntryType(const char* s)
  47. {
  48. int i = 0;
  49. while(cmCacheEntryTypes[i])
  50. {
  51. if(strcmp(s, cmCacheEntryTypes[i]) == 0)
  52. {
  53. return static_cast<cmState::CacheEntryType>(i);
  54. }
  55. ++i;
  56. }
  57. return STRING;
  58. }
  59. bool cmState::IsCacheEntryType(std::string const& key)
  60. {
  61. for(int i=0; cmCacheEntryTypes[i]; ++i)
  62. {
  63. if(strcmp(key.c_str(), cmCacheEntryTypes[i]) == 0)
  64. {
  65. return true;
  66. }
  67. }
  68. return false;
  69. }
  70. std::vector<std::string> cmState::GetCacheEntryKeys() const
  71. {
  72. std::vector<std::string> definitions;
  73. definitions.reserve(this->CMakeInstance->GetCacheManager()->GetSize());
  74. cmCacheManager::CacheIterator cit =
  75. this->CMakeInstance->GetCacheManager()->GetCacheIterator();
  76. for ( cit.Begin(); !cit.IsAtEnd(); cit.Next() )
  77. {
  78. definitions.push_back(cit.GetName());
  79. }
  80. return definitions;
  81. }
  82. const char* cmState::GetCacheEntryValue(std::string const& key) const
  83. {
  84. cmCacheManager::CacheEntry* e = this->CMakeInstance->GetCacheManager()
  85. ->GetCacheEntry(key);
  86. if (!e)
  87. {
  88. return 0;
  89. }
  90. return e->Value.c_str();
  91. }
  92. const char*
  93. cmState::GetInitializedCacheValue(std::string const& key) const
  94. {
  95. return this->CMakeInstance->GetCacheManager()->GetInitializedCacheValue(key);
  96. }
  97. cmState::CacheEntryType
  98. cmState::GetCacheEntryType(std::string const& key) const
  99. {
  100. cmCacheManager::CacheIterator it =
  101. this->CMakeInstance->GetCacheManager()->GetCacheIterator(key.c_str());
  102. return it.GetType();
  103. }
  104. void cmState::SetCacheEntryValue(std::string const& key,
  105. std::string const& value)
  106. {
  107. this->CMakeInstance->GetCacheManager()->SetCacheEntryValue(key, value);
  108. }
  109. void cmState::SetCacheEntryProperty(std::string const& key,
  110. std::string const& propertyName,
  111. std::string const& value)
  112. {
  113. cmCacheManager::CacheIterator it =
  114. this->CMakeInstance->GetCacheManager()->GetCacheIterator(key.c_str());
  115. it.SetProperty(propertyName, value.c_str());
  116. }
  117. void cmState::SetCacheEntryBoolProperty(std::string const& key,
  118. std::string const& propertyName,
  119. bool value)
  120. {
  121. cmCacheManager::CacheIterator it =
  122. this->CMakeInstance->GetCacheManager()->GetCacheIterator(key.c_str());
  123. it.SetProperty(propertyName, value);
  124. }
  125. const char* cmState::GetCacheEntryProperty(std::string const& key,
  126. std::string const& propertyName)
  127. {
  128. cmCacheManager::CacheIterator it = this->CMakeInstance->GetCacheManager()
  129. ->GetCacheIterator(key.c_str());
  130. if (!it.PropertyExists(propertyName))
  131. {
  132. return 0;
  133. }
  134. return it.GetProperty(propertyName);
  135. }
  136. bool cmState::GetCacheEntryPropertyAsBool(std::string const& key,
  137. std::string const& propertyName)
  138. {
  139. return this->CMakeInstance->GetCacheManager()
  140. ->GetCacheIterator(key.c_str()).GetPropertyAsBool(propertyName);
  141. }
  142. void cmState::AddCacheEntry(const std::string& key, const char* value,
  143. const char* helpString,
  144. cmState::CacheEntryType type)
  145. {
  146. this->CMakeInstance->GetCacheManager()->AddCacheEntry(key, value,
  147. helpString, type);
  148. }
  149. void cmState::RemoveCacheEntry(std::string const& key)
  150. {
  151. this->CMakeInstance->GetCacheManager()->RemoveCacheEntry(key);
  152. }
  153. void cmState::AppendCacheEntryProperty(const std::string& key,
  154. const std::string& property,
  155. const std::string& value,
  156. bool asString)
  157. {
  158. this->CMakeInstance->GetCacheManager()
  159. ->GetCacheIterator(key.c_str()).AppendProperty(property,
  160. value.c_str(),
  161. asString);
  162. }
  163. void cmState::RemoveCacheEntryProperty(std::string const& key,
  164. std::string const& propertyName)
  165. {
  166. this->CMakeInstance->GetCacheManager()
  167. ->GetCacheIterator(key.c_str()).SetProperty(propertyName, (void*)0);
  168. }
  169. void cmState::Initialize()
  170. {
  171. this->GlobalProperties.clear();
  172. this->PropertyDefinitions.clear();
  173. this->Locations.clear();
  174. this->OutputLocations.clear();
  175. this->ParentPositions.clear();
  176. this->CreateSnapshot(Snapshot());
  177. this->DefineProperty
  178. ("RULE_LAUNCH_COMPILE", cmProperty::DIRECTORY,
  179. "", "", true);
  180. this->DefineProperty
  181. ("RULE_LAUNCH_LINK", cmProperty::DIRECTORY,
  182. "", "", true);
  183. this->DefineProperty
  184. ("RULE_LAUNCH_CUSTOM", cmProperty::DIRECTORY,
  185. "", "", true);
  186. this->DefineProperty
  187. ("RULE_LAUNCH_COMPILE", cmProperty::TARGET,
  188. "", "", true);
  189. this->DefineProperty
  190. ("RULE_LAUNCH_LINK", cmProperty::TARGET,
  191. "", "", true);
  192. this->DefineProperty
  193. ("RULE_LAUNCH_CUSTOM", cmProperty::TARGET,
  194. "", "", true);
  195. }
  196. void cmState::DefineProperty(const std::string& name,
  197. cmProperty::ScopeType scope,
  198. const char *ShortDescription,
  199. const char *FullDescription,
  200. bool chained)
  201. {
  202. this->PropertyDefinitions[scope].DefineProperty(name,scope,ShortDescription,
  203. FullDescription,
  204. chained);
  205. }
  206. cmPropertyDefinition *cmState
  207. ::GetPropertyDefinition(const std::string& name,
  208. cmProperty::ScopeType scope)
  209. {
  210. if (this->IsPropertyDefined(name,scope))
  211. {
  212. return &(this->PropertyDefinitions[scope][name]);
  213. }
  214. return 0;
  215. }
  216. bool cmState::IsPropertyDefined(const std::string& name,
  217. cmProperty::ScopeType scope)
  218. {
  219. return this->PropertyDefinitions[scope].IsPropertyDefined(name);
  220. }
  221. bool cmState::IsPropertyChained(const std::string& name,
  222. cmProperty::ScopeType scope)
  223. {
  224. return this->PropertyDefinitions[scope].IsPropertyChained(name);
  225. }
  226. void cmState::SetLanguageEnabled(std::string const& l)
  227. {
  228. std::vector<std::string>::iterator it =
  229. std::lower_bound(this->EnabledLanguages.begin(),
  230. this->EnabledLanguages.end(), l);
  231. if (it == this->EnabledLanguages.end() || *it != l)
  232. {
  233. this->EnabledLanguages.insert(it, l);
  234. }
  235. }
  236. bool cmState::GetLanguageEnabled(std::string const& l) const
  237. {
  238. return std::binary_search(this->EnabledLanguages.begin(),
  239. this->EnabledLanguages.end(), l);
  240. }
  241. std::vector<std::string> cmState::GetEnabledLanguages() const
  242. {
  243. return this->EnabledLanguages;
  244. }
  245. void cmState::SetEnabledLanguages(std::vector<std::string> const& langs)
  246. {
  247. this->EnabledLanguages = langs;
  248. }
  249. void cmState::ClearEnabledLanguages()
  250. {
  251. this->EnabledLanguages.clear();
  252. }
  253. bool cmState::GetIsInTryCompile() const
  254. {
  255. return this->IsInTryCompile;
  256. }
  257. void cmState::SetIsInTryCompile(bool b)
  258. {
  259. this->IsInTryCompile = b;
  260. }
  261. void cmState::RenameCommand(std::string const& oldName,
  262. std::string const& newName)
  263. {
  264. // if the command already exists, free the old one
  265. std::string sOldName = cmSystemTools::LowerCase(oldName);
  266. std::string sNewName = cmSystemTools::LowerCase(newName);
  267. std::map<std::string, cmCommand*>::iterator pos =
  268. this->Commands.find(sOldName);
  269. if ( pos == this->Commands.end() )
  270. {
  271. return;
  272. }
  273. cmCommand* cmd = pos->second;
  274. pos = this->Commands.find(sNewName);
  275. if (pos != this->Commands.end())
  276. {
  277. delete pos->second;
  278. this->Commands.erase(pos);
  279. }
  280. this->Commands.insert(std::make_pair(sNewName, cmd));
  281. pos = this->Commands.find(sOldName);
  282. this->Commands.erase(pos);
  283. }
  284. void cmState::AddCommand(cmCommand* command)
  285. {
  286. std::string name = cmSystemTools::LowerCase(command->GetName());
  287. // if the command already exists, free the old one
  288. std::map<std::string, cmCommand*>::iterator pos = this->Commands.find(name);
  289. if (pos != this->Commands.end())
  290. {
  291. delete pos->second;
  292. this->Commands.erase(pos);
  293. }
  294. this->Commands.insert(std::make_pair(name, command));
  295. }
  296. void cmState::RemoveUnscriptableCommands()
  297. {
  298. std::vector<std::string> unscriptableCommands;
  299. for (std::map<std::string, cmCommand*>::iterator
  300. pos = this->Commands.begin();
  301. pos != this->Commands.end(); )
  302. {
  303. if (!pos->second->IsScriptable())
  304. {
  305. delete pos->second;
  306. this->Commands.erase(pos++);
  307. }
  308. else
  309. {
  310. ++pos;
  311. }
  312. }
  313. }
  314. cmCommand* cmState::GetCommand(std::string const& name) const
  315. {
  316. cmCommand* command = 0;
  317. std::string sName = cmSystemTools::LowerCase(name);
  318. std::map<std::string, cmCommand*>::const_iterator pos =
  319. this->Commands.find(sName);
  320. if (pos != this->Commands.end())
  321. {
  322. command = (*pos).second;
  323. }
  324. return command;
  325. }
  326. std::vector<std::string> cmState::GetCommandNames() const
  327. {
  328. std::vector<std::string> commandNames;
  329. commandNames.reserve(this->Commands.size());
  330. std::map<std::string, cmCommand*>::const_iterator cmds
  331. = this->Commands.begin();
  332. for ( ; cmds != this->Commands.end(); ++ cmds )
  333. {
  334. commandNames.push_back(cmds->first);
  335. }
  336. return commandNames;
  337. }
  338. void cmState::RemoveUserDefinedCommands()
  339. {
  340. for(std::map<std::string, cmCommand*>::iterator j = this->Commands.begin();
  341. j != this->Commands.end(); )
  342. {
  343. if (j->second->IsA("cmMacroHelperCommand") ||
  344. j->second->IsA("cmFunctionHelperCommand"))
  345. {
  346. delete j->second;
  347. this->Commands.erase(j++);
  348. }
  349. else
  350. {
  351. ++j;
  352. }
  353. }
  354. }
  355. void cmState::SetGlobalProperty(const std::string& prop, const char* value)
  356. {
  357. this->GlobalProperties.SetProperty(prop, value, cmProperty::GLOBAL);
  358. }
  359. void cmState::AppendGlobalProperty(const std::string& prop,
  360. const char* value, bool asString)
  361. {
  362. this->GlobalProperties.AppendProperty(prop, value,
  363. cmProperty::GLOBAL, asString);
  364. }
  365. const char *cmState::GetGlobalProperty(const std::string& prop)
  366. {
  367. // watch for special properties
  368. std::string output = "";
  369. if ( prop == "CACHE_VARIABLES" )
  370. {
  371. std::vector<std::string> cacheKeys = this->GetCacheEntryKeys();
  372. this->SetGlobalProperty("CACHE_VARIABLES", cmJoin(cacheKeys, ";").c_str());
  373. }
  374. else if ( prop == "COMMANDS" )
  375. {
  376. std::vector<std::string> commands = this->GetCommandNames();
  377. this->SetGlobalProperty("COMMANDS", cmJoin(commands, ";").c_str());
  378. }
  379. else if ( prop == "IN_TRY_COMPILE" )
  380. {
  381. this->SetGlobalProperty("IN_TRY_COMPILE",
  382. this->IsInTryCompile ? "1" : "0");
  383. }
  384. else if ( prop == "ENABLED_LANGUAGES" )
  385. {
  386. std::string langs;
  387. langs = cmJoin(this->EnabledLanguages, ";");
  388. this->SetGlobalProperty("ENABLED_LANGUAGES", langs.c_str());
  389. }
  390. #define STRING_LIST_ELEMENT(F) ";" #F
  391. if (prop == "CMAKE_C_KNOWN_FEATURES")
  392. {
  393. return FOR_EACH_C_FEATURE(STRING_LIST_ELEMENT) + 1;
  394. }
  395. if (prop == "CMAKE_CXX_KNOWN_FEATURES")
  396. {
  397. return FOR_EACH_CXX_FEATURE(STRING_LIST_ELEMENT) + 1;
  398. }
  399. #undef STRING_LIST_ELEMENT
  400. bool dummy = false;
  401. return this->GlobalProperties.GetPropertyValue(prop, cmProperty::GLOBAL,
  402. dummy);
  403. }
  404. bool cmState::GetGlobalPropertyAsBool(const std::string& prop)
  405. {
  406. return cmSystemTools::IsOn(this->GetGlobalProperty(prop));
  407. }
  408. void cmState::SetSourceDirectory(std::string const& sourceDirectory)
  409. {
  410. this->SourceDirectory = sourceDirectory;
  411. cmSystemTools::ConvertToUnixSlashes(this->SourceDirectory);
  412. }
  413. const char* cmState::GetSourceDirectory() const
  414. {
  415. return this->SourceDirectory.c_str();
  416. }
  417. void cmState::SetBinaryDirectory(std::string const& binaryDirectory)
  418. {
  419. this->BinaryDirectory = binaryDirectory;
  420. cmSystemTools::ConvertToUnixSlashes(this->BinaryDirectory);
  421. }
  422. const char* cmState::GetBinaryDirectory() const
  423. {
  424. return this->BinaryDirectory.c_str();
  425. }
  426. cmState::Snapshot cmState::CreateSnapshot(Snapshot originSnapshot)
  427. {
  428. PositionType pos = this->ParentPositions.size();
  429. this->ParentPositions.push_back(originSnapshot.Position);
  430. this->Locations.resize(this->Locations.size() + 1);
  431. this->OutputLocations.resize(this->OutputLocations.size() + 1);
  432. return cmState::Snapshot(this, pos);
  433. }
  434. cmState::Snapshot::Snapshot(cmState* state, PositionType position)
  435. : State(state),
  436. Position(position)
  437. {
  438. }
  439. const char* cmState::Snapshot::GetCurrentSourceDirectory() const
  440. {
  441. return this->State->Locations[this->Position].c_str();
  442. }
  443. void cmState::Snapshot::SetCurrentSourceDirectory(std::string const& dir)
  444. {
  445. assert(this->State->Locations.size() > this->Position);
  446. this->State->Locations[this->Position] = dir;
  447. cmSystemTools::ConvertToUnixSlashes(
  448. this->State->Locations[this->Position]);
  449. this->State->Locations[this->Position] =
  450. cmSystemTools::CollapseFullPath(this->State->Locations[this->Position]);
  451. }
  452. const char* cmState::Snapshot::GetCurrentBinaryDirectory() const
  453. {
  454. return this->State->OutputLocations[this->Position].c_str();
  455. }
  456. void cmState::Snapshot::SetCurrentBinaryDirectory(std::string const& dir)
  457. {
  458. assert(this->State->OutputLocations.size() > this->Position);
  459. this->State->OutputLocations[this->Position] = dir;
  460. cmSystemTools::ConvertToUnixSlashes(
  461. this->State->OutputLocations[this->Position]);
  462. this->State->OutputLocations[this->Position] =
  463. cmSystemTools::CollapseFullPath(
  464. this->State->OutputLocations[this->Position]);
  465. }