Updated formatting of documentation plus a little reorganization.
[cmake.git] / Source / cmCacheManager.cxx
blobcb37e86c6fd7cac13c9e54b993a016352f3554bb
1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmCacheManager.cxx,v $
5 Language: C++
6 Date: $Date: 2009-09-11 14:04:06 $
7 Version: $Revision: 1.113 $
9 Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
10 See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
12 This software is distributed WITHOUT ANY WARRANTY; without even
13 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 PURPOSE. See the above copyright notices for more information.
16 =========================================================================*/
18 #include "cmCacheManager.h"
19 #include "cmSystemTools.h"
20 #include "cmCacheManager.h"
21 #include "cmMakefile.h"
22 #include "cmake.h"
23 #include "cmVersion.h"
25 #include <cmsys/Directory.hxx>
26 #include <cmsys/Glob.hxx>
28 #include <cmsys/RegularExpression.hxx>
30 #if defined(_WIN32) || defined(__CYGWIN__)
31 # include <windows.h>
32 #endif // _WIN32
34 const char* cmCacheManagerTypes[] =
35 { "BOOL",
36 "PATH",
37 "FILEPATH",
38 "STRING",
39 "INTERNAL",
40 "STATIC",
41 "UNINITIALIZED",
45 cmCacheManager::cmCacheManager(cmake* cm)
47 this->CacheMajorVersion = 0;
48 this->CacheMinorVersion = 0;
49 this->CMakeInstance = cm;
52 const char* cmCacheManager::TypeToString(cmCacheManager::CacheEntryType type)
54 if ( type > 6 )
56 return cmCacheManagerTypes[6];
58 return cmCacheManagerTypes[type];
61 cmCacheManager::CacheEntryType cmCacheManager::StringToType(const char* s)
63 int i = 0;
64 while(cmCacheManagerTypes[i])
66 if(strcmp(s, cmCacheManagerTypes[i]) == 0)
68 return static_cast<CacheEntryType>(i);
70 ++i;
72 return STRING;
75 bool cmCacheManager::IsType(const char* s)
77 for(int i=0; cmCacheManagerTypes[i]; ++i)
79 if(strcmp(s, cmCacheManagerTypes[i]) == 0)
81 return true;
84 return false;
87 bool cmCacheManager::LoadCache(cmMakefile* mf)
89 return this->LoadCache(mf->GetHomeOutputDirectory());
93 bool cmCacheManager::LoadCache(const char* path)
95 return this->LoadCache(path,true);
98 bool cmCacheManager::LoadCache(const char* path,
99 bool internal)
101 std::set<cmStdString> emptySet;
102 return this->LoadCache(path, internal, emptySet, emptySet);
105 bool cmCacheManager::ParseEntry(const char* entry,
106 std::string& var,
107 std::string& value)
109 // input line is: key:type=value
110 static cmsys::RegularExpression reg(
111 "^([^:]*)=(.*[^\r\t ]|[\r\t ]*)[\r\t ]*$");
112 // input line is: "key":type=value
113 static cmsys::RegularExpression regQuoted(
114 "^\"([^\"]*)\"=(.*[^\r\t ]|[\r\t ]*)[\r\t ]*$");
115 bool flag = false;
116 if(regQuoted.find(entry))
118 var = regQuoted.match(1);
119 value = regQuoted.match(2);
120 flag = true;
122 else if (reg.find(entry))
124 var = reg.match(1);
125 value = reg.match(2);
126 flag = true;
129 // if value is enclosed in single quotes ('foo') then remove them
130 // it is used to enclose trailing space or tab
131 if (flag &&
132 value.size() >= 2 &&
133 value[0] == '\'' &&
134 value[value.size() - 1] == '\'')
136 value = value.substr(1,
137 value.size() - 2);
140 return flag;
143 bool cmCacheManager::ParseEntry(const char* entry,
144 std::string& var,
145 std::string& value,
146 CacheEntryType& type)
148 // input line is: key:type=value
149 static cmsys::RegularExpression reg(
150 "^([^:]*):([^=]*)=(.*[^\r\t ]|[\r\t ]*)[\r\t ]*$");
151 // input line is: "key":type=value
152 static cmsys::RegularExpression regQuoted(
153 "^\"([^\"]*)\":([^=]*)=(.*[^\r\t ]|[\r\t ]*)[\r\t ]*$");
154 bool flag = false;
155 if(regQuoted.find(entry))
157 var = regQuoted.match(1);
158 type = cmCacheManager::StringToType(regQuoted.match(2).c_str());
159 value = regQuoted.match(3);
160 flag = true;
162 else if (reg.find(entry))
164 var = reg.match(1);
165 type = cmCacheManager::StringToType(reg.match(2).c_str());
166 value = reg.match(3);
167 flag = true;
170 // if value is enclosed in single quotes ('foo') then remove them
171 // it is used to enclose trailing space or tab
172 if (flag &&
173 value.size() >= 2 &&
174 value[0] == '\'' &&
175 value[value.size() - 1] == '\'')
177 value = value.substr(1,
178 value.size() - 2);
181 return flag;
184 void cmCacheManager::CleanCMakeFiles(const char* path)
186 std::string glob = path;
187 glob += cmake::GetCMakeFilesDirectory();
188 glob += "/*.cmake";
189 cmsys::Glob globIt;
190 globIt.FindFiles(glob);
191 std::vector<std::string> files = globIt.GetFiles();
192 for(std::vector<std::string>::iterator i = files.begin();
193 i != files.end(); ++i)
195 cmSystemTools::RemoveFile(i->c_str());
199 bool cmCacheManager::LoadCache(const char* path,
200 bool internal,
201 std::set<cmStdString>& excludes,
202 std::set<cmStdString>& includes)
204 std::string cacheFile = path;
205 cacheFile += "/CMakeCache.txt";
206 // clear the old cache, if we are reading in internal values
207 if ( internal )
209 this->Cache.clear();
211 if(!cmSystemTools::FileExists(cacheFile.c_str()))
213 this->CleanCMakeFiles(path);
214 return false;
217 std::ifstream fin(cacheFile.c_str());
218 if(!fin)
220 return false;
222 const char *realbuffer;
223 std::string buffer;
224 std::string entryKey;
225 while(fin)
227 // Format is key:type=value
228 std::string helpString;
229 CacheEntry e;
230 e.Properties.SetCMakeInstance(this->CMakeInstance);
231 cmSystemTools::GetLineFromStream(fin, buffer);
232 realbuffer = buffer.c_str();
233 while(*realbuffer != '0' &&
234 (*realbuffer == ' ' ||
235 *realbuffer == '\t' ||
236 *realbuffer == '\r' ||
237 *realbuffer == '\n'))
239 realbuffer++;
241 // skip blank lines and comment lines
242 if(realbuffer[0] == '#' || realbuffer[0] == 0)
244 continue;
246 while(realbuffer[0] == '/' && realbuffer[1] == '/')
248 if ((realbuffer[2] == '\\') && (realbuffer[3]=='n'))
250 helpString += "\n";
251 helpString += &realbuffer[4];
253 else
255 helpString += &realbuffer[2];
257 cmSystemTools::GetLineFromStream(fin, buffer);
258 realbuffer = buffer.c_str();
259 if(!fin)
261 continue;
264 e.SetProperty("HELPSTRING", helpString.c_str());
265 if(cmCacheManager::ParseEntry(realbuffer, entryKey, e.Value, e.Type))
267 if ( excludes.find(entryKey) == excludes.end() )
269 // Load internal values if internal is set.
270 // If the entry is not internal to the cache being loaded
271 // or if it is in the list of internal entries to be
272 // imported, load it.
273 if ( internal || (e.Type != INTERNAL) ||
274 (includes.find(entryKey) != includes.end()) )
276 // If we are loading the cache from another project,
277 // make all loaded entries internal so that it is
278 // not visible in the gui
279 if (!internal)
281 e.Type = INTERNAL;
282 helpString = "DO NOT EDIT, ";
283 helpString += entryKey;
284 helpString += " loaded from external file. "
285 "To change this value edit this file: ";
286 helpString += path;
287 helpString += "/CMakeCache.txt" ;
288 e.SetProperty("HELPSTRING", helpString.c_str());
290 if(!this->ReadPropertyEntry(entryKey, e))
292 e.Initialized = true;
293 this->Cache[entryKey] = e;
298 else
300 cmSystemTools::Error("Parse error in cache file ", cacheFile.c_str(),
301 ". Offending entry: ", realbuffer);
304 this->CacheMajorVersion = 0;
305 this->CacheMinorVersion = 0;
306 if(const char* cmajor = this->GetCacheValue("CMAKE_CACHE_MAJOR_VERSION"))
308 unsigned int v=0;
309 if(sscanf(cmajor, "%u", &v) == 1)
311 this->CacheMajorVersion = v;
313 if(const char* cminor = this->GetCacheValue("CMAKE_CACHE_MINOR_VERSION"))
315 if(sscanf(cminor, "%u", &v) == 1)
317 this->CacheMinorVersion = v;
321 else
323 // CMake version not found in the list file.
324 // Set as version 0.0
325 this->AddCacheEntry("CMAKE_CACHE_MINOR_VERSION", "0",
326 "Minor version of cmake used to create the "
327 "current loaded cache", cmCacheManager::INTERNAL);
328 this->AddCacheEntry("CMAKE_CACHE_MAJOR_VERSION", "0",
329 "Major version of cmake used to create the "
330 "current loaded cache", cmCacheManager::INTERNAL);
333 // check to make sure the cache directory has not
334 // been moved
335 if ( internal && this->GetCacheValue("CMAKE_CACHEFILE_DIR") )
337 std::string currentcwd = path;
338 std::string oldcwd = this->GetCacheValue("CMAKE_CACHEFILE_DIR");
339 cmSystemTools::ConvertToUnixSlashes(currentcwd);
340 currentcwd += "/CMakeCache.txt";
341 oldcwd += "/CMakeCache.txt";
342 if(!cmSystemTools::SameFile(oldcwd.c_str(), currentcwd.c_str()))
344 std::string message =
345 std::string("The current CMakeCache.txt directory ") +
346 currentcwd + std::string(" is different than the directory ") +
347 std::string(this->GetCacheValue("CMAKE_CACHEFILE_DIR")) +
348 std::string(" where CMackeCache.txt was created. This may result "
349 "in binaries being created in the wrong place. If you "
350 "are not sure, reedit the CMakeCache.txt");
351 cmSystemTools::Error(message.c_str());
354 return true;
357 //----------------------------------------------------------------------------
358 const char* cmCacheManager::PersistentProperties[] =
360 "ADVANCED",
361 "MODIFIED",
362 "STRINGS",
366 //----------------------------------------------------------------------------
367 bool cmCacheManager::ReadPropertyEntry(std::string const& entryKey,
368 CacheEntry& e)
370 // All property entries are internal.
371 if(e.Type != cmCacheManager::INTERNAL)
373 return false;
376 const char* end = entryKey.c_str() + entryKey.size();
377 for(const char** p = this->PersistentProperties; *p; ++p)
379 std::string::size_type plen = strlen(*p) + 1;
380 if(entryKey.size() > plen && *(end-plen) == '-' &&
381 strcmp(end-plen+1, *p) == 0)
383 std::string key = entryKey.substr(0, entryKey.size() - plen);
384 cmCacheManager::CacheIterator it = this->GetCacheIterator(key.c_str());
385 if(it.IsAtEnd())
387 // Create an entry and store the property.
388 CacheEntry& ne = this->Cache[key];
389 ne.Properties.SetCMakeInstance(this->CMakeInstance);
390 ne.Type = cmCacheManager::UNINITIALIZED;
391 ne.SetProperty(*p, e.Value.c_str());
393 else
395 // Store this property on its entry.
396 it.SetProperty(*p, e.Value.c_str());
398 return true;
401 return false;
404 //----------------------------------------------------------------------------
405 void cmCacheManager::WritePropertyEntries(std::ostream& os,
406 CacheIterator const& i)
408 for(const char** p = this->PersistentProperties; *p; ++p)
410 if(const char* value = i.GetProperty(*p))
412 std::string helpstring = *p;
413 helpstring += " property for variable: ";
414 helpstring += i.GetName();
415 cmCacheManager::OutputHelpString(os, helpstring);
417 std::string key = i.GetName();
418 key += "-";
419 key += *p;
420 this->OutputKey(os, key);
421 os << ":INTERNAL=";
422 this->OutputValue(os, value);
423 os << "\n";
428 bool cmCacheManager::SaveCache(cmMakefile* mf)
430 return this->SaveCache(mf->GetHomeOutputDirectory());
434 bool cmCacheManager::SaveCache(const char* path)
436 std::string cacheFile = path;
437 cacheFile += "/CMakeCache.txt";
438 std::string tempFile = cacheFile;
439 tempFile += ".tmp";
440 std::ofstream fout(tempFile.c_str());
441 if(!fout)
443 cmSystemTools::Error("Unable to open cache file for save. ",
444 cacheFile.c_str());
445 cmSystemTools::ReportLastSystemError("");
446 return false;
448 // before writing the cache, update the version numbers
449 // to the
450 char temp[1024];
451 sprintf(temp, "%d", cmVersion::GetMinorVersion());
452 this->AddCacheEntry("CMAKE_CACHE_MINOR_VERSION", temp,
453 "Minor version of cmake used to create the "
454 "current loaded cache", cmCacheManager::INTERNAL);
455 sprintf(temp, "%d", cmVersion::GetMajorVersion());
456 this->AddCacheEntry("CMAKE_CACHE_MAJOR_VERSION", temp,
457 "Major version of cmake used to create the "
458 "current loaded cache", cmCacheManager::INTERNAL);
459 sprintf(temp, "%d", cmVersion::GetPatchVersion());
460 this->AddCacheEntry("CMAKE_CACHE_PATCH_VERSION", temp,
461 "Patch version of cmake used to create the "
462 "current loaded cache", cmCacheManager::INTERNAL);
464 // Let us store the current working directory so that if somebody
465 // Copies it, he will not be surprised
466 std::string currentcwd = path;
467 if ( currentcwd[0] >= 'A' && currentcwd[0] <= 'Z' &&
468 currentcwd[1] == ':' )
470 currentcwd[0] = currentcwd[0] - 'A' + 'a';
472 cmSystemTools::ConvertToUnixSlashes(currentcwd);
473 this->AddCacheEntry("CMAKE_CACHEFILE_DIR", currentcwd.c_str(),
474 "This is the directory where this CMakeCahe.txt"
475 " was created", cmCacheManager::INTERNAL);
477 fout << "# This is the CMakeCache file.\n"
478 << "# For build in directory: " << currentcwd << "\n";
479 cmCacheManager::CacheEntry* cmakeCacheEntry
480 = this->GetCacheEntry("CMAKE_COMMAND");
481 if ( cmakeCacheEntry )
483 fout << "# It was generated by CMake: " <<
484 cmakeCacheEntry->Value << std::endl;
487 fout << "# You can edit this file to change values found and used by cmake."
488 << std::endl
489 << "# If you do not want to change any of the values, simply exit the "
490 "editor." << std::endl
491 << "# If you do want to change a value, simply edit, save, and exit "
492 "the editor." << std::endl
493 << "# The syntax for the file is as follows:\n"
494 << "# KEY:TYPE=VALUE\n"
495 << "# KEY is the name of a variable in the cache.\n"
496 << "# TYPE is a hint to GUI's for the type of VALUE, DO NOT EDIT "
497 "TYPE!." << std::endl
498 << "# VALUE is the current value for the KEY.\n\n";
500 fout << "########################\n";
501 fout << "# EXTERNAL cache entries\n";
502 fout << "########################\n";
503 fout << "\n";
505 for( std::map<cmStdString, CacheEntry>::const_iterator i =
506 this->Cache.begin(); i != this->Cache.end(); ++i)
508 const CacheEntry& ce = (*i).second;
509 CacheEntryType t = ce.Type;
510 if(!ce.Initialized)
513 // This should be added in, but is not for now.
514 cmSystemTools::Error("Cache entry \"", (*i).first.c_str(),
515 "\" is uninitialized");
518 else if(t != INTERNAL)
520 // Format is key:type=value
521 if(const char* help = ce.GetProperty("HELPSTRING"))
523 cmCacheManager::OutputHelpString(fout, help);
525 else
527 cmCacheManager::OutputHelpString(fout, "Missing description");
529 this->OutputKey(fout, i->first);
530 fout << ":" << cmCacheManagerTypes[t] << "=";
531 this->OutputValue(fout, ce.Value);
532 fout << "\n\n";
536 fout << "\n";
537 fout << "########################\n";
538 fout << "# INTERNAL cache entries\n";
539 fout << "########################\n";
540 fout << "\n";
542 for( cmCacheManager::CacheIterator i = this->NewIterator();
543 !i.IsAtEnd(); i.Next())
545 if ( !i.Initialized() )
547 continue;
550 CacheEntryType t = i.GetType();
551 this->WritePropertyEntries(fout, i);
552 if(t == cmCacheManager::INTERNAL)
554 // Format is key:type=value
555 if(const char* help = i.GetProperty("HELPSTRING"))
557 this->OutputHelpString(fout, help);
559 this->OutputKey(fout, i.GetName());
560 fout << ":" << cmCacheManagerTypes[t] << "=";
561 this->OutputValue(fout, i.GetValue());
562 fout << "\n";
565 fout << "\n";
566 fout.close();
567 cmSystemTools::CopyFileIfDifferent(tempFile.c_str(),
568 cacheFile.c_str());
569 cmSystemTools::RemoveFile(tempFile.c_str());
570 std::string checkCacheFile = path;
571 checkCacheFile += cmake::GetCMakeFilesDirectory();
572 cmSystemTools::MakeDirectory(checkCacheFile.c_str());
573 checkCacheFile += "/cmake.check_cache";
574 std::ofstream checkCache(checkCacheFile.c_str());
575 if(!checkCache)
577 cmSystemTools::Error("Unable to open check cache file for write. ",
578 checkCacheFile.c_str());
579 return false;
581 checkCache << "# This file is generated by cmake for dependency checking "
582 "of the CMakeCache.txt file\n";
583 return true;
586 bool cmCacheManager::DeleteCache(const char* path)
588 std::string cacheFile = path;
589 cmSystemTools::ConvertToUnixSlashes(cacheFile);
590 std::string cmakeFiles = cacheFile;
591 cacheFile += "/CMakeCache.txt";
592 cmSystemTools::RemoveFile(cacheFile.c_str());
593 // now remove the files in the CMakeFiles directory
594 // this cleans up language cache files
595 cmsys::Directory dir;
596 cmakeFiles += cmake::GetCMakeFilesDirectory();
597 dir.Load(cmakeFiles.c_str());
598 for (unsigned long fileNum = 0;
599 fileNum < dir.GetNumberOfFiles();
600 ++fileNum)
602 if(!cmSystemTools::
603 FileIsDirectory(dir.GetFile(fileNum)))
605 std::string fullPath = cmakeFiles;
606 fullPath += "/";
607 fullPath += dir.GetFile(fileNum);
608 cmSystemTools::RemoveFile(fullPath.c_str());
611 return true;
614 void cmCacheManager::OutputKey(std::ostream& fout, std::string const& key)
616 // support : in key name by double quoting
617 const char* q = (key.find(':') != key.npos ||
618 key.find("//") == 0)? "\"" : "";
619 fout << q << key << q;
622 void cmCacheManager::OutputValue(std::ostream& fout, std::string const& value)
624 // if value has trailing space or tab, enclose it in single quotes
625 if (value.size() &&
626 (value[value.size() - 1] == ' ' ||
627 value[value.size() - 1] == '\t'))
629 fout << '\'' << value << '\'';
631 else
633 fout << value;
637 void cmCacheManager::OutputHelpString(std::ostream& fout,
638 const std::string& helpString)
640 std::string::size_type end = helpString.size();
641 if(end == 0)
643 return;
645 std::string oneLine;
646 std::string::size_type pos = 0;
647 for (std::string::size_type i=0; i<=end; i++)
649 if ((i==end)
650 || (helpString[i]=='\n')
651 || ((i-pos >= 60) && (helpString[i]==' ')))
653 fout << "//";
654 if (helpString[pos] == '\n')
656 pos++;
657 fout << "\\n";
659 oneLine = helpString.substr(pos, i - pos);
660 fout << oneLine.c_str() << "\n";
661 pos = i;
666 void cmCacheManager::RemoveCacheEntry(const char* key)
668 CacheEntryMap::iterator i = this->Cache.find(key);
669 if(i != this->Cache.end())
671 this->Cache.erase(i);
676 cmCacheManager::CacheEntry *cmCacheManager::GetCacheEntry(const char* key)
678 CacheEntryMap::iterator i = this->Cache.find(key);
679 if(i != this->Cache.end())
681 return &i->second;
683 return 0;
686 cmCacheManager::CacheIterator cmCacheManager::GetCacheIterator(
687 const char *key)
689 return CacheIterator(*this, key);
692 const char* cmCacheManager::GetCacheValue(const char* key) const
694 CacheEntryMap::const_iterator i = this->Cache.find(key);
695 if(i != this->Cache.end() &&
696 i->second.Initialized)
698 return i->second.Value.c_str();
700 return 0;
704 void cmCacheManager::PrintCache(std::ostream& out) const
706 out << "=================================================" << std::endl;
707 out << "CMakeCache Contents:" << std::endl;
708 for(std::map<cmStdString, CacheEntry>::const_iterator i =
709 this->Cache.begin(); i != this->Cache.end(); ++i)
711 if((*i).second.Type != INTERNAL)
713 out << (*i).first.c_str() << " = " << (*i).second.Value.c_str()
714 << std::endl;
717 out << "\n\n";
718 out << "To change values in the CMakeCache, "
719 << std::endl << "edit CMakeCache.txt in your output directory.\n";
720 out << "=================================================" << std::endl;
724 void cmCacheManager::AddCacheEntry(const char* key,
725 const char* value,
726 const char* helpString,
727 CacheEntryType type)
729 CacheEntry& e = this->Cache[key];
730 e.Properties.SetCMakeInstance(this->CMakeInstance);
731 if ( value )
733 e.Value = value;
734 e.Initialized = true;
736 else
738 e.Value = "";
740 e.Type = type;
741 // make sure we only use unix style paths
742 if(type == FILEPATH || type == PATH)
744 if(e.Value.find(';') != e.Value.npos)
746 std::vector<std::string> paths;
747 cmSystemTools::ExpandListArgument(e.Value, paths);
748 const char* sep = "";
749 e.Value = "";
750 for(std::vector<std::string>::iterator i = paths.begin();
751 i != paths.end(); ++i)
753 cmSystemTools::ConvertToUnixSlashes(*i);
754 e.Value += sep;
755 e.Value += *i;
756 sep = ";";
759 else
761 cmSystemTools::ConvertToUnixSlashes(e.Value);
764 e.SetProperty("HELPSTRING", helpString? helpString :
765 "(This variable does not exist and should not be used)");
766 this->Cache[key] = e;
769 bool cmCacheManager::CacheIterator::IsAtEnd() const
771 return this->Position == this->Container.Cache.end();
774 void cmCacheManager::CacheIterator::Begin()
776 this->Position = this->Container.Cache.begin();
779 bool cmCacheManager::CacheIterator::Find(const char* key)
781 this->Position = this->Container.Cache.find(key);
782 return !this->IsAtEnd();
785 void cmCacheManager::CacheIterator::Next()
787 if (!this->IsAtEnd())
789 ++this->Position;
793 void cmCacheManager::CacheIterator::SetValue(const char* value)
795 if (this->IsAtEnd())
797 return;
799 CacheEntry* entry = &this->GetEntry();
800 if ( value )
802 entry->Value = value;
803 entry->Initialized = true;
805 else
807 entry->Value = "";
811 //----------------------------------------------------------------------------
812 bool cmCacheManager::CacheIterator::GetValueAsBool() const
814 return cmSystemTools::IsOn(this->GetEntry().Value.c_str());
817 //----------------------------------------------------------------------------
818 const char*
819 cmCacheManager::CacheEntry::GetProperty(const char* prop) const
821 if(strcmp(prop, "TYPE") == 0)
823 return cmCacheManagerTypes[this->Type];
825 else if(strcmp(prop, "VALUE") == 0)
827 return this->Value.c_str();
829 bool c = false;
830 return
831 this->Properties.GetPropertyValue(prop, cmProperty::CACHE, c);
834 //----------------------------------------------------------------------------
835 void cmCacheManager::CacheEntry::SetProperty(const char* prop,
836 const char* value)
838 if(strcmp(prop, "TYPE") == 0)
840 this->Type = cmCacheManager::StringToType(value? value : "STRING");
842 else if(strcmp(prop, "VALUE") == 0)
844 this->Value = value? value : "";
846 else
848 this->Properties.SetProperty(prop, value, cmProperty::CACHE);
852 //----------------------------------------------------------------------------
853 void cmCacheManager::CacheEntry::AppendProperty(const char* prop,
854 const char* value)
856 if(strcmp(prop, "TYPE") == 0)
858 this->Type = cmCacheManager::StringToType(value? value : "STRING");
860 else if(strcmp(prop, "VALUE") == 0)
862 if(value)
864 if(!this->Value.empty() && *value)
866 this->Value += ";";
868 this->Value += value;
871 else
873 this->Properties.AppendProperty(prop, value, cmProperty::CACHE);
877 //----------------------------------------------------------------------------
878 const char* cmCacheManager::CacheIterator::GetProperty(const char* prop) const
880 if(!this->IsAtEnd())
882 return this->GetEntry().GetProperty(prop);
884 return 0;
887 //----------------------------------------------------------------------------
888 void cmCacheManager::CacheIterator::SetProperty(const char* p, const char* v)
890 if(!this->IsAtEnd())
892 this->GetEntry().SetProperty(p, v);
896 //----------------------------------------------------------------------------
897 void cmCacheManager::CacheIterator::AppendProperty(const char* p,
898 const char* v)
900 if(!this->IsAtEnd())
902 this->GetEntry().AppendProperty(p, v);
906 //----------------------------------------------------------------------------
907 bool cmCacheManager::CacheIterator::GetPropertyAsBool(const char* prop) const
909 if(const char* value = this->GetProperty(prop))
911 return cmSystemTools::IsOn(value);
913 return false;
916 //----------------------------------------------------------------------------
917 void cmCacheManager::CacheIterator::SetProperty(const char* p, bool v)
919 this->SetProperty(p, v ? "ON" : "OFF");
922 //----------------------------------------------------------------------------
923 bool cmCacheManager::CacheIterator::PropertyExists(const char* prop) const
925 return this->GetProperty(prop)? true:false;
928 //----------------------------------------------------------------------------
929 bool cmCacheManager::NeedCacheCompatibility(int major, int minor)
931 // Compatibility is not needed if the cache version is zero because
932 // the cache was created or modified by the user.
933 if(this->CacheMajorVersion == 0)
935 return false;
938 // Compatibility is needed if the cache version is equal to or lower
939 // than the given version.
940 unsigned int actual_compat =
941 CMake_VERSION_ENCODE(this->CacheMajorVersion, this->CacheMinorVersion, 0);
942 return (actual_compat &&
943 actual_compat <= CMake_VERSION_ENCODE(major, minor, 0));
946 //----------------------------------------------------------------------------
947 void cmCacheManager::DefineProperties(cmake *cm)
949 cm->DefineProperty
950 ("ADVANCED", cmProperty::CACHE,
951 "True if entry should be hidden by default in GUIs.",
952 "This is a boolean value indicating whether the entry is considered "
953 "interesting only for advanced configuration. "
954 "The mark_as_advanced() command modifies this property."
957 cm->DefineProperty
958 ("HELPSTRING", cmProperty::CACHE,
959 "Help associated with entry in GUIs.",
960 "This string summarizes the purpose of an entry to help users set it "
961 "through a CMake GUI."
964 cm->DefineProperty
965 ("TYPE", cmProperty::CACHE,
966 "Widget type for entry in GUIs.",
967 "Cache entry values are always strings, but CMake GUIs present widgets "
968 "to help users set values. "
969 "The GUIs use this property as a hint to determine the widget type. "
970 "Valid TYPE values are:\n"
971 " BOOL = Boolean ON/OFF value.\n"
972 " PATH = Path to a directory.\n"
973 " FILEPATH = Path to a file.\n"
974 " STRING = Generic string value.\n"
975 " INTERNAL = Do not present in GUI at all.\n"
976 " STATIC = Value managed by CMake, do not change.\n"
977 " UNINITIALIZED = Type not yet specified.\n"
978 "Generally the TYPE of a cache entry should be set by the command "
979 "which creates it (set, option, find_library, etc.)."
982 cm->DefineProperty
983 ("MODIFIED", cmProperty::CACHE,
984 "Internal management property. Do not set or get.",
985 "This is an internal cache entry property managed by CMake to "
986 "track interactive user modification of entries. Ignore it."
989 cm->DefineProperty
990 ("STRINGS", cmProperty::CACHE,
991 "Enumerate possible STRING entry values for GUI selection.",
992 "For cache entries with type STRING, this enumerates a set of values. "
993 "CMake GUIs may use this to provide a selection widget instead of a "
994 "generic string entry field. "
995 "This is for convenience only. "
996 "CMake does not enforce that the value matches one of those listed."
999 cm->DefineProperty
1000 ("VALUE", cmProperty::CACHE,
1001 "Value of a cache entry.",
1002 "This property maps to the actual value of a cache entry. "
1003 "Setting this property always sets the value without checking, so "
1004 "use with care."