cmCacheManager.cxx 20 KB

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