cmCacheManager.cxx 20 KB

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