cmCacheManager.cxx 28 KB

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