cmCacheManager.cxx 28 KB

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