FIX: stupid pb fixed (close to being medieval'ed by The Ken)
[cmake.git] / Source / cmCacheManager.cxx
blob0bdf3cbab4aa5b9e35fa3784820cf05fb8ad3f5f
1 /*=========================================================================
3 Program: Insight Segmentation & Registration Toolkit
4 Module: $RCSfile: cmCacheManager.cxx,v $
5 Language: C++
6 Date: $Date: 2002-04-30 18:00:14 $
7 Version: $Revision: 1.51 $
9 Copyright (c) 2002 Insight Consortium. All rights reserved.
10 See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm 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 "cmRegularExpression.h"
23 #include "stdio.h"
25 #if defined(_WIN32) || defined(__CYGWIN__)
26 # include <windows.h>
27 #endif // _WIN32
29 const char* cmCacheManagerTypes[] =
30 { "BOOL",
31 "PATH",
32 "FILEPATH",
33 "STRING",
34 "INTERNAL",
35 "STATIC",
39 cmCacheManager::CacheEntryType cmCacheManager::StringToType(const char* s)
41 int i = 0;
42 while(cmCacheManagerTypes[i])
44 if(strcmp(s, cmCacheManagerTypes[i]) == 0)
46 return static_cast<CacheEntryType>(i);
48 ++i;
50 return STRING;
54 struct CleanUpCacheManager
56 ~CleanUpCacheManager()
58 delete cmCacheManager::GetInstance();
60 void Use() {}
63 CleanUpCacheManager cleanup;
65 cmCacheManager* cmCacheManager::s_Instance = 0;
67 cmCacheManager* cmCacheManager::GetInstance()
69 if(!cmCacheManager::s_Instance)
71 cleanup.Use();
72 cmCacheManager::s_Instance = new cmCacheManager;
74 return cmCacheManager::s_Instance;
79 bool cmCacheManager::LoadCache(cmMakefile* mf)
81 return this->LoadCache(mf->GetHomeOutputDirectory());
85 bool cmCacheManager::LoadCache(const char* path)
87 return this->LoadCache(path,true);
90 bool cmCacheManager::LoadCache(const char* path,
91 bool internal)
93 std::set<std::string> emptySet;
94 return this->LoadCache(path, internal, emptySet, emptySet);
97 bool cmCacheManager::ParseEntry(const char* entry,
98 std::string& var,
99 std::string& value,
100 CacheEntryType& type)
102 // input line is: key:type=value
103 cmRegularExpression reg("^([^:]*):([^=]*)=(.*[^\t ]|[\t ]*)[\t ]*$");
104 // input line is: "key":type=value
105 cmRegularExpression regQuoted("^\"([^\"]*)\":([^=]*)=(.*[^\t ]|[\t ]*)[\t ]*$");
106 bool flag = false;
107 if(regQuoted.find(entry))
109 var = regQuoted.match(1);
110 type = cmCacheManager::StringToType(regQuoted.match(2).c_str());
111 value = regQuoted.match(3);
112 flag = true;
114 else if (reg.find(entry))
116 var = reg.match(1);
117 type = cmCacheManager::StringToType(reg.match(2).c_str());
118 value = reg.match(3);
119 flag = true;
122 // if value is enclosed in single quotes ('foo') then remove them
123 // it is used to enclose trailing space or tab
124 if (flag &&
125 value.size() >= 2 &&
126 value[0] == '\'' &&
127 value[value.size() - 1] == '\'')
129 value = value.substr(1,
130 value.size() - 2);
133 return flag;
136 bool cmCacheManager::LoadCache(const char* path,
137 bool internal,
138 std::set<std::string>& excludes,
139 std::set<std::string>& includes)
141 std::string cacheFile = path;
142 cacheFile += "/CMakeCache.txt";
143 // clear the old cache, if we are reading in internal values
144 if ( internal )
146 m_Cache.clear();
148 std::ifstream fin(cacheFile.c_str());
149 if(!fin)
151 return false;
153 const int bsize = 4096;
154 char buffer[bsize];
155 char *realbuffer;
156 // input line is: key:type=value
157 cmRegularExpression reg("^([^:]*):([^=]*)=(.*[^\t ]|[\t ]*)[\t ]*$");
158 // input line is: "key":type=value
159 cmRegularExpression regQuoted("^\"([^\"]*)\":([^=]*)=(.*[^\t ]|[\t ]*)[\t ]*$");
161 std::string entryKey;
162 while(fin)
164 // Format is key:type=value
165 CacheEntry e;
166 fin.getline(buffer, bsize);
167 realbuffer = buffer;
168 while(*realbuffer != '0' &&
169 (*realbuffer == ' ' ||
170 *realbuffer == '\t' ||
171 *realbuffer == '\n'))
173 realbuffer++;
175 // skip blank lines and comment lines
176 if(realbuffer[0] == '#' || realbuffer[0] == 0)
178 continue;
180 while(realbuffer[0] == '/' && realbuffer[1] == '/')
182 e.m_HelpString += &realbuffer[2];
183 fin.getline(realbuffer, bsize);
184 if(!fin)
186 continue;
189 if(cmCacheManager::ParseEntry(realbuffer, entryKey, e.m_Value, e.m_Type))
191 if ( excludes.find(entryKey) == excludes.end() )
193 // Load internal values if internal is set.
194 // If the entry is not internal to the cache being loaded
195 // or if it is in the list of internal entries to be
196 // imported, load it.
197 if ( internal || (e.m_Type != INTERNAL) ||
198 (includes.find(entryKey) != includes.end()) )
200 // If we are loading the cache from another project,
201 // make all loaded entries internal so that it is
202 // not visible in the gui
203 if (!internal)
205 e.m_Type = INTERNAL;
206 e.m_HelpString = "DO NOT EDIT, ";
207 e.m_HelpString += entryKey;
208 e.m_HelpString += " loaded from external file. "
209 "To change this value edit this file: ";
210 e.m_HelpString += path;
211 e.m_HelpString += "/CMakeCache.txt" ;
213 m_Cache[entryKey] = e;
217 else
219 cmSystemTools::Error("Parse error in cache file ", cacheFile.c_str(),
220 ". Offending entry: ", realbuffer);
223 // if CMAKE version not found in the list file
224 // add them as version 0.0
225 if(!this->GetCacheValue("CMAKE_CACHE_MINOR_VERSION"))
227 this->AddCacheEntry("CMAKE_CACHE_MINOR_VERSION", "0",
228 "Minor version of cmake used to create the "
229 "current loaded cache", cmCacheManager::INTERNAL);
230 this->AddCacheEntry("CMAKE_CACHE_MAJOR_VERSION", "0",
231 "Major version of cmake used to create the "
232 "current loaded cache", cmCacheManager::INTERNAL);
235 // check to make sure the cache directory has not
236 // been moved
237 if ( internal && this->GetCacheValue("CMAKE_CACHEFILE_DIR") )
239 std::string currentcwd = path;
240 std::string oldcwd = this->GetCacheValue("CMAKE_CACHEFILE_DIR");
241 cmSystemTools::ConvertToUnixSlashes(currentcwd);
242 currentcwd += "/CMakeCache.txt";
243 oldcwd += "/CMakeCache.txt";
244 if(!cmSystemTools::SameFile(oldcwd.c_str(), currentcwd.c_str()))
246 std::string message =
247 std::string("The current CMakeCache.txt directory ") +
248 currentcwd + std::string(" is different than the directory ") +
249 std::string(this->GetCacheValue("CMAKE_CACHEFILE_DIR")) +
250 std::string(" where CMackeCache.txt was created. This may result "
251 "in binaries being created in the wrong place. If you "
252 "are not sure, reedit the CMakeCache.txt");
253 cmSystemTools::Error(message.c_str());
256 return true;
259 bool cmCacheManager::SaveCache(cmMakefile* mf)
261 return this->SaveCache(mf->GetHomeOutputDirectory());
265 bool cmCacheManager::SaveCache(const char* path)
267 std::string cacheFile = path;
268 cacheFile += "/CMakeCache.txt";
269 std::string tempFile = cacheFile;
270 tempFile += ".tmp";
271 std::ofstream fout(tempFile.c_str());
272 if(!fout)
274 cmSystemTools::Error("Unable to open cache file for save. ",
275 cacheFile.c_str());
276 return false;
278 // before writting the cache, update the version numbers
279 // to the
280 char temp[1024];
281 sprintf(temp, "%d", cmMakefile::GetMinorVersion());
282 this->AddCacheEntry("CMAKE_CACHE_MINOR_VERSION", temp,
283 "Minor version of cmake used to create the "
284 "current loaded cache", cmCacheManager::INTERNAL);
285 sprintf(temp, "%d", cmMakefile::GetMajorVersion());
286 this->AddCacheEntry("CMAKE_CACHE_MAJOR_VERSION", temp,
287 "Major version of cmake used to create the "
288 "current loaded cache", cmCacheManager::INTERNAL);
290 // Let us store the current working directory so that if somebody
291 // Copies it, he will not be surprised
292 std::string currentcwd = path;
293 if ( currentcwd[0] >= 'A' && currentcwd[0] <= 'Z' &&
294 currentcwd[1] == ':' )
296 currentcwd[0] = currentcwd[0] - 'A' + 'a';
298 cmSystemTools::ConvertToUnixSlashes(currentcwd);
299 this->AddCacheEntry("CMAKE_CACHEFILE_DIR", currentcwd.c_str(),
300 "This is the directory where this CMakeCahe.txt"
301 " was created", cmCacheManager::INTERNAL);
303 fout << "# This is the CMakeCache file.\n"
304 << "# For build in directory: " << currentcwd << "\n"
305 << "# You can edit this file to change values found and used by cmake.\n"
306 << "# If you do not want to change any of the values, simply exit the editor.\n"
307 << "# If you do want to change a value, simply edit, save, and exit the editor.\n"
308 << "# The syntax for the file is as follows:\n"
309 << "# KEY:TYPE=VALUE\n"
310 << "# KEY is the name of a varible in the cache.\n"
311 << "# TYPE is a hint to GUI's for the type of VALUE, DO NOT EDIT TYPE!.\n"
312 << "# VALUE is the current value for the KEY.\n\n";
314 fout << "########################\n";
315 fout << "# EXTERNAL cache entries\n";
316 fout << "########################\n";
317 fout << "\n";
319 for( std::map<cmStdString, CacheEntry>::const_iterator i = m_Cache.begin();
320 i != m_Cache.end(); ++i)
322 const CacheEntry& ce = (*i).second;
323 CacheEntryType t = ce.m_Type;
324 if(t != INTERNAL)
326 // Format is key:type=value
327 cmCacheManager::OutputHelpString(fout, ce.m_HelpString);
328 std::string key;
329 // support : in key name by double quoting
330 if((*i).first.find(':') != std::string::npos ||
331 (*i).first.find("//") == 0)
333 key = "\"";
334 key += i->first;
335 key += "\"";
337 else
339 key = i->first;
341 fout << key.c_str() << ":"
342 << cmCacheManagerTypes[t] << "=";
343 // if value has trailing space or tab, enclose it in single quotes
344 if (ce.m_Value.size() &&
345 (ce.m_Value[ce.m_Value.size() - 1] == ' ' ||
346 ce.m_Value[ce.m_Value.size() - 1] == '\t'))
348 fout << '\'' << ce.m_Value << '\'';
350 else
352 fout << ce.m_Value;
354 fout << "\n\n";
358 fout << "\n";
359 fout << "########################\n";
360 fout << "# INTERNAL cache entries\n";
361 fout << "########################\n";
362 fout << "\n";
364 for( std::map<cmStdString, CacheEntry>::const_iterator i = m_Cache.begin();
365 i != m_Cache.end(); ++i)
367 const CacheEntry& ce = (*i).second;
368 CacheEntryType t = ce.m_Type;
369 if(t == INTERNAL)
371 // Format is key:type=value
372 cmCacheManager::OutputHelpString(fout, ce.m_HelpString);
373 std::string key;
374 // support : in key name by double quoting
375 if((*i).first.find(':') != std::string::npos ||
376 (*i).first.find("//") == 0)
378 key = "\"";
379 key += i->first;
380 key += "\"";
382 else
384 key = i->first;
386 fout << key.c_str() << ":"
387 << cmCacheManagerTypes[t] << "=";
388 // if value has trailing space or tab, enclose it in single quotes
389 if (ce.m_Value.size() &&
390 (ce.m_Value[ce.m_Value.size() - 1] == ' ' ||
391 ce.m_Value[ce.m_Value.size() - 1] == '\t'))
393 fout << '\'' << ce.m_Value << '\'';
395 else
397 fout << ce.m_Value;
399 fout << "\n";
402 fout << "\n";
403 fout.close();
404 cmSystemTools::CopyFileIfDifferent(tempFile.c_str(),
405 cacheFile.c_str());
406 cmSystemTools::RemoveFile(tempFile.c_str());
407 return true;
410 void cmCacheManager::OutputHelpString(std::ofstream& fout,
411 const std::string& helpString)
413 std::string::size_type end = helpString.size();
414 if(end == 0)
416 return;
418 std::string oneLine;
419 std::string::size_type pos = 0;
420 std::string::size_type nextBreak = 60;
421 bool done = false;
423 while(!done)
425 if(nextBreak >= end)
427 nextBreak = end;
428 done = true;
430 else
432 while(nextBreak < end && helpString[nextBreak] != ' ')
434 nextBreak++;
437 oneLine = helpString.substr(pos, nextBreak - pos);
438 fout << "//" << oneLine.c_str() << "\n";
439 pos = nextBreak;
440 nextBreak += 60;
444 void cmCacheManager::RemoveCacheEntry(const char* key)
446 CacheEntryMap::iterator i = m_Cache.find(key);
447 if(i != m_Cache.end())
449 m_Cache.erase(i);
451 else
453 std::cerr << "Failed to remove entry:" << key << std::endl;
458 cmCacheManager::CacheEntry *cmCacheManager::GetCacheEntry(const char* key)
460 CacheEntryMap::iterator i = m_Cache.find(key);
461 if(i != m_Cache.end())
463 return &i->second;
465 return 0;
468 const char* cmCacheManager::GetCacheValue(const char* key) const
470 CacheEntryMap::const_iterator i = m_Cache.find(key);
471 if(i != m_Cache.end())
473 return i->second.m_Value.c_str();
475 return 0;
479 void cmCacheManager::PrintCache(std::ostream& out) const
481 out << "=================================================" << std::endl;
482 out << "CMakeCache Contents:" << std::endl;
483 for(std::map<cmStdString, CacheEntry>::const_iterator i = m_Cache.begin();
484 i != m_Cache.end(); ++i)
486 if((*i).second.m_Type != INTERNAL)
488 out << (*i).first.c_str() << " = " << (*i).second.m_Value.c_str() << std::endl;
491 out << "\n\n";
492 out << "To change values in the CMakeCache, \nedit CMakeCache.txt in your output directory.\n";
493 out << "=================================================" << std::endl;
497 void cmCacheManager::AddCacheEntry(const char* key,
498 const char* value,
499 const char* helpString,
500 CacheEntryType type)
502 CacheEntry e;
503 e.m_Value = value;
504 e.m_Type = type;
505 // make sure we only use unix style paths
506 if(type == FILEPATH || type == PATH)
508 cmSystemTools::ConvertToUnixSlashes(e.m_Value);
510 e.m_HelpString = helpString;
511 m_Cache[key] = e;
514 void cmCacheManager::AddCacheEntry(const char* key, bool v,
515 const char* helpString)
517 if(v)
519 this->AddCacheEntry(key, "ON", helpString, cmCacheManager::BOOL);
521 else
523 this->AddCacheEntry(key, "OFF", helpString, cmCacheManager::BOOL);
527 bool cmCacheManager::IsAdvanced(const char* key)
529 std::string advancedVar = key;
530 advancedVar += "-ADVANCED";
531 const char* value =
532 cmCacheManager::GetInstance()->GetCacheValue(advancedVar.c_str());
533 if(value)
535 return cmSystemTools::IsOn(value);
537 return false;