1 /*=========================================================================
3 Program: Insight Segmentation & Registration Toolkit
4 Module: $RCSfile: cmCacheManager.cxx,v $
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"
25 #if defined(_WIN32) || defined(__CYGWIN__)
29 const char* cmCacheManagerTypes
[] =
39 cmCacheManager::CacheEntryType
cmCacheManager::StringToType(const char* s
)
42 while(cmCacheManagerTypes
[i
])
44 if(strcmp(s
, cmCacheManagerTypes
[i
]) == 0)
46 return static_cast<CacheEntryType
>(i
);
54 struct CleanUpCacheManager
56 ~CleanUpCacheManager()
58 delete cmCacheManager::GetInstance();
63 CleanUpCacheManager cleanup
;
65 cmCacheManager
* cmCacheManager::s_Instance
= 0;
67 cmCacheManager
* cmCacheManager::GetInstance()
69 if(!cmCacheManager::s_Instance
)
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
,
93 std::set
<std::string
> emptySet
;
94 return this->LoadCache(path
, internal
, emptySet
, emptySet
);
97 bool cmCacheManager::ParseEntry(const char* entry
,
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 ]*$");
107 if(regQuoted
.find(entry
))
109 var
= regQuoted
.match(1);
110 type
= cmCacheManager::StringToType(regQuoted
.match(2).c_str());
111 value
= regQuoted
.match(3);
114 else if (reg
.find(entry
))
117 type
= cmCacheManager::StringToType(reg
.match(2).c_str());
118 value
= reg
.match(3);
122 // if value is enclosed in single quotes ('foo') then remove them
123 // it is used to enclose trailing space or tab
127 value
[value
.size() - 1] == '\'')
129 value
= value
.substr(1,
136 bool cmCacheManager::LoadCache(const char* path
,
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
148 std::ifstream
fin(cacheFile
.c_str());
153 const int bsize
= 4096;
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
;
164 // Format is key:type=value
166 fin
.getline(buffer
, bsize
);
168 while(*realbuffer
!= '0' &&
169 (*realbuffer
== ' ' ||
170 *realbuffer
== '\t' ||
171 *realbuffer
== '\n'))
175 // skip blank lines and comment lines
176 if(realbuffer
[0] == '#' || realbuffer
[0] == 0)
180 while(realbuffer
[0] == '/' && realbuffer
[1] == '/')
182 e
.m_HelpString
+= &realbuffer
[2];
183 fin
.getline(realbuffer
, bsize
);
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
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
;
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
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());
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
;
271 std::ofstream
fout(tempFile
.c_str());
274 cmSystemTools::Error("Unable to open cache file for save. ",
278 // before writting the cache, update the version numbers
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";
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
;
326 // Format is key:type=value
327 cmCacheManager::OutputHelpString(fout
, ce
.m_HelpString
);
329 // support : in key name by double quoting
330 if((*i
).first
.find(':') != std::string::npos
||
331 (*i
).first
.find("//") == 0)
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
<< '\'';
359 fout
<< "########################\n";
360 fout
<< "# INTERNAL cache entries\n";
361 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
;
371 // Format is key:type=value
372 cmCacheManager::OutputHelpString(fout
, ce
.m_HelpString
);
374 // support : in key name by double quoting
375 if((*i
).first
.find(':') != std::string::npos
||
376 (*i
).first
.find("//") == 0)
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
<< '\'';
404 cmSystemTools::CopyFileIfDifferent(tempFile
.c_str(),
406 cmSystemTools::RemoveFile(tempFile
.c_str());
410 void cmCacheManager::OutputHelpString(std::ofstream
& fout
,
411 const std::string
& helpString
)
413 std::string::size_type end
= helpString
.size();
419 std::string::size_type pos
= 0;
420 std::string::size_type nextBreak
= 60;
432 while(nextBreak
< end
&& helpString
[nextBreak
] != ' ')
437 oneLine
= helpString
.substr(pos
, nextBreak
- pos
);
438 fout
<< "//" << oneLine
.c_str() << "\n";
444 void cmCacheManager::RemoveCacheEntry(const char* key
)
446 CacheEntryMap::iterator i
= m_Cache
.find(key
);
447 if(i
!= m_Cache
.end())
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())
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();
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
;
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
,
499 const char* helpString
,
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
;
514 void cmCacheManager::AddCacheEntry(const char* key
, bool v
,
515 const char* helpString
)
519 this->AddCacheEntry(key
, "ON", helpString
, cmCacheManager::BOOL
);
523 this->AddCacheEntry(key
, "OFF", helpString
, cmCacheManager::BOOL
);
527 bool cmCacheManager::IsAdvanced(const char* key
)
529 std::string advancedVar
= key
;
530 advancedVar
+= "-ADVANCED";
532 cmCacheManager::GetInstance()->GetCacheValue(advancedVar
.c_str());
535 return cmSystemTools::IsOn(value
);