cmCacheManager.cxx 29 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006
  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. bool asString)
  791. {
  792. if(strcmp(prop, "TYPE") == 0)
  793. {
  794. this->Type = cmCacheManager::StringToType(value? value : "STRING");
  795. }
  796. else if(strcmp(prop, "VALUE") == 0)
  797. {
  798. if(value)
  799. {
  800. if(!this->Value.empty() && *value && !asString)
  801. {
  802. this->Value += ";";
  803. }
  804. this->Value += value;
  805. }
  806. }
  807. else
  808. {
  809. this->Properties.AppendProperty(prop, value, cmProperty::CACHE, asString);
  810. }
  811. }
  812. //----------------------------------------------------------------------------
  813. const char* cmCacheManager::CacheIterator::GetProperty(const char* prop) const
  814. {
  815. if(!this->IsAtEnd())
  816. {
  817. return this->GetEntry().GetProperty(prop);
  818. }
  819. return 0;
  820. }
  821. //----------------------------------------------------------------------------
  822. void cmCacheManager::CacheIterator::SetProperty(const char* p, const char* v)
  823. {
  824. if(!this->IsAtEnd())
  825. {
  826. this->GetEntry().SetProperty(p, v);
  827. }
  828. }
  829. //----------------------------------------------------------------------------
  830. void cmCacheManager::CacheIterator::AppendProperty(const char* p,
  831. const char* v,
  832. bool asString)
  833. {
  834. if(!this->IsAtEnd())
  835. {
  836. this->GetEntry().AppendProperty(p, v, asString);
  837. }
  838. }
  839. //----------------------------------------------------------------------------
  840. bool cmCacheManager::CacheIterator::GetPropertyAsBool(const char* prop) const
  841. {
  842. if(const char* value = this->GetProperty(prop))
  843. {
  844. return cmSystemTools::IsOn(value);
  845. }
  846. return false;
  847. }
  848. //----------------------------------------------------------------------------
  849. void cmCacheManager::CacheIterator::SetProperty(const char* p, bool v)
  850. {
  851. this->SetProperty(p, v ? "ON" : "OFF");
  852. }
  853. //----------------------------------------------------------------------------
  854. bool cmCacheManager::CacheIterator::PropertyExists(const char* prop) const
  855. {
  856. return this->GetProperty(prop)? true:false;
  857. }
  858. //----------------------------------------------------------------------------
  859. bool cmCacheManager::NeedCacheCompatibility(int major, int minor)
  860. {
  861. // Compatibility is not needed if the cache version is zero because
  862. // the cache was created or modified by the user.
  863. if(this->CacheMajorVersion == 0)
  864. {
  865. return false;
  866. }
  867. // Compatibility is needed if the cache version is equal to or lower
  868. // than the given version.
  869. unsigned int actual_compat =
  870. CMake_VERSION_ENCODE(this->CacheMajorVersion, this->CacheMinorVersion, 0);
  871. return (actual_compat &&
  872. actual_compat <= CMake_VERSION_ENCODE(major, minor, 0));
  873. }
  874. //----------------------------------------------------------------------------
  875. void cmCacheManager::DefineProperties(cmake *cm)
  876. {
  877. cm->DefineProperty
  878. ("ADVANCED", cmProperty::CACHE,
  879. "True if entry should be hidden by default in GUIs.",
  880. "This is a boolean value indicating whether the entry is considered "
  881. "interesting only for advanced configuration. "
  882. "The mark_as_advanced() command modifies this property."
  883. );
  884. cm->DefineProperty
  885. ("HELPSTRING", cmProperty::CACHE,
  886. "Help associated with entry in GUIs.",
  887. "This string summarizes the purpose of an entry to help users set it "
  888. "through a CMake GUI."
  889. );
  890. cm->DefineProperty
  891. ("TYPE", cmProperty::CACHE,
  892. "Widget type for entry in GUIs.",
  893. "Cache entry values are always strings, but CMake GUIs present widgets "
  894. "to help users set values. "
  895. "The GUIs use this property as a hint to determine the widget type. "
  896. "Valid TYPE values are:\n"
  897. " BOOL = Boolean ON/OFF value.\n"
  898. " PATH = Path to a directory.\n"
  899. " FILEPATH = Path to a file.\n"
  900. " STRING = Generic string value.\n"
  901. " INTERNAL = Do not present in GUI at all.\n"
  902. " STATIC = Value managed by CMake, do not change.\n"
  903. " UNINITIALIZED = Type not yet specified.\n"
  904. "Generally the TYPE of a cache entry should be set by the command "
  905. "which creates it (set, option, find_library, etc.)."
  906. );
  907. cm->DefineProperty
  908. ("MODIFIED", cmProperty::CACHE,
  909. "Internal management property. Do not set or get.",
  910. "This is an internal cache entry property managed by CMake to "
  911. "track interactive user modification of entries. Ignore it."
  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. }