cmCacheManager.cxx 29 KB

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