diff options
Diffstat (limited to 'Source/cmCacheManager.cxx')
-rw-r--r-- | Source/cmCacheManager.cxx | 995 |
1 files changed, 995 insertions, 0 deletions
diff --git a/Source/cmCacheManager.cxx b/Source/cmCacheManager.cxx new file mode 100644 index 0000000..864df8e --- /dev/null +++ b/Source/cmCacheManager.cxx @@ -0,0 +1,995 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2009 Kitware, Inc., Insight Software Consortium + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ + +#include "cmCacheManager.h" +#include "cmSystemTools.h" +#include "cmCacheManager.h" +#include "cmGeneratedFileStream.h" +#include "cmMakefile.h" +#include "cmake.h" +#include "cmVersion.h" + +#include <cmsys/Directory.hxx> +#include <cmsys/Glob.hxx> + +#include <cmsys/RegularExpression.hxx> + +const char* cmCacheManagerTypes[] = +{ "BOOL", + "PATH", + "FILEPATH", + "STRING", + "INTERNAL", + "STATIC", + "UNINITIALIZED", + 0 +}; + +cmCacheManager::cmCacheManager(cmake* cm) +{ + this->CacheMajorVersion = 0; + this->CacheMinorVersion = 0; + this->CMakeInstance = cm; +} + +const char* cmCacheManager::TypeToString(cmCacheManager::CacheEntryType type) +{ + if ( type > 6 ) + { + return cmCacheManagerTypes[6]; + } + return cmCacheManagerTypes[type]; +} + +cmCacheManager::CacheEntryType cmCacheManager::StringToType(const char* s) +{ + int i = 0; + while(cmCacheManagerTypes[i]) + { + if(strcmp(s, cmCacheManagerTypes[i]) == 0) + { + return static_cast<CacheEntryType>(i); + } + ++i; + } + return STRING; +} + +bool cmCacheManager::IsType(const char* s) +{ + for(int i=0; cmCacheManagerTypes[i]; ++i) + { + if(strcmp(s, cmCacheManagerTypes[i]) == 0) + { + return true; + } + } + return false; +} + +bool cmCacheManager::LoadCache(cmMakefile* mf) +{ + return this->LoadCache(mf->GetHomeOutputDirectory()); +} + + +bool cmCacheManager::LoadCache(const char* path) +{ + return this->LoadCache(path,true); +} + +bool cmCacheManager::LoadCache(const char* path, + bool internal) +{ + std::set<cmStdString> emptySet; + return this->LoadCache(path, internal, emptySet, emptySet); +} + +static bool ParseEntryWithoutType(const char* entry, + std::string& var, + std::string& value) +{ + // input line is: key=value + static cmsys::RegularExpression reg( + "^([^=]*)=(.*[^\r\t ]|[\r\t ]*)[\r\t ]*$"); + // input line is: "key"=value + static cmsys::RegularExpression regQuoted( + "^\"([^\"]*)\"=(.*[^\r\t ]|[\r\t ]*)[\r\t ]*$"); + bool flag = false; + if(regQuoted.find(entry)) + { + var = regQuoted.match(1); + value = regQuoted.match(2); + flag = true; + } + else if (reg.find(entry)) + { + var = reg.match(1); + value = reg.match(2); + flag = true; + } + + // if value is enclosed in single quotes ('foo') then remove them + // it is used to enclose trailing space or tab + if (flag && + value.size() >= 2 && + value[0] == '\'' && + value[value.size() - 1] == '\'') + { + value = value.substr(1, + value.size() - 2); + } + + return flag; +} + +bool cmCacheManager::ParseEntry(const char* entry, + std::string& var, + std::string& value, + CacheEntryType& type) +{ + // input line is: key:type=value + static cmsys::RegularExpression reg( + "^([^:]*):([^=]*)=(.*[^\r\t ]|[\r\t ]*)[\r\t ]*$"); + // input line is: "key":type=value + static cmsys::RegularExpression regQuoted( + "^\"([^\"]*)\":([^=]*)=(.*[^\r\t ]|[\r\t ]*)[\r\t ]*$"); + bool flag = false; + if(regQuoted.find(entry)) + { + var = regQuoted.match(1); + type = cmCacheManager::StringToType(regQuoted.match(2).c_str()); + value = regQuoted.match(3); + flag = true; + } + else if (reg.find(entry)) + { + var = reg.match(1); + type = cmCacheManager::StringToType(reg.match(2).c_str()); + value = reg.match(3); + flag = true; + } + + // if value is enclosed in single quotes ('foo') then remove them + // it is used to enclose trailing space or tab + if (flag && + value.size() >= 2 && + value[0] == '\'' && + value[value.size() - 1] == '\'') + { + value = value.substr(1, + value.size() - 2); + } + + if (!flag) + { + return ParseEntryWithoutType(entry, var, value); + } + + return flag; +} + +void cmCacheManager::CleanCMakeFiles(const char* path) +{ + std::string glob = path; + glob += cmake::GetCMakeFilesDirectory(); + glob += "/*.cmake"; + cmsys::Glob globIt; + globIt.FindFiles(glob); + std::vector<std::string> files = globIt.GetFiles(); + for(std::vector<std::string>::iterator i = files.begin(); + i != files.end(); ++i) + { + cmSystemTools::RemoveFile(i->c_str()); + } +} + +bool cmCacheManager::LoadCache(const char* path, + bool internal, + std::set<cmStdString>& excludes, + std::set<cmStdString>& includes) +{ + std::string cacheFile = path; + cacheFile += "/CMakeCache.txt"; + // clear the old cache, if we are reading in internal values + if ( internal ) + { + this->Cache.clear(); + } + if(!cmSystemTools::FileExists(cacheFile.c_str())) + { + this->CleanCMakeFiles(path); + return false; + } + + std::ifstream fin(cacheFile.c_str()); + if(!fin) + { + return false; + } + const char *realbuffer; + std::string buffer; + std::string entryKey; + while(fin) + { + // Format is key:type=value + std::string helpString; + CacheEntry e; + e.Properties.SetCMakeInstance(this->CMakeInstance); + cmSystemTools::GetLineFromStream(fin, buffer); + realbuffer = buffer.c_str(); + while(*realbuffer != '0' && + (*realbuffer == ' ' || + *realbuffer == '\t' || + *realbuffer == '\r' || + *realbuffer == '\n')) + { + realbuffer++; + } + // skip blank lines and comment lines + if(realbuffer[0] == '#' || realbuffer[0] == 0) + { + continue; + } + while(realbuffer[0] == '/' && realbuffer[1] == '/') + { + if ((realbuffer[2] == '\\') && (realbuffer[3]=='n')) + { + helpString += "\n"; + helpString += &realbuffer[4]; + } + else + { + helpString += &realbuffer[2]; + } + cmSystemTools::GetLineFromStream(fin, buffer); + realbuffer = buffer.c_str(); + if(!fin) + { + continue; + } + } + e.SetProperty("HELPSTRING", helpString.c_str()); + if(cmCacheManager::ParseEntry(realbuffer, entryKey, e.Value, e.Type)) + { + if ( excludes.find(entryKey) == excludes.end() ) + { + // Load internal values if internal is set. + // If the entry is not internal to the cache being loaded + // or if it is in the list of internal entries to be + // imported, load it. + if ( internal || (e.Type != INTERNAL) || + (includes.find(entryKey) != includes.end()) ) + { + // If we are loading the cache from another project, + // make all loaded entries internal so that it is + // not visible in the gui + if (!internal) + { + e.Type = INTERNAL; + helpString = "DO NOT EDIT, "; + helpString += entryKey; + helpString += " loaded from external file. " + "To change this value edit this file: "; + helpString += path; + helpString += "/CMakeCache.txt" ; + e.SetProperty("HELPSTRING", helpString.c_str()); + } + if(!this->ReadPropertyEntry(entryKey, e)) + { + e.Initialized = true; + this->Cache[entryKey] = e; + } + } + } + } + else + { + cmSystemTools::Error("Parse error in cache file ", cacheFile.c_str(), + ". Offending entry: ", realbuffer); + } + } + this->CacheMajorVersion = 0; + this->CacheMinorVersion = 0; + if(const char* cmajor = this->GetCacheValue("CMAKE_CACHE_MAJOR_VERSION")) + { + unsigned int v=0; + if(sscanf(cmajor, "%u", &v) == 1) + { + this->CacheMajorVersion = v; + } + if(const char* cminor = this->GetCacheValue("CMAKE_CACHE_MINOR_VERSION")) + { + if(sscanf(cminor, "%u", &v) == 1) + { + this->CacheMinorVersion = v; + } + } + } + else + { + // CMake version not found in the list file. + // Set as version 0.0 + this->AddCacheEntry("CMAKE_CACHE_MINOR_VERSION", "0", + "Minor version of cmake used to create the " + "current loaded cache", cmCacheManager::INTERNAL); + this->AddCacheEntry("CMAKE_CACHE_MAJOR_VERSION", "0", + "Major version of cmake used to create the " + "current loaded cache", cmCacheManager::INTERNAL); + + } + // check to make sure the cache directory has not + // been moved + if ( internal && this->GetCacheValue("CMAKE_CACHEFILE_DIR") ) + { + std::string currentcwd = path; + std::string oldcwd = this->GetCacheValue("CMAKE_CACHEFILE_DIR"); + cmSystemTools::ConvertToUnixSlashes(currentcwd); + currentcwd += "/CMakeCache.txt"; + oldcwd += "/CMakeCache.txt"; + if(!cmSystemTools::SameFile(oldcwd.c_str(), currentcwd.c_str())) + { + std::string message = + std::string("The current CMakeCache.txt directory ") + + currentcwd + std::string(" is different than the directory ") + + std::string(this->GetCacheValue("CMAKE_CACHEFILE_DIR")) + + std::string(" where CMakeCache.txt was created. This may result " + "in binaries being created in the wrong place. If you " + "are not sure, reedit the CMakeCache.txt"); + cmSystemTools::Error(message.c_str()); + } + } + return true; +} + +//---------------------------------------------------------------------------- +const char* cmCacheManager::PersistentProperties[] = +{ + "ADVANCED", + "MODIFIED", + "STRINGS", + 0 +}; + +//---------------------------------------------------------------------------- +bool cmCacheManager::ReadPropertyEntry(std::string const& entryKey, + CacheEntry& e) +{ + // All property entries are internal. + if(e.Type != cmCacheManager::INTERNAL) + { + return false; + } + + const char* end = entryKey.c_str() + entryKey.size(); + for(const char** p = this->PersistentProperties; *p; ++p) + { + std::string::size_type plen = strlen(*p) + 1; + if(entryKey.size() > plen && *(end-plen) == '-' && + strcmp(end-plen+1, *p) == 0) + { + std::string key = entryKey.substr(0, entryKey.size() - plen); + cmCacheManager::CacheIterator it = this->GetCacheIterator(key.c_str()); + if(it.IsAtEnd()) + { + // Create an entry and store the property. + CacheEntry& ne = this->Cache[key]; + ne.Properties.SetCMakeInstance(this->CMakeInstance); + ne.Type = cmCacheManager::UNINITIALIZED; + ne.SetProperty(*p, e.Value.c_str()); + } + else + { + // Store this property on its entry. + it.SetProperty(*p, e.Value.c_str()); + } + return true; + } + } + return false; +} + +//---------------------------------------------------------------------------- +void cmCacheManager::WritePropertyEntries(std::ostream& os, + CacheIterator const& i) +{ + for(const char** p = this->PersistentProperties; *p; ++p) + { + if(const char* value = i.GetProperty(*p)) + { + std::string helpstring = *p; + helpstring += " property for variable: "; + helpstring += i.GetName(); + cmCacheManager::OutputHelpString(os, helpstring); + + std::string key = i.GetName(); + key += "-"; + key += *p; + this->OutputKey(os, key); + os << ":INTERNAL="; + this->OutputValue(os, value); + os << "\n"; + } + } +} + +bool cmCacheManager::SaveCache(cmMakefile* mf) +{ + return this->SaveCache(mf->GetHomeOutputDirectory()); +} + + +bool cmCacheManager::SaveCache(const char* path) +{ + std::string cacheFile = path; + cacheFile += "/CMakeCache.txt"; + cmGeneratedFileStream fout(cacheFile.c_str()); + fout.SetCopyIfDifferent(true); + if(!fout) + { + cmSystemTools::Error("Unable to open cache file for save. ", + cacheFile.c_str()); + cmSystemTools::ReportLastSystemError(""); + return false; + } + // before writing the cache, update the version numbers + // to the + char temp[1024]; + sprintf(temp, "%d", cmVersion::GetMinorVersion()); + this->AddCacheEntry("CMAKE_CACHE_MINOR_VERSION", temp, + "Minor version of cmake used to create the " + "current loaded cache", cmCacheManager::INTERNAL); + sprintf(temp, "%d", cmVersion::GetMajorVersion()); + this->AddCacheEntry("CMAKE_CACHE_MAJOR_VERSION", temp, + "Major version of cmake used to create the " + "current loaded cache", cmCacheManager::INTERNAL); + sprintf(temp, "%d", cmVersion::GetPatchVersion()); + this->AddCacheEntry("CMAKE_CACHE_PATCH_VERSION", temp, + "Patch version of cmake used to create the " + "current loaded cache", cmCacheManager::INTERNAL); + + // Let us store the current working directory so that if somebody + // Copies it, he will not be surprised + std::string currentcwd = path; + if ( currentcwd[0] >= 'A' && currentcwd[0] <= 'Z' && + currentcwd[1] == ':' ) + { + // Cast added to avoid compiler warning. Cast is ok because + // value is guaranteed to fit in char by the above if... + currentcwd[0] = static_cast<char>(currentcwd[0] - 'A' + 'a'); + } + cmSystemTools::ConvertToUnixSlashes(currentcwd); + this->AddCacheEntry("CMAKE_CACHEFILE_DIR", currentcwd.c_str(), + "This is the directory where this CMakeCache.txt" + " was created", cmCacheManager::INTERNAL); + + fout << "# This is the CMakeCache file.\n" + << "# For build in directory: " << currentcwd << "\n"; + cmCacheManager::CacheEntry* cmakeCacheEntry + = this->GetCacheEntry("CMAKE_COMMAND"); + if ( cmakeCacheEntry ) + { + fout << "# It was generated by CMake: " << + cmakeCacheEntry->Value << std::endl; + } + + fout << "# You can edit this file to change values found and used by cmake." + << std::endl + << "# If you do not want to change any of the values, simply exit the " + "editor." << std::endl + << "# If you do want to change a value, simply edit, save, and exit " + "the editor." << std::endl + << "# The syntax for the file is as follows:\n" + << "# KEY:TYPE=VALUE\n" + << "# KEY is the name of a variable in the cache.\n" + << "# TYPE is a hint to GUIs for the type of VALUE, DO NOT EDIT " + "TYPE!." << std::endl + << "# VALUE is the current value for the KEY.\n\n"; + + fout << "########################\n"; + fout << "# EXTERNAL cache entries\n"; + fout << "########################\n"; + fout << "\n"; + + for( std::map<cmStdString, CacheEntry>::const_iterator i = + this->Cache.begin(); i != this->Cache.end(); ++i) + { + const CacheEntry& ce = (*i).second; + CacheEntryType t = ce.Type; + if(!ce.Initialized) + { + /* + // This should be added in, but is not for now. + cmSystemTools::Error("Cache entry \"", (*i).first.c_str(), + "\" is uninitialized"); + */ + } + else if(t != INTERNAL) + { + // Format is key:type=value + if(const char* help = ce.GetProperty("HELPSTRING")) + { + cmCacheManager::OutputHelpString(fout, help); + } + else + { + cmCacheManager::OutputHelpString(fout, "Missing description"); + } + this->OutputKey(fout, i->first); + fout << ":" << cmCacheManagerTypes[t] << "="; + this->OutputValue(fout, ce.Value); + fout << "\n\n"; + } + } + + fout << "\n"; + fout << "########################\n"; + fout << "# INTERNAL cache entries\n"; + fout << "########################\n"; + fout << "\n"; + + for( cmCacheManager::CacheIterator i = this->NewIterator(); + !i.IsAtEnd(); i.Next()) + { + if ( !i.Initialized() ) + { + continue; + } + + CacheEntryType t = i.GetType(); + this->WritePropertyEntries(fout, i); + if(t == cmCacheManager::INTERNAL) + { + // Format is key:type=value + if(const char* help = i.GetProperty("HELPSTRING")) + { + this->OutputHelpString(fout, help); + } + this->OutputKey(fout, i.GetName()); + fout << ":" << cmCacheManagerTypes[t] << "="; + this->OutputValue(fout, i.GetValue()); + fout << "\n"; + } + } + fout << "\n"; + fout.Close(); + std::string checkCacheFile = path; + checkCacheFile += cmake::GetCMakeFilesDirectory(); + cmSystemTools::MakeDirectory(checkCacheFile.c_str()); + checkCacheFile += "/cmake.check_cache"; + std::ofstream checkCache(checkCacheFile.c_str()); + if(!checkCache) + { + cmSystemTools::Error("Unable to open check cache file for write. ", + checkCacheFile.c_str()); + return false; + } + checkCache << "# This file is generated by cmake for dependency checking " + "of the CMakeCache.txt file\n"; + return true; +} + +bool cmCacheManager::DeleteCache(const char* path) +{ + std::string cacheFile = path; + cmSystemTools::ConvertToUnixSlashes(cacheFile); + std::string cmakeFiles = cacheFile; + cacheFile += "/CMakeCache.txt"; + if(cmSystemTools::FileExists(cacheFile.c_str())) + { + cmSystemTools::RemoveFile(cacheFile.c_str()); + // now remove the files in the CMakeFiles directory + // this cleans up language cache files + cmakeFiles += cmake::GetCMakeFilesDirectory(); + if(cmSystemTools::FileIsDirectory(cmakeFiles.c_str())) + { + cmSystemTools::RemoveADirectory(cmakeFiles.c_str()); + } + } + return true; +} + +void cmCacheManager::OutputKey(std::ostream& fout, std::string const& key) +{ + // support : in key name by double quoting + const char* q = (key.find(':') != key.npos || + key.find("//") == 0)? "\"" : ""; + fout << q << key << q; +} + +void cmCacheManager::OutputValue(std::ostream& fout, std::string const& value) +{ + // if value has trailing space or tab, enclose it in single quotes + if (value.size() && + (value[value.size() - 1] == ' ' || + value[value.size() - 1] == '\t')) + { + fout << '\'' << value << '\''; + } + else + { + fout << value; + } +} + +void cmCacheManager::OutputHelpString(std::ostream& fout, + const std::string& helpString) +{ + std::string::size_type end = helpString.size(); + if(end == 0) + { + return; + } + std::string oneLine; + std::string::size_type pos = 0; + for (std::string::size_type i=0; i<=end; i++) + { + if ((i==end) + || (helpString[i]=='\n') + || ((i-pos >= 60) && (helpString[i]==' '))) + { + fout << "//"; + if (helpString[pos] == '\n') + { + pos++; + fout << "\\n"; + } + oneLine = helpString.substr(pos, i - pos); + fout << oneLine.c_str() << "\n"; + pos = i; + } + } +} + +void cmCacheManager::RemoveCacheEntry(const char* key) +{ + CacheEntryMap::iterator i = this->Cache.find(key); + if(i != this->Cache.end()) + { + this->Cache.erase(i); + } +} + + +cmCacheManager::CacheEntry *cmCacheManager::GetCacheEntry(const char* key) +{ + CacheEntryMap::iterator i = this->Cache.find(key); + if(i != this->Cache.end()) + { + return &i->second; + } + return 0; +} + +cmCacheManager::CacheIterator cmCacheManager::GetCacheIterator( + const char *key) +{ + return CacheIterator(*this, key); +} + +const char* cmCacheManager::GetCacheValue(const char* key) const +{ + CacheEntryMap::const_iterator i = this->Cache.find(key); + if(i != this->Cache.end() && + i->second.Initialized) + { + return i->second.Value.c_str(); + } + return 0; +} + + +void cmCacheManager::PrintCache(std::ostream& out) const +{ + out << "=================================================" << std::endl; + out << "CMakeCache Contents:" << std::endl; + for(std::map<cmStdString, CacheEntry>::const_iterator i = + this->Cache.begin(); i != this->Cache.end(); ++i) + { + if((*i).second.Type != INTERNAL) + { + out << (*i).first.c_str() << " = " << (*i).second.Value.c_str() + << std::endl; + } + } + out << "\n\n"; + out << "To change values in the CMakeCache, " + << std::endl << "edit CMakeCache.txt in your output directory.\n"; + out << "=================================================" << std::endl; +} + + +void cmCacheManager::AddCacheEntry(const char* key, + const char* value, + const char* helpString, + CacheEntryType type) +{ + CacheEntry& e = this->Cache[key]; + e.Properties.SetCMakeInstance(this->CMakeInstance); + if ( value ) + { + e.Value = value; + e.Initialized = true; + } + else + { + e.Value = ""; + } + e.Type = type; + // make sure we only use unix style paths + if(type == FILEPATH || type == PATH) + { + if(e.Value.find(';') != e.Value.npos) + { + std::vector<std::string> paths; + cmSystemTools::ExpandListArgument(e.Value, paths); + const char* sep = ""; + e.Value = ""; + for(std::vector<std::string>::iterator i = paths.begin(); + i != paths.end(); ++i) + { + cmSystemTools::ConvertToUnixSlashes(*i); + e.Value += sep; + e.Value += *i; + sep = ";"; + } + } + else + { + cmSystemTools::ConvertToUnixSlashes(e.Value); + } + } + e.SetProperty("HELPSTRING", helpString? helpString : + "(This variable does not exist and should not be used)"); + this->Cache[key] = e; +} + +bool cmCacheManager::CacheIterator::IsAtEnd() const +{ + return this->Position == this->Container.Cache.end(); +} + +void cmCacheManager::CacheIterator::Begin() +{ + this->Position = this->Container.Cache.begin(); +} + +bool cmCacheManager::CacheIterator::Find(const char* key) +{ + this->Position = this->Container.Cache.find(key); + return !this->IsAtEnd(); +} + +void cmCacheManager::CacheIterator::Next() +{ + if (!this->IsAtEnd()) + { + ++this->Position; + } +} + +void cmCacheManager::CacheIterator::SetValue(const char* value) +{ + if (this->IsAtEnd()) + { + return; + } + CacheEntry* entry = &this->GetEntry(); + if ( value ) + { + entry->Value = value; + entry->Initialized = true; + } + else + { + entry->Value = ""; + } +} + +//---------------------------------------------------------------------------- +bool cmCacheManager::CacheIterator::GetValueAsBool() const +{ + return cmSystemTools::IsOn(this->GetEntry().Value.c_str()); +} + +//---------------------------------------------------------------------------- +const char* +cmCacheManager::CacheEntry::GetProperty(const char* prop) const +{ + if(strcmp(prop, "TYPE") == 0) + { + return cmCacheManagerTypes[this->Type]; + } + else if(strcmp(prop, "VALUE") == 0) + { + return this->Value.c_str(); + } + bool c = false; + return + this->Properties.GetPropertyValue(prop, cmProperty::CACHE, c); +} + +//---------------------------------------------------------------------------- +void cmCacheManager::CacheEntry::SetProperty(const char* prop, + const char* value) +{ + if(strcmp(prop, "TYPE") == 0) + { + this->Type = cmCacheManager::StringToType(value? value : "STRING"); + } + else if(strcmp(prop, "VALUE") == 0) + { + this->Value = value? value : ""; + } + else + { + this->Properties.SetProperty(prop, value, cmProperty::CACHE); + } +} + +//---------------------------------------------------------------------------- +void cmCacheManager::CacheEntry::AppendProperty(const char* prop, + const char* value, + bool asString) +{ + if(strcmp(prop, "TYPE") == 0) + { + this->Type = cmCacheManager::StringToType(value? value : "STRING"); + } + else if(strcmp(prop, "VALUE") == 0) + { + if(value) + { + if(!this->Value.empty() && *value && !asString) + { + this->Value += ";"; + } + this->Value += value; + } + } + else + { + this->Properties.AppendProperty(prop, value, cmProperty::CACHE, asString); + } +} + +//---------------------------------------------------------------------------- +const char* cmCacheManager::CacheIterator::GetProperty(const char* prop) const +{ + if(!this->IsAtEnd()) + { + return this->GetEntry().GetProperty(prop); + } + return 0; +} + +//---------------------------------------------------------------------------- +void cmCacheManager::CacheIterator::SetProperty(const char* p, const char* v) +{ + if(!this->IsAtEnd()) + { + this->GetEntry().SetProperty(p, v); + } +} + +//---------------------------------------------------------------------------- +void cmCacheManager::CacheIterator::AppendProperty(const char* p, + const char* v, + bool asString) +{ + if(!this->IsAtEnd()) + { + this->GetEntry().AppendProperty(p, v, asString); + } +} + +//---------------------------------------------------------------------------- +bool cmCacheManager::CacheIterator::GetPropertyAsBool(const char* prop) const +{ + if(const char* value = this->GetProperty(prop)) + { + return cmSystemTools::IsOn(value); + } + return false; +} + +//---------------------------------------------------------------------------- +void cmCacheManager::CacheIterator::SetProperty(const char* p, bool v) +{ + this->SetProperty(p, v ? "ON" : "OFF"); +} + +//---------------------------------------------------------------------------- +bool cmCacheManager::CacheIterator::PropertyExists(const char* prop) const +{ + return this->GetProperty(prop)? true:false; +} + +//---------------------------------------------------------------------------- +bool cmCacheManager::NeedCacheCompatibility(int major, int minor) +{ + // Compatibility is not needed if the cache version is zero because + // the cache was created or modified by the user. + if(this->CacheMajorVersion == 0) + { + return false; + } + + // Compatibility is needed if the cache version is equal to or lower + // than the given version. + unsigned int actual_compat = + CMake_VERSION_ENCODE(this->CacheMajorVersion, this->CacheMinorVersion, 0); + return (actual_compat && + actual_compat <= CMake_VERSION_ENCODE(major, minor, 0)); +} + +//---------------------------------------------------------------------------- +void cmCacheManager::DefineProperties(cmake *cm) +{ + cm->DefineProperty + ("ADVANCED", cmProperty::CACHE, + "True if entry should be hidden by default in GUIs.", + "This is a boolean value indicating whether the entry is considered " + "interesting only for advanced configuration. " + "The mark_as_advanced() command modifies this property." + ); + + cm->DefineProperty + ("HELPSTRING", cmProperty::CACHE, + "Help associated with entry in GUIs.", + "This string summarizes the purpose of an entry to help users set it " + "through a CMake GUI." + ); + + cm->DefineProperty + ("TYPE", cmProperty::CACHE, + "Widget type for entry in GUIs.", + "Cache entry values are always strings, but CMake GUIs present widgets " + "to help users set values. " + "The GUIs use this property as a hint to determine the widget type. " + "Valid TYPE values are:\n" + " BOOL = Boolean ON/OFF value.\n" + " PATH = Path to a directory.\n" + " FILEPATH = Path to a file.\n" + " STRING = Generic string value.\n" + " INTERNAL = Do not present in GUI at all.\n" + " STATIC = Value managed by CMake, do not change.\n" + " UNINITIALIZED = Type not yet specified.\n" + "Generally the TYPE of a cache entry should be set by the command " + "which creates it (set, option, find_library, etc.)." + ); + + cm->DefineProperty + ("MODIFIED", cmProperty::CACHE, + "Internal management property. Do not set or get.", + "This is an internal cache entry property managed by CMake to " + "track interactive user modification of entries. Ignore it." + ); + + cm->DefineProperty + ("STRINGS", cmProperty::CACHE, + "Enumerate possible STRING entry values for GUI selection.", + "For cache entries with type STRING, this enumerates a set of values. " + "CMake GUIs may use this to provide a selection widget instead of a " + "generic string entry field. " + "This is for convenience only. " + "CMake does not enforce that the value matches one of those listed." + ); + + cm->DefineProperty + ("VALUE", cmProperty::CACHE, + "Value of a cache entry.", + "This property maps to the actual value of a cache entry. " + "Setting this property always sets the value without checking, so " + "use with care." + ); +} |