cmCacheManager.cxx 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008
  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::IsType(const char* s)
  62. {
  63. for(int i=0; cmCacheManagerTypes[i]; ++i)
  64. {
  65. if(strcmp(s, cmCacheManagerTypes[i]) == 0)
  66. {
  67. return true;
  68. }
  69. }
  70. return false;
  71. }
  72. bool cmCacheManager::LoadCache(cmMakefile* mf)
  73. {
  74. return this->LoadCache(mf->GetHomeOutputDirectory());
  75. }
  76. bool cmCacheManager::LoadCache(const char* path)
  77. {
  78. return this->LoadCache(path,true);
  79. }
  80. bool cmCacheManager::LoadCache(const char* path,
  81. bool internal)
  82. {
  83. std::set<cmStdString> emptySet;
  84. return this->LoadCache(path, internal, emptySet, emptySet);
  85. }
  86. bool cmCacheManager::ParseEntry(const char* entry,
  87. std::string& var,
  88. std::string& value)
  89. {
  90. // input line is: key:type=value
  91. static cmsys::RegularExpression reg(
  92. "^([^:]*)=(.*[^\r\t ]|[\r\t ]*)[\r\t ]*$");
  93. // input line is: "key":type=value
  94. static cmsys::RegularExpression regQuoted(
  95. "^\"([^\"]*)\"=(.*[^\r\t ]|[\r\t ]*)[\r\t ]*$");
  96. bool flag = false;
  97. if(regQuoted.find(entry))
  98. {
  99. var = regQuoted.match(1);
  100. value = regQuoted.match(2);
  101. flag = true;
  102. }
  103. else if (reg.find(entry))
  104. {
  105. var = reg.match(1);
  106. value = reg.match(2);
  107. flag = true;
  108. }
  109. // if value is enclosed in single quotes ('foo') then remove them
  110. // it is used to enclose trailing space or tab
  111. if (flag &&
  112. value.size() >= 2 &&
  113. value[0] == '\'' &&
  114. value[value.size() - 1] == '\'')
  115. {
  116. value = value.substr(1,
  117. value.size() - 2);
  118. }
  119. return flag;
  120. }
  121. bool cmCacheManager::ParseEntry(const char* entry,
  122. std::string& var,
  123. std::string& value,
  124. CacheEntryType& type)
  125. {
  126. // input line is: key:type=value
  127. static cmsys::RegularExpression reg(
  128. "^([^:]*):([^=]*)=(.*[^\r\t ]|[\r\t ]*)[\r\t ]*$");
  129. // input line is: "key":type=value
  130. static cmsys::RegularExpression regQuoted(
  131. "^\"([^\"]*)\":([^=]*)=(.*[^\r\t ]|[\r\t ]*)[\r\t ]*$");
  132. bool flag = false;
  133. if(regQuoted.find(entry))
  134. {
  135. var = regQuoted.match(1);
  136. type = cmCacheManager::StringToType(regQuoted.match(2).c_str());
  137. value = regQuoted.match(3);
  138. flag = true;
  139. }
  140. else if (reg.find(entry))
  141. {
  142. var = reg.match(1);
  143. type = cmCacheManager::StringToType(reg.match(2).c_str());
  144. value = reg.match(3);
  145. flag = true;
  146. }
  147. // if value is enclosed in single quotes ('foo') then remove them
  148. // it is used to enclose trailing space or tab
  149. if (flag &&
  150. value.size() >= 2 &&
  151. value[0] == '\'' &&
  152. value[value.size() - 1] == '\'')
  153. {
  154. value = value.substr(1,
  155. value.size() - 2);
  156. }
  157. return flag;
  158. }
  159. void cmCacheManager::CleanCMakeFiles(const char* path)
  160. {
  161. std::string glob = path;
  162. glob += cmake::GetCMakeFilesDirectory();
  163. glob += "/*.cmake";
  164. cmsys::Glob globIt;
  165. globIt.FindFiles(glob);
  166. std::vector<std::string> files = globIt.GetFiles();
  167. for(std::vector<std::string>::iterator i = files.begin();
  168. i != files.end(); ++i)
  169. {
  170. cmSystemTools::RemoveFile(i->c_str());
  171. }
  172. }
  173. bool cmCacheManager::LoadCache(const char* path,
  174. bool internal,
  175. std::set<cmStdString>& excludes,
  176. std::set<cmStdString>& includes)
  177. {
  178. std::string cacheFile = path;
  179. cacheFile += "/CMakeCache.txt";
  180. // clear the old cache, if we are reading in internal values
  181. if ( internal )
  182. {
  183. this->Cache.clear();
  184. }
  185. if(!cmSystemTools::FileExists(cacheFile.c_str()))
  186. {
  187. this->CleanCMakeFiles(path);
  188. return false;
  189. }
  190. std::ifstream fin(cacheFile.c_str());
  191. if(!fin)
  192. {
  193. return false;
  194. }
  195. const char *realbuffer;
  196. std::string buffer;
  197. std::string entryKey;
  198. while(fin)
  199. {
  200. // Format is key:type=value
  201. std::string helpString;
  202. CacheEntry e;
  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 CMackeCache.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.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. if ( value )
  672. {
  673. e.Value = value;
  674. e.Initialized = true;
  675. }
  676. else
  677. {
  678. e.Value = "";
  679. }
  680. e.Type = type;
  681. // make sure we only use unix style paths
  682. if(type == FILEPATH || type == PATH)
  683. {
  684. if(e.Value.find(';') != e.Value.npos)
  685. {
  686. std::vector<std::string> paths;
  687. cmSystemTools::ExpandListArgument(e.Value, paths);
  688. const char* sep = "";
  689. e.Value = "";
  690. for(std::vector<std::string>::iterator i = paths.begin();
  691. i != paths.end(); ++i)
  692. {
  693. cmSystemTools::ConvertToUnixSlashes(*i);
  694. e.Value += sep;
  695. e.Value += *i;
  696. sep = ";";
  697. }
  698. }
  699. else
  700. {
  701. cmSystemTools::ConvertToUnixSlashes(e.Value);
  702. }
  703. }
  704. e.SetProperty("HELPSTRING", helpString? helpString :
  705. "(This variable does not exist and should not be used)");
  706. this->Cache[key] = e;
  707. }
  708. void cmCacheManager::AddCacheEntry(const char* key, bool v,
  709. const char* helpString)
  710. {
  711. if(v)
  712. {
  713. this->AddCacheEntry(key, "ON", helpString, cmCacheManager::BOOL);
  714. }
  715. else
  716. {
  717. this->AddCacheEntry(key, "OFF", helpString, cmCacheManager::BOOL);
  718. }
  719. }
  720. bool cmCacheManager::CacheIterator::IsAtEnd() const
  721. {
  722. return this->Position == this->Container.Cache.end();
  723. }
  724. void cmCacheManager::CacheIterator::Begin()
  725. {
  726. this->Position = this->Container.Cache.begin();
  727. }
  728. bool cmCacheManager::CacheIterator::Find(const char* key)
  729. {
  730. this->Position = this->Container.Cache.find(key);
  731. return !this->IsAtEnd();
  732. }
  733. void cmCacheManager::CacheIterator::Next()
  734. {
  735. if (!this->IsAtEnd())
  736. {
  737. ++this->Position;
  738. }
  739. }
  740. void cmCacheManager::CacheIterator::SetValue(const char* value)
  741. {
  742. if (this->IsAtEnd())
  743. {
  744. return;
  745. }
  746. CacheEntry* entry = &this->GetEntry();
  747. if ( value )
  748. {
  749. entry->Value = value;
  750. entry->Initialized = true;
  751. }
  752. else
  753. {
  754. entry->Value = "";
  755. }
  756. }
  757. //----------------------------------------------------------------------------
  758. bool cmCacheManager::CacheIterator::GetValueAsBool() const
  759. {
  760. return cmSystemTools::IsOn(this->GetEntry().Value.c_str());
  761. }
  762. //----------------------------------------------------------------------------
  763. const char*
  764. cmCacheManager::CacheEntry::GetProperty(const char* prop) const
  765. {
  766. if(strcmp(prop, "TYPE") == 0)
  767. {
  768. return cmCacheManagerTypes[this->Type];
  769. }
  770. else if(strcmp(prop, "VALUE") == 0)
  771. {
  772. return this->Value.c_str();
  773. }
  774. bool c = false;
  775. return
  776. this->Properties.GetPropertyValue(prop, cmProperty::CACHE, c);
  777. }
  778. //----------------------------------------------------------------------------
  779. void cmCacheManager::CacheEntry::SetProperty(const char* prop,
  780. const char* value)
  781. {
  782. if(strcmp(prop, "TYPE") == 0)
  783. {
  784. this->Type = cmCacheManager::StringToType(value? value : "STRING");
  785. }
  786. else if(strcmp(prop, "VALUE") == 0)
  787. {
  788. this->Value = value? value : "";
  789. }
  790. else
  791. {
  792. this->Properties.SetProperty(prop, value, cmProperty::CACHE);
  793. }
  794. }
  795. //----------------------------------------------------------------------------
  796. void cmCacheManager::CacheEntry::AppendProperty(const char* prop,
  797. const char* value)
  798. {
  799. if(strcmp(prop, "TYPE") == 0)
  800. {
  801. this->Type = cmCacheManager::StringToType(value? value : "STRING");
  802. }
  803. else if(strcmp(prop, "VALUE") == 0)
  804. {
  805. if(value)
  806. {
  807. if(!this->Value.empty() && *value)
  808. {
  809. this->Value += ";";
  810. }
  811. this->Value += value;
  812. }
  813. }
  814. else
  815. {
  816. this->Properties.AppendProperty(prop, value, cmProperty::CACHE);
  817. }
  818. }
  819. //----------------------------------------------------------------------------
  820. const char* cmCacheManager::CacheIterator::GetProperty(const char* prop) const
  821. {
  822. if(!this->IsAtEnd())
  823. {
  824. return this->GetEntry().GetProperty(prop);
  825. }
  826. return 0;
  827. }
  828. //----------------------------------------------------------------------------
  829. void cmCacheManager::CacheIterator::SetProperty(const char* p, const char* v)
  830. {
  831. if(!this->IsAtEnd())
  832. {
  833. return this->GetEntry().SetProperty(p, v);
  834. }
  835. }
  836. //----------------------------------------------------------------------------
  837. void cmCacheManager::CacheIterator::AppendProperty(const char* p,
  838. const char* v)
  839. {
  840. if(!this->IsAtEnd())
  841. {
  842. this->GetEntry().AppendProperty(p, v);
  843. }
  844. }
  845. //----------------------------------------------------------------------------
  846. bool cmCacheManager::CacheIterator::GetPropertyAsBool(const char* prop) const
  847. {
  848. if(const char* value = this->GetProperty(prop))
  849. {
  850. return cmSystemTools::IsOn(value);
  851. }
  852. return false;
  853. }
  854. //----------------------------------------------------------------------------
  855. void cmCacheManager::CacheIterator::SetProperty(const char* p, bool v)
  856. {
  857. this->SetProperty(p, v ? "ON" : "OFF");
  858. }
  859. //----------------------------------------------------------------------------
  860. bool cmCacheManager::CacheIterator::PropertyExists(const char* prop) const
  861. {
  862. return this->GetProperty(prop)? true:false;
  863. }
  864. //----------------------------------------------------------------------------
  865. bool cmCacheManager::NeedCacheCompatibility(int major, int minor)
  866. {
  867. // Compatibility is not needed if the cache version is zero because
  868. // the cache was created or modified by the user.
  869. if(this->CacheMajorVersion == 0)
  870. {
  871. return false;
  872. }
  873. // Compatibility is needed if the cache version is equal to or lower
  874. // than the given version.
  875. unsigned int actual_compat =
  876. CMake_VERSION_ENCODE(this->CacheMajorVersion, this->CacheMinorVersion, 0);
  877. return (actual_compat &&
  878. actual_compat <= CMake_VERSION_ENCODE(major, minor, 0));
  879. }
  880. //----------------------------------------------------------------------------
  881. void cmCacheManager::DefineProperties(cmake *cm)
  882. {
  883. cm->DefineProperty
  884. ("ADVANCED", cmProperty::CACHE,
  885. "True if entry should be hidden by default in GUIs.",
  886. "This is a boolean value indicating whether the entry is considered "
  887. "interesting only for advanced configuration. "
  888. "The mark_as_advanced() command modifies this property."
  889. );
  890. cm->DefineProperty
  891. ("HELPSTRING", cmProperty::CACHE,
  892. "Help associated with entry in GUIs.",
  893. "This string summarizes the purpose of an entry to help users set it "
  894. "through a CMake GUI."
  895. );
  896. cm->DefineProperty
  897. ("TYPE", cmProperty::CACHE,
  898. "Widget type for entry in GUIs.",
  899. "Cache entry values are always strings, but CMake GUIs present widgets "
  900. "to help users set values. "
  901. "The GUIs use this property as a hint to determine the widget type. "
  902. "Valid TYPE values are:\n"
  903. " BOOL = Boolean ON/OFF value.\n"
  904. " PATH = Path to a directory.\n"
  905. " FILEPATH = Path to a file.\n"
  906. " STRING = Generic string value.\n"
  907. " INTERNAL = Do not present in GUI at all.\n"
  908. " STATIC = Value managed by CMake, do not change.\n"
  909. " UNINITIALIZED = Type not yet specified.\n"
  910. "Generally the TYPE of a cache entry should be set by the command "
  911. "which creates it (set, option, find_library, etc.)."
  912. );
  913. cm->DefineProperty
  914. ("STRINGS", cmProperty::CACHE,
  915. "Enumerate possible STRING entry values for GUI selection.",
  916. "For cache entries with type STRING, this enumerates a set of values. "
  917. "CMake GUIs may use this to provide a selection widget instead of a "
  918. "generic string entry field. "
  919. "This is for convenience only. "
  920. "CMake does not enforce that the value matches one of those listed."
  921. );
  922. cm->DefineProperty
  923. ("VALUE", cmProperty::CACHE,
  924. "Value of a cache entry.",
  925. "This property maps to the actual value of a cache entry. "
  926. "Setting this property always sets the value without checking, so "
  927. "use with care."
  928. );
  929. }