cmCacheManager.cxx 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657
  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 "cmGeneratedFileStream.h"
  12. #include "cmSystemTools.h"
  13. #include "cmVersion.h"
  14. #include "cmake.h"
  15. #include <cmsys/Directory.hxx>
  16. #include <cmsys/FStream.hxx>
  17. #include <cmsys/Glob.hxx>
  18. #include <cmsys/RegularExpression.hxx>
  19. cmCacheManager::cmCacheManager()
  20. {
  21. this->CacheMajorVersion = 0;
  22. this->CacheMinorVersion = 0;
  23. }
  24. void cmCacheManager::CleanCMakeFiles(const std::string& path)
  25. {
  26. std::string glob = path;
  27. glob += cmake::GetCMakeFilesDirectory();
  28. glob += "/*.cmake";
  29. cmsys::Glob globIt;
  30. globIt.FindFiles(glob);
  31. std::vector<std::string> files = globIt.GetFiles();
  32. std::for_each(files.begin(), files.end(), cmSystemTools::RemoveFile);
  33. }
  34. bool cmCacheManager::LoadCache(const std::string& path, bool internal,
  35. std::set<std::string>& excludes,
  36. std::set<std::string>& includes)
  37. {
  38. std::string cacheFile = path;
  39. cacheFile += "/CMakeCache.txt";
  40. // clear the old cache, if we are reading in internal values
  41. if (internal) {
  42. this->Cache.clear();
  43. }
  44. if (!cmSystemTools::FileExists(cacheFile.c_str())) {
  45. this->CleanCMakeFiles(path);
  46. return false;
  47. }
  48. cmsys::ifstream fin(cacheFile.c_str());
  49. if (!fin) {
  50. return false;
  51. }
  52. const char* realbuffer;
  53. std::string buffer;
  54. std::string entryKey;
  55. unsigned int lineno = 0;
  56. while (fin) {
  57. // Format is key:type=value
  58. std::string helpString;
  59. CacheEntry e;
  60. cmSystemTools::GetLineFromStream(fin, buffer);
  61. lineno++;
  62. realbuffer = buffer.c_str();
  63. while (*realbuffer != '0' &&
  64. (*realbuffer == ' ' || *realbuffer == '\t' || *realbuffer == '\r' ||
  65. *realbuffer == '\n')) {
  66. if (*realbuffer == '\n') {
  67. lineno++;
  68. }
  69. realbuffer++;
  70. }
  71. // skip blank lines and comment lines
  72. if (realbuffer[0] == '#' || realbuffer[0] == 0) {
  73. continue;
  74. }
  75. while (realbuffer[0] == '/' && realbuffer[1] == '/') {
  76. if ((realbuffer[2] == '\\') && (realbuffer[3] == 'n')) {
  77. helpString += "\n";
  78. helpString += &realbuffer[4];
  79. } else {
  80. helpString += &realbuffer[2];
  81. }
  82. cmSystemTools::GetLineFromStream(fin, buffer);
  83. lineno++;
  84. realbuffer = buffer.c_str();
  85. if (!fin) {
  86. continue;
  87. }
  88. }
  89. e.SetProperty("HELPSTRING", helpString.c_str());
  90. if (cmState::ParseCacheEntry(realbuffer, entryKey, e.Value, e.Type)) {
  91. if (excludes.find(entryKey) == excludes.end()) {
  92. // Load internal values if internal is set.
  93. // If the entry is not internal to the cache being loaded
  94. // or if it is in the list of internal entries to be
  95. // imported, load it.
  96. if (internal || (e.Type != cmState::INTERNAL) ||
  97. (includes.find(entryKey) != includes.end())) {
  98. // If we are loading the cache from another project,
  99. // make all loaded entries internal so that it is
  100. // not visible in the gui
  101. if (!internal) {
  102. e.Type = cmState::INTERNAL;
  103. helpString = "DO NOT EDIT, ";
  104. helpString += entryKey;
  105. helpString += " loaded from external file. "
  106. "To change this value edit this file: ";
  107. helpString += path;
  108. helpString += "/CMakeCache.txt";
  109. e.SetProperty("HELPSTRING", helpString.c_str());
  110. }
  111. if (!this->ReadPropertyEntry(entryKey, e)) {
  112. e.Initialized = true;
  113. this->Cache[entryKey] = e;
  114. }
  115. }
  116. }
  117. } else {
  118. std::ostringstream error;
  119. error << "Parse error in cache file " << cacheFile;
  120. error << " on line " << lineno << ". Offending entry: " << realbuffer;
  121. cmSystemTools::Error(error.str().c_str());
  122. }
  123. }
  124. this->CacheMajorVersion = 0;
  125. this->CacheMinorVersion = 0;
  126. if (const char* cmajor =
  127. this->GetInitializedCacheValue("CMAKE_CACHE_MAJOR_VERSION")) {
  128. unsigned int v = 0;
  129. if (sscanf(cmajor, "%u", &v) == 1) {
  130. this->CacheMajorVersion = v;
  131. }
  132. if (const char* cminor =
  133. this->GetInitializedCacheValue("CMAKE_CACHE_MINOR_VERSION")) {
  134. if (sscanf(cminor, "%u", &v) == 1) {
  135. this->CacheMinorVersion = v;
  136. }
  137. }
  138. } else {
  139. // CMake version not found in the list file.
  140. // Set as version 0.0
  141. this->AddCacheEntry("CMAKE_CACHE_MINOR_VERSION", "0",
  142. "Minor version of cmake used to create the "
  143. "current loaded cache",
  144. cmState::INTERNAL);
  145. this->AddCacheEntry("CMAKE_CACHE_MAJOR_VERSION", "0",
  146. "Major version of cmake used to create the "
  147. "current loaded cache",
  148. cmState::INTERNAL);
  149. }
  150. // check to make sure the cache directory has not
  151. // been moved
  152. const char* oldDir = this->GetInitializedCacheValue("CMAKE_CACHEFILE_DIR");
  153. if (internal && oldDir) {
  154. std::string currentcwd = path;
  155. std::string oldcwd = oldDir;
  156. cmSystemTools::ConvertToUnixSlashes(currentcwd);
  157. currentcwd += "/CMakeCache.txt";
  158. oldcwd += "/CMakeCache.txt";
  159. if (!cmSystemTools::SameFile(oldcwd, currentcwd)) {
  160. std::string message =
  161. std::string("The current CMakeCache.txt directory ") + currentcwd +
  162. std::string(" is different than the directory ") +
  163. std::string(this->GetInitializedCacheValue("CMAKE_CACHEFILE_DIR")) +
  164. std::string(" where CMakeCache.txt was created. This may result "
  165. "in binaries being created in the wrong place. If you "
  166. "are not sure, reedit the CMakeCache.txt");
  167. cmSystemTools::Error(message.c_str());
  168. }
  169. }
  170. return true;
  171. }
  172. const char* cmCacheManager::PersistentProperties[] = { "ADVANCED", "MODIFIED",
  173. "STRINGS", CM_NULLPTR };
  174. bool cmCacheManager::ReadPropertyEntry(std::string const& entryKey,
  175. CacheEntry& e)
  176. {
  177. // All property entries are internal.
  178. if (e.Type != cmState::INTERNAL) {
  179. return false;
  180. }
  181. const char* end = entryKey.c_str() + entryKey.size();
  182. for (const char** p = this->PersistentProperties; *p; ++p) {
  183. std::string::size_type plen = strlen(*p) + 1;
  184. if (entryKey.size() > plen && *(end - plen) == '-' &&
  185. strcmp(end - plen + 1, *p) == 0) {
  186. std::string key = entryKey.substr(0, entryKey.size() - plen);
  187. cmCacheManager::CacheIterator it = this->GetCacheIterator(key.c_str());
  188. if (it.IsAtEnd()) {
  189. // Create an entry and store the property.
  190. CacheEntry& ne = this->Cache[key];
  191. ne.Type = cmState::UNINITIALIZED;
  192. ne.SetProperty(*p, e.Value.c_str());
  193. } else {
  194. // Store this property on its entry.
  195. it.SetProperty(*p, e.Value.c_str());
  196. }
  197. return true;
  198. }
  199. }
  200. return false;
  201. }
  202. void cmCacheManager::WritePropertyEntries(std::ostream& os,
  203. CacheIterator const& i)
  204. {
  205. for (const char** p = this->PersistentProperties; *p; ++p) {
  206. if (const char* value = i.GetProperty(*p)) {
  207. std::string helpstring = *p;
  208. helpstring += " property for variable: ";
  209. helpstring += i.GetName();
  210. cmCacheManager::OutputHelpString(os, helpstring);
  211. std::string key = i.GetName();
  212. key += "-";
  213. key += *p;
  214. this->OutputKey(os, key);
  215. os << ":INTERNAL=";
  216. this->OutputValue(os, value);
  217. os << "\n";
  218. }
  219. }
  220. }
  221. bool cmCacheManager::SaveCache(const std::string& path)
  222. {
  223. std::string cacheFile = path;
  224. cacheFile += "/CMakeCache.txt";
  225. cmGeneratedFileStream fout(cacheFile.c_str());
  226. fout.SetCopyIfDifferent(true);
  227. if (!fout) {
  228. cmSystemTools::Error("Unable to open cache file for save. ",
  229. cacheFile.c_str());
  230. cmSystemTools::ReportLastSystemError("");
  231. return false;
  232. }
  233. // before writing the cache, update the version numbers
  234. // to the
  235. char temp[1024];
  236. sprintf(temp, "%d", cmVersion::GetMinorVersion());
  237. this->AddCacheEntry("CMAKE_CACHE_MINOR_VERSION", temp,
  238. "Minor version of cmake used to create the "
  239. "current loaded cache",
  240. cmState::INTERNAL);
  241. sprintf(temp, "%d", cmVersion::GetMajorVersion());
  242. this->AddCacheEntry("CMAKE_CACHE_MAJOR_VERSION", temp,
  243. "Major version of cmake used to create the "
  244. "current loaded cache",
  245. cmState::INTERNAL);
  246. sprintf(temp, "%d", cmVersion::GetPatchVersion());
  247. this->AddCacheEntry("CMAKE_CACHE_PATCH_VERSION", temp,
  248. "Patch version of cmake used to create the "
  249. "current loaded cache",
  250. cmState::INTERNAL);
  251. // Let us store the current working directory so that if somebody
  252. // Copies it, he will not be surprised
  253. std::string currentcwd = path;
  254. if (currentcwd[0] >= 'A' && currentcwd[0] <= 'Z' && currentcwd[1] == ':') {
  255. // Cast added to avoid compiler warning. Cast is ok because
  256. // value is guaranteed to fit in char by the above if...
  257. currentcwd[0] = static_cast<char>(currentcwd[0] - 'A' + 'a');
  258. }
  259. cmSystemTools::ConvertToUnixSlashes(currentcwd);
  260. this->AddCacheEntry("CMAKE_CACHEFILE_DIR", currentcwd.c_str(),
  261. "This is the directory where this CMakeCache.txt"
  262. " was created",
  263. cmState::INTERNAL);
  264. /* clang-format off */
  265. fout << "# This is the CMakeCache file.\n"
  266. << "# For build in directory: " << currentcwd << "\n"
  267. << "# It was generated by CMake: "
  268. << cmSystemTools::GetCMakeCommand() << std::endl;
  269. /* clang-format on */
  270. /* clang-format off */
  271. fout << "# You can edit this file to change values found and used by cmake."
  272. << std::endl
  273. << "# If you do not want to change any of the values, simply exit the "
  274. "editor." << std::endl
  275. << "# If you do want to change a value, simply edit, save, and exit "
  276. "the editor." << std::endl
  277. << "# The syntax for the file is as follows:\n"
  278. << "# KEY:TYPE=VALUE\n"
  279. << "# KEY is the name of a variable in the cache.\n"
  280. << "# TYPE is a hint to GUIs for the type of VALUE, DO NOT EDIT "
  281. "TYPE!." << std::endl
  282. << "# VALUE is the current value for the KEY.\n\n";
  283. /* clang-format on */
  284. fout << "########################\n";
  285. fout << "# EXTERNAL cache entries\n";
  286. fout << "########################\n";
  287. fout << "\n";
  288. for (std::map<std::string, CacheEntry>::const_iterator i =
  289. this->Cache.begin();
  290. i != this->Cache.end(); ++i) {
  291. const CacheEntry& ce = (*i).second;
  292. cmState::CacheEntryType t = ce.Type;
  293. if (!ce.Initialized) {
  294. /*
  295. // This should be added in, but is not for now.
  296. cmSystemTools::Error("Cache entry \"", (*i).first.c_str(),
  297. "\" is uninitialized");
  298. */
  299. } else if (t != cmState::INTERNAL) {
  300. // Format is key:type=value
  301. if (const char* help = ce.GetProperty("HELPSTRING")) {
  302. cmCacheManager::OutputHelpString(fout, help);
  303. } else {
  304. cmCacheManager::OutputHelpString(fout, "Missing description");
  305. }
  306. this->OutputKey(fout, i->first);
  307. fout << ":" << cmState::CacheEntryTypeToString(t) << "=";
  308. this->OutputValue(fout, ce.Value);
  309. fout << "\n\n";
  310. }
  311. }
  312. fout << "\n";
  313. fout << "########################\n";
  314. fout << "# INTERNAL cache entries\n";
  315. fout << "########################\n";
  316. fout << "\n";
  317. for (cmCacheManager::CacheIterator i = this->NewIterator(); !i.IsAtEnd();
  318. i.Next()) {
  319. if (!i.Initialized()) {
  320. continue;
  321. }
  322. cmState::CacheEntryType t = i.GetType();
  323. this->WritePropertyEntries(fout, i);
  324. if (t == cmState::INTERNAL) {
  325. // Format is key:type=value
  326. if (const char* help = i.GetProperty("HELPSTRING")) {
  327. this->OutputHelpString(fout, help);
  328. }
  329. this->OutputKey(fout, i.GetName());
  330. fout << ":" << cmState::CacheEntryTypeToString(t) << "=";
  331. this->OutputValue(fout, i.GetValue());
  332. fout << "\n";
  333. }
  334. }
  335. fout << "\n";
  336. fout.Close();
  337. std::string checkCacheFile = path;
  338. checkCacheFile += cmake::GetCMakeFilesDirectory();
  339. cmSystemTools::MakeDirectory(checkCacheFile.c_str());
  340. checkCacheFile += "/cmake.check_cache";
  341. cmsys::ofstream checkCache(checkCacheFile.c_str());
  342. if (!checkCache) {
  343. cmSystemTools::Error("Unable to open check cache file for write. ",
  344. checkCacheFile.c_str());
  345. return false;
  346. }
  347. checkCache << "# This file is generated by cmake for dependency checking "
  348. "of the CMakeCache.txt file\n";
  349. return true;
  350. }
  351. bool cmCacheManager::DeleteCache(const std::string& path)
  352. {
  353. std::string cacheFile = path;
  354. cmSystemTools::ConvertToUnixSlashes(cacheFile);
  355. std::string cmakeFiles = cacheFile;
  356. cacheFile += "/CMakeCache.txt";
  357. if (cmSystemTools::FileExists(cacheFile.c_str())) {
  358. cmSystemTools::RemoveFile(cacheFile);
  359. // now remove the files in the CMakeFiles directory
  360. // this cleans up language cache files
  361. cmakeFiles += cmake::GetCMakeFilesDirectory();
  362. if (cmSystemTools::FileIsDirectory(cmakeFiles)) {
  363. cmSystemTools::RemoveADirectory(cmakeFiles);
  364. }
  365. }
  366. return true;
  367. }
  368. void cmCacheManager::OutputKey(std::ostream& fout, std::string const& key)
  369. {
  370. // support : in key name by double quoting
  371. const char* q =
  372. (key.find(':') != key.npos || key.find("//") == 0) ? "\"" : "";
  373. fout << q << key << q;
  374. }
  375. void cmCacheManager::OutputValue(std::ostream& fout, std::string const& value)
  376. {
  377. // if value has trailing space or tab, enclose it in single quotes
  378. if (!value.empty() &&
  379. (value[value.size() - 1] == ' ' || value[value.size() - 1] == '\t')) {
  380. fout << '\'' << value << '\'';
  381. } else {
  382. fout << value;
  383. }
  384. }
  385. void cmCacheManager::OutputHelpString(std::ostream& fout,
  386. const std::string& helpString)
  387. {
  388. std::string::size_type end = helpString.size();
  389. if (end == 0) {
  390. return;
  391. }
  392. std::string oneLine;
  393. std::string::size_type pos = 0;
  394. for (std::string::size_type i = 0; i <= end; i++) {
  395. if ((i == end) || (helpString[i] == '\n') ||
  396. ((i - pos >= 60) && (helpString[i] == ' '))) {
  397. fout << "//";
  398. if (helpString[pos] == '\n') {
  399. pos++;
  400. fout << "\\n";
  401. }
  402. oneLine = helpString.substr(pos, i - pos);
  403. fout << oneLine << "\n";
  404. pos = i;
  405. }
  406. }
  407. }
  408. void cmCacheManager::RemoveCacheEntry(const std::string& key)
  409. {
  410. CacheEntryMap::iterator i = this->Cache.find(key);
  411. if (i != this->Cache.end()) {
  412. this->Cache.erase(i);
  413. }
  414. }
  415. cmCacheManager::CacheEntry* cmCacheManager::GetCacheEntry(
  416. const std::string& key)
  417. {
  418. CacheEntryMap::iterator i = this->Cache.find(key);
  419. if (i != this->Cache.end()) {
  420. return &i->second;
  421. }
  422. return CM_NULLPTR;
  423. }
  424. cmCacheManager::CacheIterator cmCacheManager::GetCacheIterator(const char* key)
  425. {
  426. return CacheIterator(*this, key);
  427. }
  428. const char* cmCacheManager::GetInitializedCacheValue(
  429. const std::string& key) const
  430. {
  431. CacheEntryMap::const_iterator i = this->Cache.find(key);
  432. if (i != this->Cache.end() && i->second.Initialized) {
  433. return i->second.Value.c_str();
  434. }
  435. return CM_NULLPTR;
  436. }
  437. void cmCacheManager::PrintCache(std::ostream& out) const
  438. {
  439. out << "=================================================" << std::endl;
  440. out << "CMakeCache Contents:" << std::endl;
  441. for (std::map<std::string, CacheEntry>::const_iterator i =
  442. this->Cache.begin();
  443. i != this->Cache.end(); ++i) {
  444. if ((*i).second.Type != cmState::INTERNAL) {
  445. out << (*i).first << " = " << (*i).second.Value << std::endl;
  446. }
  447. }
  448. out << "\n\n";
  449. out << "To change values in the CMakeCache, " << std::endl
  450. << "edit CMakeCache.txt in your output directory.\n";
  451. out << "=================================================" << std::endl;
  452. }
  453. void cmCacheManager::AddCacheEntry(const std::string& key, const char* value,
  454. const char* helpString,
  455. cmState::CacheEntryType type)
  456. {
  457. CacheEntry& e = this->Cache[key];
  458. if (value) {
  459. e.Value = value;
  460. e.Initialized = true;
  461. } else {
  462. e.Value = "";
  463. }
  464. e.Type = type;
  465. // make sure we only use unix style paths
  466. if (type == cmState::FILEPATH || type == cmState::PATH) {
  467. if (e.Value.find(';') != e.Value.npos) {
  468. std::vector<std::string> paths;
  469. cmSystemTools::ExpandListArgument(e.Value, paths);
  470. const char* sep = "";
  471. e.Value = "";
  472. for (std::vector<std::string>::iterator i = paths.begin();
  473. i != paths.end(); ++i) {
  474. cmSystemTools::ConvertToUnixSlashes(*i);
  475. e.Value += sep;
  476. e.Value += *i;
  477. sep = ";";
  478. }
  479. } else {
  480. cmSystemTools::ConvertToUnixSlashes(e.Value);
  481. }
  482. }
  483. e.SetProperty("HELPSTRING", helpString
  484. ? helpString
  485. : "(This variable does not exist and should not be used)");
  486. }
  487. bool cmCacheManager::CacheIterator::IsAtEnd() const
  488. {
  489. return this->Position == this->Container.Cache.end();
  490. }
  491. void cmCacheManager::CacheIterator::Begin()
  492. {
  493. this->Position = this->Container.Cache.begin();
  494. }
  495. bool cmCacheManager::CacheIterator::Find(const std::string& key)
  496. {
  497. this->Position = this->Container.Cache.find(key);
  498. return !this->IsAtEnd();
  499. }
  500. void cmCacheManager::CacheIterator::Next()
  501. {
  502. if (!this->IsAtEnd()) {
  503. ++this->Position;
  504. }
  505. }
  506. std::vector<std::string> cmCacheManager::CacheIterator::GetPropertyList() const
  507. {
  508. return this->GetEntry().GetPropertyList();
  509. }
  510. void cmCacheManager::CacheIterator::SetValue(const char* value)
  511. {
  512. if (this->IsAtEnd()) {
  513. return;
  514. }
  515. CacheEntry* entry = &this->GetEntry();
  516. if (value) {
  517. entry->Value = value;
  518. entry->Initialized = true;
  519. } else {
  520. entry->Value = "";
  521. }
  522. }
  523. bool cmCacheManager::CacheIterator::GetValueAsBool() const
  524. {
  525. return cmSystemTools::IsOn(this->GetEntry().Value.c_str());
  526. }
  527. std::vector<std::string> cmCacheManager::CacheEntry::GetPropertyList() const
  528. {
  529. return this->Properties.GetPropertyList();
  530. }
  531. const char* cmCacheManager::CacheEntry::GetProperty(
  532. const std::string& prop) const
  533. {
  534. if (prop == "TYPE") {
  535. return cmState::CacheEntryTypeToString(this->Type);
  536. } else if (prop == "VALUE") {
  537. return this->Value.c_str();
  538. }
  539. return this->Properties.GetPropertyValue(prop);
  540. }
  541. void cmCacheManager::CacheEntry::SetProperty(const std::string& prop,
  542. const char* value)
  543. {
  544. if (prop == "TYPE") {
  545. this->Type = cmState::StringToCacheEntryType(value ? value : "STRING");
  546. } else if (prop == "VALUE") {
  547. this->Value = value ? value : "";
  548. } else {
  549. this->Properties.SetProperty(prop, value);
  550. }
  551. }
  552. void cmCacheManager::CacheEntry::AppendProperty(const std::string& prop,
  553. const char* value,
  554. bool asString)
  555. {
  556. if (prop == "TYPE") {
  557. this->Type = cmState::StringToCacheEntryType(value ? value : "STRING");
  558. } else if (prop == "VALUE") {
  559. if (value) {
  560. if (!this->Value.empty() && *value && !asString) {
  561. this->Value += ";";
  562. }
  563. this->Value += value;
  564. }
  565. } else {
  566. this->Properties.AppendProperty(prop, value, asString);
  567. }
  568. }
  569. const char* cmCacheManager::CacheIterator::GetProperty(
  570. const std::string& prop) const
  571. {
  572. if (!this->IsAtEnd()) {
  573. return this->GetEntry().GetProperty(prop);
  574. }
  575. return CM_NULLPTR;
  576. }
  577. void cmCacheManager::CacheIterator::SetProperty(const std::string& p,
  578. const char* v)
  579. {
  580. if (!this->IsAtEnd()) {
  581. this->GetEntry().SetProperty(p, v);
  582. }
  583. }
  584. void cmCacheManager::CacheIterator::AppendProperty(const std::string& p,
  585. const char* v,
  586. bool asString)
  587. {
  588. if (!this->IsAtEnd()) {
  589. this->GetEntry().AppendProperty(p, v, asString);
  590. }
  591. }
  592. bool cmCacheManager::CacheIterator::GetPropertyAsBool(
  593. const std::string& prop) const
  594. {
  595. if (const char* value = this->GetProperty(prop)) {
  596. return cmSystemTools::IsOn(value);
  597. }
  598. return false;
  599. }
  600. void cmCacheManager::CacheIterator::SetProperty(const std::string& p, bool v)
  601. {
  602. this->SetProperty(p, v ? "ON" : "OFF");
  603. }
  604. bool cmCacheManager::CacheIterator::PropertyExists(
  605. const std::string& prop) const
  606. {
  607. return this->GetProperty(prop) != CM_NULLPTR;
  608. }