cmCacheManager.cxx 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901
  1. /*============================================================================
  2. CMake - Cross Platform Makefile Generator
  3. Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
  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 "cmCacheManager.h"
  11. #include "cmSystemTools.h"
  12. #include "cmGeneratedFileStream.h"
  13. #include "cmMakefile.h"
  14. #include "cmake.h"
  15. #include "cmVersion.h"
  16. #include <cmsys/Directory.hxx>
  17. #include <cmsys/Glob.hxx>
  18. #include <cmsys/FStream.hxx>
  19. #include <cmsys/RegularExpression.hxx>
  20. const char* cmCacheManagerTypes[] =
  21. { "BOOL",
  22. "PATH",
  23. "FILEPATH",
  24. "STRING",
  25. "INTERNAL",
  26. "STATIC",
  27. "UNINITIALIZED",
  28. 0
  29. };
  30. cmCacheManager::cmCacheManager(cmake* cm)
  31. {
  32. this->CacheMajorVersion = 0;
  33. this->CacheMinorVersion = 0;
  34. this->CMakeInstance = cm;
  35. }
  36. const char* cmCacheManager::TypeToString(cmCacheManager::CacheEntryType type)
  37. {
  38. if ( type > 6 )
  39. {
  40. return cmCacheManagerTypes[6];
  41. }
  42. return cmCacheManagerTypes[type];
  43. }
  44. cmCacheManager::CacheEntryType cmCacheManager::StringToType(const char* s)
  45. {
  46. int i = 0;
  47. while(cmCacheManagerTypes[i])
  48. {
  49. if(strcmp(s, cmCacheManagerTypes[i]) == 0)
  50. {
  51. return static_cast<CacheEntryType>(i);
  52. }
  53. ++i;
  54. }
  55. return STRING;
  56. }
  57. bool cmCacheManager::IsType(const char* s)
  58. {
  59. for(int i=0; cmCacheManagerTypes[i]; ++i)
  60. {
  61. if(strcmp(s, cmCacheManagerTypes[i]) == 0)
  62. {
  63. return true;
  64. }
  65. }
  66. return false;
  67. }
  68. bool cmCacheManager::LoadCache(const std::string& path)
  69. {
  70. std::set<std::string> emptySet;
  71. return this->LoadCache(path, true, emptySet, emptySet);
  72. }
  73. static bool ParseEntryWithoutType(const std::string& entry,
  74. std::string& var,
  75. std::string& value)
  76. {
  77. // input line is: key=value
  78. static cmsys::RegularExpression reg(
  79. "^([^=]*)=(.*[^\r\t ]|[\r\t ]*)[\r\t ]*$");
  80. // input line is: "key"=value
  81. static cmsys::RegularExpression regQuoted(
  82. "^\"([^\"]*)\"=(.*[^\r\t ]|[\r\t ]*)[\r\t ]*$");
  83. bool flag = false;
  84. if(regQuoted.find(entry))
  85. {
  86. var = regQuoted.match(1);
  87. value = regQuoted.match(2);
  88. flag = true;
  89. }
  90. else if (reg.find(entry))
  91. {
  92. var = reg.match(1);
  93. value = reg.match(2);
  94. flag = true;
  95. }
  96. // if value is enclosed in single quotes ('foo') then remove them
  97. // it is used to enclose trailing space or tab
  98. if (flag &&
  99. value.size() >= 2 &&
  100. value[0] == '\'' &&
  101. value[value.size() - 1] == '\'')
  102. {
  103. value = value.substr(1,
  104. value.size() - 2);
  105. }
  106. return flag;
  107. }
  108. bool cmCacheManager::ParseEntry(const std::string& entry,
  109. std::string& var,
  110. std::string& value,
  111. CacheEntryType& type)
  112. {
  113. // input line is: key:type=value
  114. static cmsys::RegularExpression reg(
  115. "^([^=:]*):([^=]*)=(.*[^\r\t ]|[\r\t ]*)[\r\t ]*$");
  116. // input line is: "key":type=value
  117. static cmsys::RegularExpression regQuoted(
  118. "^\"([^\"]*)\":([^=]*)=(.*[^\r\t ]|[\r\t ]*)[\r\t ]*$");
  119. bool flag = false;
  120. if(regQuoted.find(entry))
  121. {
  122. var = regQuoted.match(1);
  123. type = cmCacheManager::StringToType(regQuoted.match(2).c_str());
  124. value = regQuoted.match(3);
  125. flag = true;
  126. }
  127. else if (reg.find(entry))
  128. {
  129. var = reg.match(1);
  130. type = cmCacheManager::StringToType(reg.match(2).c_str());
  131. value = reg.match(3);
  132. flag = true;
  133. }
  134. // if value is enclosed in single quotes ('foo') then remove them
  135. // it is used to enclose trailing space or tab
  136. if (flag &&
  137. value.size() >= 2 &&
  138. value[0] == '\'' &&
  139. value[value.size() - 1] == '\'')
  140. {
  141. value = value.substr(1,
  142. value.size() - 2);
  143. }
  144. if (!flag)
  145. {
  146. return ParseEntryWithoutType(entry, var, value);
  147. }
  148. return flag;
  149. }
  150. void cmCacheManager::CleanCMakeFiles(const std::string& path)
  151. {
  152. std::string glob = path;
  153. glob += cmake::GetCMakeFilesDirectory();
  154. glob += "/*.cmake";
  155. cmsys::Glob globIt;
  156. globIt.FindFiles(glob);
  157. std::vector<std::string> files = globIt.GetFiles();
  158. std::for_each(files.begin(), files.end(), cmSystemTools::RemoveFile);
  159. }
  160. bool cmCacheManager::LoadCache(const std::string& path,
  161. bool internal,
  162. std::set<std::string>& excludes,
  163. std::set<std::string>& includes)
  164. {
  165. std::string cacheFile = path;
  166. cacheFile += "/CMakeCache.txt";
  167. // clear the old cache, if we are reading in internal values
  168. if ( internal )
  169. {
  170. this->Cache.clear();
  171. }
  172. if(!cmSystemTools::FileExists(cacheFile.c_str()))
  173. {
  174. this->CleanCMakeFiles(path);
  175. return false;
  176. }
  177. cmsys::ifstream fin(cacheFile.c_str());
  178. if(!fin)
  179. {
  180. return false;
  181. }
  182. const char *realbuffer;
  183. std::string buffer;
  184. std::string entryKey;
  185. while(fin)
  186. {
  187. // Format is key:type=value
  188. std::string helpString;
  189. CacheEntry e;
  190. e.Properties.SetCMakeInstance(this->CMakeInstance);
  191. cmSystemTools::GetLineFromStream(fin, buffer);
  192. realbuffer = buffer.c_str();
  193. while(*realbuffer != '0' &&
  194. (*realbuffer == ' ' ||
  195. *realbuffer == '\t' ||
  196. *realbuffer == '\r' ||
  197. *realbuffer == '\n'))
  198. {
  199. realbuffer++;
  200. }
  201. // skip blank lines and comment lines
  202. if(realbuffer[0] == '#' || realbuffer[0] == 0)
  203. {
  204. continue;
  205. }
  206. while(realbuffer[0] == '/' && realbuffer[1] == '/')
  207. {
  208. if ((realbuffer[2] == '\\') && (realbuffer[3]=='n'))
  209. {
  210. helpString += "\n";
  211. helpString += &realbuffer[4];
  212. }
  213. else
  214. {
  215. helpString += &realbuffer[2];
  216. }
  217. cmSystemTools::GetLineFromStream(fin, buffer);
  218. realbuffer = buffer.c_str();
  219. if(!fin)
  220. {
  221. continue;
  222. }
  223. }
  224. e.SetProperty("HELPSTRING", helpString.c_str());
  225. if(cmCacheManager::ParseEntry(realbuffer, entryKey, e.Value, e.Type))
  226. {
  227. if ( excludes.find(entryKey) == excludes.end() )
  228. {
  229. // Load internal values if internal is set.
  230. // If the entry is not internal to the cache being loaded
  231. // or if it is in the list of internal entries to be
  232. // imported, load it.
  233. if ( internal || (e.Type != INTERNAL) ||
  234. (includes.find(entryKey) != includes.end()) )
  235. {
  236. // If we are loading the cache from another project,
  237. // make all loaded entries internal so that it is
  238. // not visible in the gui
  239. if (!internal)
  240. {
  241. e.Type = INTERNAL;
  242. helpString = "DO NOT EDIT, ";
  243. helpString += entryKey;
  244. helpString += " loaded from external file. "
  245. "To change this value edit this file: ";
  246. helpString += path;
  247. helpString += "/CMakeCache.txt" ;
  248. e.SetProperty("HELPSTRING", helpString.c_str());
  249. }
  250. if(!this->ReadPropertyEntry(entryKey, e))
  251. {
  252. e.Initialized = true;
  253. this->Cache[entryKey] = e;
  254. }
  255. }
  256. }
  257. }
  258. else
  259. {
  260. cmSystemTools::Error("Parse error in cache file ", cacheFile.c_str(),
  261. ". Offending entry: ", realbuffer);
  262. }
  263. }
  264. this->CacheMajorVersion = 0;
  265. this->CacheMinorVersion = 0;
  266. if(const char* cmajor =
  267. this->GetInitializedCacheValue("CMAKE_CACHE_MAJOR_VERSION"))
  268. {
  269. unsigned int v=0;
  270. if(sscanf(cmajor, "%u", &v) == 1)
  271. {
  272. this->CacheMajorVersion = v;
  273. }
  274. if(const char* cminor =
  275. this->GetInitializedCacheValue("CMAKE_CACHE_MINOR_VERSION"))
  276. {
  277. if(sscanf(cminor, "%u", &v) == 1)
  278. {
  279. this->CacheMinorVersion = v;
  280. }
  281. }
  282. }
  283. else
  284. {
  285. // CMake version not found in the list file.
  286. // Set as version 0.0
  287. this->AddCacheEntry("CMAKE_CACHE_MINOR_VERSION", "0",
  288. "Minor version of cmake used to create the "
  289. "current loaded cache", cmCacheManager::INTERNAL);
  290. this->AddCacheEntry("CMAKE_CACHE_MAJOR_VERSION", "0",
  291. "Major version of cmake used to create the "
  292. "current loaded cache", cmCacheManager::INTERNAL);
  293. }
  294. // check to make sure the cache directory has not
  295. // been moved
  296. const char* oldDir = this->GetInitializedCacheValue("CMAKE_CACHEFILE_DIR");
  297. if (internal && oldDir)
  298. {
  299. std::string currentcwd = path;
  300. std::string oldcwd = oldDir;
  301. cmSystemTools::ConvertToUnixSlashes(currentcwd);
  302. currentcwd += "/CMakeCache.txt";
  303. oldcwd += "/CMakeCache.txt";
  304. if(!cmSystemTools::SameFile(oldcwd, currentcwd))
  305. {
  306. std::string message =
  307. std::string("The current CMakeCache.txt directory ") +
  308. currentcwd + std::string(" is different than the directory ") +
  309. std::string(this->GetInitializedCacheValue("CMAKE_CACHEFILE_DIR")) +
  310. std::string(" where CMakeCache.txt was created. This may result "
  311. "in binaries being created in the wrong place. If you "
  312. "are not sure, reedit the CMakeCache.txt");
  313. cmSystemTools::Error(message.c_str());
  314. }
  315. }
  316. return true;
  317. }
  318. //----------------------------------------------------------------------------
  319. const char* cmCacheManager::PersistentProperties[] =
  320. {
  321. "ADVANCED",
  322. "MODIFIED",
  323. "STRINGS",
  324. 0
  325. };
  326. //----------------------------------------------------------------------------
  327. bool cmCacheManager::ReadPropertyEntry(std::string const& entryKey,
  328. CacheEntry& e)
  329. {
  330. // All property entries are internal.
  331. if(e.Type != cmCacheManager::INTERNAL)
  332. {
  333. return false;
  334. }
  335. const char* end = entryKey.c_str() + entryKey.size();
  336. for(const char** p = this->PersistentProperties; *p; ++p)
  337. {
  338. std::string::size_type plen = strlen(*p) + 1;
  339. if(entryKey.size() > plen && *(end-plen) == '-' &&
  340. strcmp(end-plen+1, *p) == 0)
  341. {
  342. std::string key = entryKey.substr(0, entryKey.size() - plen);
  343. cmCacheManager::CacheIterator it = this->GetCacheIterator(key.c_str());
  344. if(it.IsAtEnd())
  345. {
  346. // Create an entry and store the property.
  347. CacheEntry& ne = this->Cache[key];
  348. ne.Properties.SetCMakeInstance(this->CMakeInstance);
  349. ne.Type = cmCacheManager::UNINITIALIZED;
  350. ne.SetProperty(*p, e.Value.c_str());
  351. }
  352. else
  353. {
  354. // Store this property on its entry.
  355. it.SetProperty(*p, e.Value.c_str());
  356. }
  357. return true;
  358. }
  359. }
  360. return false;
  361. }
  362. //----------------------------------------------------------------------------
  363. void cmCacheManager::WritePropertyEntries(std::ostream& os,
  364. CacheIterator const& i)
  365. {
  366. for(const char** p = this->PersistentProperties; *p; ++p)
  367. {
  368. if(const char* value = i.GetProperty(*p))
  369. {
  370. std::string helpstring = *p;
  371. helpstring += " property for variable: ";
  372. helpstring += i.GetName();
  373. cmCacheManager::OutputHelpString(os, helpstring);
  374. std::string key = i.GetName();
  375. key += "-";
  376. key += *p;
  377. this->OutputKey(os, key);
  378. os << ":INTERNAL=";
  379. this->OutputValue(os, value);
  380. os << "\n";
  381. }
  382. }
  383. }
  384. bool cmCacheManager::SaveCache(const std::string& path)
  385. {
  386. std::string cacheFile = path;
  387. cacheFile += "/CMakeCache.txt";
  388. cmGeneratedFileStream fout(cacheFile.c_str());
  389. fout.SetCopyIfDifferent(true);
  390. if(!fout)
  391. {
  392. cmSystemTools::Error("Unable to open cache file for save. ",
  393. cacheFile.c_str());
  394. cmSystemTools::ReportLastSystemError("");
  395. return false;
  396. }
  397. // before writing the cache, update the version numbers
  398. // to the
  399. char temp[1024];
  400. sprintf(temp, "%d", cmVersion::GetMinorVersion());
  401. this->AddCacheEntry("CMAKE_CACHE_MINOR_VERSION", temp,
  402. "Minor version of cmake used to create the "
  403. "current loaded cache", cmCacheManager::INTERNAL);
  404. sprintf(temp, "%d", cmVersion::GetMajorVersion());
  405. this->AddCacheEntry("CMAKE_CACHE_MAJOR_VERSION", temp,
  406. "Major version of cmake used to create the "
  407. "current loaded cache", cmCacheManager::INTERNAL);
  408. sprintf(temp, "%d", cmVersion::GetPatchVersion());
  409. this->AddCacheEntry("CMAKE_CACHE_PATCH_VERSION", temp,
  410. "Patch version of cmake used to create the "
  411. "current loaded cache", cmCacheManager::INTERNAL);
  412. // Let us store the current working directory so that if somebody
  413. // Copies it, he will not be surprised
  414. std::string currentcwd = path;
  415. if ( currentcwd[0] >= 'A' && currentcwd[0] <= 'Z' &&
  416. currentcwd[1] == ':' )
  417. {
  418. // Cast added to avoid compiler warning. Cast is ok because
  419. // value is guaranteed to fit in char by the above if...
  420. currentcwd[0] = static_cast<char>(currentcwd[0] - 'A' + 'a');
  421. }
  422. cmSystemTools::ConvertToUnixSlashes(currentcwd);
  423. this->AddCacheEntry("CMAKE_CACHEFILE_DIR", currentcwd.c_str(),
  424. "This is the directory where this CMakeCache.txt"
  425. " was created", cmCacheManager::INTERNAL);
  426. fout << "# This is the CMakeCache file.\n"
  427. << "# For build in directory: " << currentcwd << "\n";
  428. cmCacheManager::CacheEntry* cmakeCacheEntry
  429. = this->GetCacheEntry("CMAKE_COMMAND");
  430. if ( cmakeCacheEntry )
  431. {
  432. fout << "# It was generated by CMake: " <<
  433. cmakeCacheEntry->Value << std::endl;
  434. }
  435. fout << "# You can edit this file to change values found and used by cmake."
  436. << std::endl
  437. << "# If you do not want to change any of the values, simply exit the "
  438. "editor." << std::endl
  439. << "# If you do want to change a value, simply edit, save, and exit "
  440. "the editor." << std::endl
  441. << "# The syntax for the file is as follows:\n"
  442. << "# KEY:TYPE=VALUE\n"
  443. << "# KEY is the name of a variable in the cache.\n"
  444. << "# TYPE is a hint to GUIs for the type of VALUE, DO NOT EDIT "
  445. "TYPE!." << std::endl
  446. << "# VALUE is the current value for the KEY.\n\n";
  447. fout << "########################\n";
  448. fout << "# EXTERNAL cache entries\n";
  449. fout << "########################\n";
  450. fout << "\n";
  451. for( std::map<std::string, CacheEntry>::const_iterator i =
  452. this->Cache.begin(); i != this->Cache.end(); ++i)
  453. {
  454. const CacheEntry& ce = (*i).second;
  455. CacheEntryType t = ce.Type;
  456. if(!ce.Initialized)
  457. {
  458. /*
  459. // This should be added in, but is not for now.
  460. cmSystemTools::Error("Cache entry \"", (*i).first.c_str(),
  461. "\" is uninitialized");
  462. */
  463. }
  464. else if(t != INTERNAL)
  465. {
  466. // Format is key:type=value
  467. if(const char* help = ce.GetProperty("HELPSTRING"))
  468. {
  469. cmCacheManager::OutputHelpString(fout, help);
  470. }
  471. else
  472. {
  473. cmCacheManager::OutputHelpString(fout, "Missing description");
  474. }
  475. this->OutputKey(fout, i->first);
  476. fout << ":" << cmCacheManagerTypes[t] << "=";
  477. this->OutputValue(fout, ce.Value);
  478. fout << "\n\n";
  479. }
  480. }
  481. fout << "\n";
  482. fout << "########################\n";
  483. fout << "# INTERNAL cache entries\n";
  484. fout << "########################\n";
  485. fout << "\n";
  486. for( cmCacheManager::CacheIterator i = this->NewIterator();
  487. !i.IsAtEnd(); i.Next())
  488. {
  489. if ( !i.Initialized() )
  490. {
  491. continue;
  492. }
  493. CacheEntryType t = i.GetType();
  494. this->WritePropertyEntries(fout, i);
  495. if(t == cmCacheManager::INTERNAL)
  496. {
  497. // Format is key:type=value
  498. if(const char* help = i.GetProperty("HELPSTRING"))
  499. {
  500. this->OutputHelpString(fout, help);
  501. }
  502. this->OutputKey(fout, i.GetName());
  503. fout << ":" << cmCacheManagerTypes[t] << "=";
  504. this->OutputValue(fout, i.GetValue());
  505. fout << "\n";
  506. }
  507. }
  508. fout << "\n";
  509. fout.Close();
  510. std::string checkCacheFile = path;
  511. checkCacheFile += cmake::GetCMakeFilesDirectory();
  512. cmSystemTools::MakeDirectory(checkCacheFile.c_str());
  513. checkCacheFile += "/cmake.check_cache";
  514. cmsys::ofstream checkCache(checkCacheFile.c_str());
  515. if(!checkCache)
  516. {
  517. cmSystemTools::Error("Unable to open check cache file for write. ",
  518. checkCacheFile.c_str());
  519. return false;
  520. }
  521. checkCache << "# This file is generated by cmake for dependency checking "
  522. "of the CMakeCache.txt file\n";
  523. return true;
  524. }
  525. bool cmCacheManager::DeleteCache(const std::string& path)
  526. {
  527. std::string cacheFile = path;
  528. cmSystemTools::ConvertToUnixSlashes(cacheFile);
  529. std::string cmakeFiles = cacheFile;
  530. cacheFile += "/CMakeCache.txt";
  531. if(cmSystemTools::FileExists(cacheFile.c_str()))
  532. {
  533. cmSystemTools::RemoveFile(cacheFile);
  534. // now remove the files in the CMakeFiles directory
  535. // this cleans up language cache files
  536. cmakeFiles += cmake::GetCMakeFilesDirectory();
  537. if(cmSystemTools::FileIsDirectory(cmakeFiles))
  538. {
  539. cmSystemTools::RemoveADirectory(cmakeFiles);
  540. }
  541. }
  542. return true;
  543. }
  544. void cmCacheManager::OutputKey(std::ostream& fout, std::string const& key)
  545. {
  546. // support : in key name by double quoting
  547. const char* q = (key.find(':') != key.npos ||
  548. key.find("//") == 0)? "\"" : "";
  549. fout << q << key << q;
  550. }
  551. void cmCacheManager::OutputValue(std::ostream& fout, std::string const& value)
  552. {
  553. // if value has trailing space or tab, enclose it in single quotes
  554. if (!value.empty() &&
  555. (value[value.size() - 1] == ' ' ||
  556. value[value.size() - 1] == '\t'))
  557. {
  558. fout << '\'' << value << '\'';
  559. }
  560. else
  561. {
  562. fout << value;
  563. }
  564. }
  565. void cmCacheManager::OutputHelpString(std::ostream& fout,
  566. const std::string& helpString)
  567. {
  568. std::string::size_type end = helpString.size();
  569. if(end == 0)
  570. {
  571. return;
  572. }
  573. std::string oneLine;
  574. std::string::size_type pos = 0;
  575. for (std::string::size_type i=0; i<=end; i++)
  576. {
  577. if ((i==end)
  578. || (helpString[i]=='\n')
  579. || ((i-pos >= 60) && (helpString[i]==' ')))
  580. {
  581. fout << "//";
  582. if (helpString[pos] == '\n')
  583. {
  584. pos++;
  585. fout << "\\n";
  586. }
  587. oneLine = helpString.substr(pos, i - pos);
  588. fout << oneLine << "\n";
  589. pos = i;
  590. }
  591. }
  592. }
  593. void cmCacheManager::RemoveCacheEntry(const std::string& key)
  594. {
  595. CacheEntryMap::iterator i = this->Cache.find(key);
  596. if(i != this->Cache.end())
  597. {
  598. this->Cache.erase(i);
  599. }
  600. }
  601. cmCacheManager::CacheEntry *cmCacheManager::GetCacheEntry(
  602. const std::string& key)
  603. {
  604. CacheEntryMap::iterator i = this->Cache.find(key);
  605. if(i != this->Cache.end())
  606. {
  607. return &i->second;
  608. }
  609. return 0;
  610. }
  611. cmCacheManager::CacheIterator cmCacheManager::GetCacheIterator(
  612. const char *key)
  613. {
  614. return CacheIterator(*this, key);
  615. }
  616. const char*
  617. cmCacheManager::GetInitializedCacheValue(const std::string& key) const
  618. {
  619. CacheEntryMap::const_iterator i = this->Cache.find(key);
  620. if(i != this->Cache.end() &&
  621. i->second.Initialized)
  622. {
  623. return i->second.Value.c_str();
  624. }
  625. return 0;
  626. }
  627. void cmCacheManager::PrintCache(std::ostream& out) const
  628. {
  629. out << "=================================================" << std::endl;
  630. out << "CMakeCache Contents:" << std::endl;
  631. for(std::map<std::string, CacheEntry>::const_iterator i =
  632. this->Cache.begin(); i != this->Cache.end(); ++i)
  633. {
  634. if((*i).second.Type != INTERNAL)
  635. {
  636. out << (*i).first << " = " << (*i).second.Value
  637. << std::endl;
  638. }
  639. }
  640. out << "\n\n";
  641. out << "To change values in the CMakeCache, "
  642. << std::endl << "edit CMakeCache.txt in your output directory.\n";
  643. out << "=================================================" << std::endl;
  644. }
  645. void cmCacheManager::AddCacheEntry(const std::string& key,
  646. const char* value,
  647. const char* helpString,
  648. CacheEntryType type)
  649. {
  650. CacheEntry& e = this->Cache[key];
  651. e.Properties.SetCMakeInstance(this->CMakeInstance);
  652. if ( value )
  653. {
  654. e.Value = value;
  655. e.Initialized = true;
  656. }
  657. else
  658. {
  659. e.Value = "";
  660. }
  661. e.Type = type;
  662. // make sure we only use unix style paths
  663. if(type == FILEPATH || type == PATH)
  664. {
  665. if(e.Value.find(';') != e.Value.npos)
  666. {
  667. std::vector<std::string> paths;
  668. cmSystemTools::ExpandListArgument(e.Value, paths);
  669. const char* sep = "";
  670. e.Value = "";
  671. for(std::vector<std::string>::iterator i = paths.begin();
  672. i != paths.end(); ++i)
  673. {
  674. cmSystemTools::ConvertToUnixSlashes(*i);
  675. e.Value += sep;
  676. e.Value += *i;
  677. sep = ";";
  678. }
  679. }
  680. else
  681. {
  682. cmSystemTools::ConvertToUnixSlashes(e.Value);
  683. }
  684. }
  685. e.SetProperty("HELPSTRING", helpString? helpString :
  686. "(This variable does not exist and should not be used)");
  687. this->CMakeInstance->UnwatchUnusedCli(key);
  688. }
  689. bool cmCacheManager::CacheIterator::IsAtEnd() const
  690. {
  691. return this->Position == this->Container.Cache.end();
  692. }
  693. void cmCacheManager::CacheIterator::Begin()
  694. {
  695. this->Position = this->Container.Cache.begin();
  696. }
  697. bool cmCacheManager::CacheIterator::Find(const std::string& key)
  698. {
  699. this->Position = this->Container.Cache.find(key);
  700. return !this->IsAtEnd();
  701. }
  702. void cmCacheManager::CacheIterator::Next()
  703. {
  704. if (!this->IsAtEnd())
  705. {
  706. ++this->Position;
  707. }
  708. }
  709. void cmCacheManager::CacheIterator::SetValue(const char* value)
  710. {
  711. if (this->IsAtEnd())
  712. {
  713. return;
  714. }
  715. CacheEntry* entry = &this->GetEntry();
  716. if ( value )
  717. {
  718. entry->Value = value;
  719. entry->Initialized = true;
  720. }
  721. else
  722. {
  723. entry->Value = "";
  724. }
  725. }
  726. //----------------------------------------------------------------------------
  727. bool cmCacheManager::CacheIterator::GetValueAsBool() const
  728. {
  729. return cmSystemTools::IsOn(this->GetEntry().Value.c_str());
  730. }
  731. //----------------------------------------------------------------------------
  732. const char*
  733. cmCacheManager::CacheEntry::GetProperty(const std::string& prop) const
  734. {
  735. if(prop == "TYPE")
  736. {
  737. return cmCacheManagerTypes[this->Type];
  738. }
  739. else if(prop == "VALUE")
  740. {
  741. return this->Value.c_str();
  742. }
  743. bool c = false;
  744. return
  745. this->Properties.GetPropertyValue(prop, cmProperty::CACHE, c);
  746. }
  747. //----------------------------------------------------------------------------
  748. void cmCacheManager::CacheEntry::SetProperty(const std::string& prop,
  749. const char* value)
  750. {
  751. if(prop == "TYPE")
  752. {
  753. this->Type = cmCacheManager::StringToType(value? value : "STRING");
  754. }
  755. else if(prop == "VALUE")
  756. {
  757. this->Value = value? value : "";
  758. }
  759. else
  760. {
  761. this->Properties.SetProperty(prop, value, cmProperty::CACHE);
  762. }
  763. }
  764. //----------------------------------------------------------------------------
  765. void cmCacheManager::CacheEntry::AppendProperty(const std::string& prop,
  766. const char* value,
  767. bool asString)
  768. {
  769. if(prop == "TYPE")
  770. {
  771. this->Type = cmCacheManager::StringToType(value? value : "STRING");
  772. }
  773. else if(prop == "VALUE")
  774. {
  775. if(value)
  776. {
  777. if(!this->Value.empty() && *value && !asString)
  778. {
  779. this->Value += ";";
  780. }
  781. this->Value += value;
  782. }
  783. }
  784. else
  785. {
  786. this->Properties.AppendProperty(prop, value, cmProperty::CACHE, asString);
  787. }
  788. }
  789. //----------------------------------------------------------------------------
  790. const char* cmCacheManager::CacheIterator::GetProperty(
  791. const std::string& prop) const
  792. {
  793. if(!this->IsAtEnd())
  794. {
  795. return this->GetEntry().GetProperty(prop);
  796. }
  797. return 0;
  798. }
  799. //----------------------------------------------------------------------------
  800. void cmCacheManager::CacheIterator::SetProperty(const std::string& p,
  801. const char* v)
  802. {
  803. if(!this->IsAtEnd())
  804. {
  805. this->GetEntry().SetProperty(p, v);
  806. }
  807. }
  808. //----------------------------------------------------------------------------
  809. void cmCacheManager::CacheIterator::AppendProperty(const std::string& p,
  810. const char* v,
  811. bool asString)
  812. {
  813. if(!this->IsAtEnd())
  814. {
  815. this->GetEntry().AppendProperty(p, v, asString);
  816. }
  817. }
  818. //----------------------------------------------------------------------------
  819. bool cmCacheManager::CacheIterator::GetPropertyAsBool(
  820. const std::string& prop) const
  821. {
  822. if(const char* value = this->GetProperty(prop))
  823. {
  824. return cmSystemTools::IsOn(value);
  825. }
  826. return false;
  827. }
  828. //----------------------------------------------------------------------------
  829. void cmCacheManager::CacheIterator::SetProperty(const std::string& p, bool v)
  830. {
  831. this->SetProperty(p, v ? "ON" : "OFF");
  832. }
  833. //----------------------------------------------------------------------------
  834. bool cmCacheManager::CacheIterator::PropertyExists(
  835. const std::string& prop) const
  836. {
  837. return this->GetProperty(prop)? true:false;
  838. }