/src/CMake/Source/cmCacheManager.cxx
Line | Count | Source |
1 | | /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying |
2 | | file LICENSE.rst or https://cmake.org/licensing for details. */ |
3 | | #include "cmCacheManager.h" |
4 | | |
5 | | #include <algorithm> |
6 | | #include <cstdio> |
7 | | #include <cstring> |
8 | | #include <sstream> |
9 | | #include <string> |
10 | | |
11 | | #include "cmsys/FStream.hxx" |
12 | | #include "cmsys/Glob.hxx" |
13 | | |
14 | | #include "cmGeneratedFileStream.h" |
15 | | #include "cmList.h" |
16 | | #include "cmMessageType.h" |
17 | | #include "cmMessenger.h" |
18 | | #include "cmState.h" |
19 | | #include "cmStringAlgorithms.h" |
20 | | #include "cmSystemTools.h" |
21 | | #include "cmVersion.h" |
22 | | |
23 | | void cmCacheManager::CleanCMakeFiles(std::string const& path) |
24 | 0 | { |
25 | 0 | std::string glob = cmStrCat(path, "/CMakeFiles/*.cmake"); |
26 | 0 | cmsys::Glob globIt; |
27 | 0 | globIt.FindFiles(glob); |
28 | 0 | std::vector<std::string> files = globIt.GetFiles(); |
29 | 0 | std::for_each(files.begin(), files.end(), cmSystemTools::RemoveFile); |
30 | 0 | } |
31 | | |
32 | | bool cmCacheManager::LoadCache(std::string const& path, bool internal, |
33 | | std::set<std::string>& excludes, |
34 | | std::set<std::string>& includes) |
35 | 0 | { |
36 | 0 | std::string cacheFile = cmStrCat(path, "/CMakeCache.txt"); |
37 | | // clear the old cache, if we are reading in internal values |
38 | 0 | if (internal) { |
39 | 0 | this->Cache.clear(); |
40 | 0 | } |
41 | 0 | if (!cmSystemTools::FileExists(cacheFile)) { |
42 | 0 | this->CleanCMakeFiles(path); |
43 | 0 | return false; |
44 | 0 | } |
45 | | |
46 | 0 | cmsys::ifstream fin(cacheFile.c_str()); |
47 | 0 | if (!fin) { |
48 | 0 | return false; |
49 | 0 | } |
50 | 0 | char const* realbuffer; |
51 | 0 | std::string buffer; |
52 | 0 | std::string entryKey; |
53 | 0 | unsigned int lineno = 0; |
54 | 0 | while (fin) { |
55 | | // Format is key:type=value |
56 | 0 | std::string helpString; |
57 | 0 | CacheEntry e; |
58 | 0 | cmSystemTools::GetLineFromStream(fin, buffer); |
59 | 0 | lineno++; |
60 | 0 | realbuffer = buffer.c_str(); |
61 | 0 | while (*realbuffer == ' ' || *realbuffer == '\t' || *realbuffer == '\r' || |
62 | 0 | *realbuffer == '\n') { |
63 | 0 | if (*realbuffer == '\n') { |
64 | 0 | lineno++; |
65 | 0 | } |
66 | 0 | realbuffer++; |
67 | 0 | } |
68 | | // skip blank lines and comment lines |
69 | 0 | if (realbuffer[0] == '#' || realbuffer[0] == 0) { |
70 | 0 | continue; |
71 | 0 | } |
72 | 0 | while (realbuffer[0] == '/' && realbuffer[1] == '/') { |
73 | 0 | if ((realbuffer[2] == '\\') && (realbuffer[3] == 'n')) { |
74 | 0 | helpString = cmStrCat(std::move(helpString), '\n', &realbuffer[4]); |
75 | 0 | } else { |
76 | 0 | helpString = cmStrCat(std::move(helpString), &realbuffer[2]); |
77 | 0 | } |
78 | 0 | cmSystemTools::GetLineFromStream(fin, buffer); |
79 | 0 | lineno++; |
80 | 0 | realbuffer = buffer.c_str(); |
81 | 0 | if (!fin) { |
82 | 0 | continue; |
83 | 0 | } |
84 | 0 | } |
85 | 0 | e.SetProperty("HELPSTRING", helpString); |
86 | 0 | if (cmState::ParseCacheEntry(realbuffer, entryKey, e.Value, e.Type)) { |
87 | 0 | if (excludes.find(entryKey) == excludes.end()) { |
88 | | // Load internal values if internal is set. |
89 | | // If the entry is not internal to the cache being loaded |
90 | | // or if it is in the list of internal entries to be |
91 | | // imported, load it. |
92 | 0 | if (internal || (e.Type != cmStateEnums::INTERNAL) || |
93 | 0 | (includes.find(entryKey) != includes.end())) { |
94 | | // If we are loading the cache from another project, |
95 | | // make all loaded entries internal so that it is |
96 | | // not visible in the gui |
97 | 0 | if (!internal) { |
98 | 0 | e.Type = cmStateEnums::INTERNAL; |
99 | 0 | helpString = cmStrCat("DO NOT EDIT, ", entryKey, |
100 | 0 | " loaded from external file. " |
101 | 0 | "To change this value edit this file: ", |
102 | 0 | path, "/CMakeCache.txt"); |
103 | 0 | e.SetProperty("HELPSTRING", helpString); |
104 | 0 | } |
105 | 0 | if (!this->ReadPropertyEntry(entryKey, e)) { |
106 | 0 | e.Initialized = true; |
107 | 0 | this->Cache[entryKey] = e; |
108 | 0 | } |
109 | 0 | } |
110 | 0 | } |
111 | 0 | } else { |
112 | 0 | std::ostringstream error; |
113 | 0 | error << "Parse error in cache file " << cacheFile << " on line " |
114 | 0 | << lineno << ". Offending entry: " << realbuffer; |
115 | 0 | cmSystemTools::Error(error.str()); |
116 | 0 | } |
117 | 0 | } |
118 | 0 | this->CacheMajorVersion = 0; |
119 | 0 | this->CacheMinorVersion = 0; |
120 | 0 | if (cmValue cmajor = |
121 | 0 | this->GetInitializedCacheValue("CMAKE_CACHE_MAJOR_VERSION")) { |
122 | 0 | unsigned int v = 0; |
123 | 0 | if (sscanf(cmajor->c_str(), "%u", &v) == 1) { |
124 | 0 | this->CacheMajorVersion = v; |
125 | 0 | } |
126 | 0 | if (cmValue cminor = |
127 | 0 | this->GetInitializedCacheValue("CMAKE_CACHE_MINOR_VERSION")) { |
128 | 0 | if (sscanf(cminor->c_str(), "%u", &v) == 1) { |
129 | 0 | this->CacheMinorVersion = v; |
130 | 0 | } |
131 | 0 | } |
132 | 0 | } else { |
133 | | // CMake version not found in the list file. |
134 | | // Set as version 0.0 |
135 | 0 | this->AddCacheEntry("CMAKE_CACHE_MINOR_VERSION", "0", |
136 | 0 | "Minor version of cmake used to create the " |
137 | 0 | "current loaded cache", |
138 | 0 | cmStateEnums::INTERNAL); |
139 | 0 | this->AddCacheEntry("CMAKE_CACHE_MAJOR_VERSION", "0", |
140 | 0 | "Major version of cmake used to create the " |
141 | 0 | "current loaded cache", |
142 | 0 | cmStateEnums::INTERNAL); |
143 | 0 | } |
144 | | // check to make sure the cache directory has not |
145 | | // been moved |
146 | 0 | cmValue oldDir = this->GetInitializedCacheValue("CMAKE_CACHEFILE_DIR"); |
147 | 0 | if (internal && oldDir) { |
148 | 0 | std::string currentcwd = path; |
149 | 0 | std::string oldcwd = *oldDir; |
150 | 0 | cmSystemTools::ConvertToUnixSlashes(currentcwd); |
151 | 0 | currentcwd = cmStrCat(std::move(currentcwd), "/CMakeCache.txt"); |
152 | 0 | oldcwd = cmStrCat(std::move(oldcwd), "/CMakeCache.txt"); |
153 | 0 | if (!cmSystemTools::SameFile(oldcwd, currentcwd)) { |
154 | 0 | cmValue dir = this->GetInitializedCacheValue("CMAKE_CACHEFILE_DIR"); |
155 | 0 | std::string message = |
156 | 0 | cmStrCat("The current CMakeCache.txt directory ", currentcwd, |
157 | 0 | " is different than the directory ", (dir ? *dir : ""), |
158 | 0 | " where CMakeCache.txt was created. This may result " |
159 | 0 | "in binaries being created in the wrong place. If you " |
160 | 0 | "are not sure, reedit the CMakeCache.txt"); |
161 | 0 | cmSystemTools::Error(message); |
162 | 0 | } |
163 | 0 | } |
164 | 0 | this->CacheLoaded = true; |
165 | 0 | return true; |
166 | 0 | } |
167 | | |
168 | | char const* cmCacheManager::PersistentProperties[] = { "ADVANCED", "MODIFIED", |
169 | | "STRINGS" }; |
170 | | |
171 | | bool cmCacheManager::ReadPropertyEntry(std::string const& entryKey, |
172 | | CacheEntry const& e) |
173 | 0 | { |
174 | | // All property entries are internal. |
175 | 0 | if (e.Type != cmStateEnums::INTERNAL) { |
176 | 0 | return false; |
177 | 0 | } |
178 | | |
179 | 0 | char const* end = entryKey.c_str() + entryKey.size(); |
180 | 0 | for (char const* p : cmCacheManager::PersistentProperties) { |
181 | 0 | std::string::size_type plen = strlen(p) + 1; |
182 | 0 | if (entryKey.size() > plen && *(end - plen) == '-' && |
183 | 0 | strcmp(end - plen + 1, p) == 0) { |
184 | 0 | std::string key = entryKey.substr(0, entryKey.size() - plen); |
185 | 0 | if (auto* entry = this->GetCacheEntry(key)) { |
186 | | // Store this property on its entry. |
187 | 0 | entry->SetProperty(p, e.Value); |
188 | 0 | } else { |
189 | | // Create an entry and store the property. |
190 | 0 | CacheEntry& ne = this->Cache[key]; |
191 | 0 | ne.SetProperty(p, e.Value); |
192 | 0 | } |
193 | 0 | return true; |
194 | 0 | } |
195 | 0 | } |
196 | 0 | return false; |
197 | 0 | } |
198 | | |
199 | | void cmCacheManager::WritePropertyEntries(std::ostream& os, |
200 | | std::string const& entryKey, |
201 | | CacheEntry const& e, |
202 | | cmMessenger* messenger) const |
203 | 0 | { |
204 | 0 | for (char const* p : cmCacheManager::PersistentProperties) { |
205 | 0 | if (cmValue value = e.GetProperty(p)) { |
206 | 0 | std::string helpstring = |
207 | 0 | cmStrCat(p, " property for variable: ", entryKey); |
208 | 0 | cmCacheManager::OutputHelpString(os, helpstring); |
209 | |
|
210 | 0 | std::string key = cmStrCat(entryKey, '-', p); |
211 | 0 | cmCacheManager::OutputKey(os, key); |
212 | 0 | os << ":INTERNAL="; |
213 | 0 | cmCacheManager::OutputValue(os, *value); |
214 | 0 | os << '\n'; |
215 | 0 | cmCacheManager::OutputNewlineTruncationWarning(os, key, *value, |
216 | 0 | messenger); |
217 | 0 | } |
218 | 0 | } |
219 | 0 | } |
220 | | |
221 | | bool cmCacheManager::SaveCache(std::string const& path, cmMessenger* messenger) |
222 | 0 | { |
223 | 0 | std::string cacheFile = cmStrCat(path, "/CMakeCache.txt"); |
224 | 0 | cmGeneratedFileStream fout(cacheFile); |
225 | 0 | fout.SetCopyIfDifferent(true); |
226 | 0 | if (!fout) { |
227 | 0 | cmSystemTools::Error( |
228 | 0 | cmStrCat("Unable to open cache file for save. ", std::move(cacheFile))); |
229 | 0 | cmSystemTools::ReportLastSystemError(""); |
230 | 0 | return false; |
231 | 0 | } |
232 | | // before writing the cache, update the version numbers |
233 | | // to the |
234 | 0 | this->AddCacheEntry("CMAKE_CACHE_MAJOR_VERSION", |
235 | 0 | std::to_string(cmVersion::GetMajorVersion()), |
236 | 0 | "Major version of cmake used to create the " |
237 | 0 | "current loaded cache", |
238 | 0 | cmStateEnums::INTERNAL); |
239 | 0 | this->AddCacheEntry("CMAKE_CACHE_MINOR_VERSION", |
240 | 0 | std::to_string(cmVersion::GetMinorVersion()), |
241 | 0 | "Minor version of cmake used to create the " |
242 | 0 | "current loaded cache", |
243 | 0 | cmStateEnums::INTERNAL); |
244 | 0 | this->AddCacheEntry("CMAKE_CACHE_PATCH_VERSION", |
245 | 0 | std::to_string(cmVersion::GetPatchVersion()), |
246 | 0 | "Patch version of cmake used to create the " |
247 | 0 | "current loaded cache", |
248 | 0 | cmStateEnums::INTERNAL); |
249 | | |
250 | | // Let us store the current working directory so that if somebody |
251 | | // Copies it, he will not be surprised |
252 | 0 | std::string currentcwd = path; |
253 | 0 | if (currentcwd[0] >= 'A' && currentcwd[0] <= 'Z' && currentcwd[1] == ':') { |
254 | | // Cast added to avoid compiler warning. Cast is ok because |
255 | | // value is guaranteed to fit in char by the above if... |
256 | 0 | currentcwd[0] = static_cast<char>(currentcwd[0] - 'A' + 'a'); |
257 | 0 | } |
258 | 0 | cmSystemTools::ConvertToUnixSlashes(currentcwd); |
259 | 0 | this->AddCacheEntry("CMAKE_CACHEFILE_DIR", currentcwd, |
260 | 0 | "This is the directory where this CMakeCache.txt" |
261 | 0 | " was created", |
262 | 0 | cmStateEnums::INTERNAL); |
263 | | |
264 | | /* clang-format off */ |
265 | 0 | fout << "# This is the CMakeCache file.\n" |
266 | 0 | "# For build in directory: " << currentcwd << "\n" |
267 | 0 | "# It was generated by CMake: " |
268 | 0 | << cmSystemTools::GetCMakeCommand() |
269 | 0 | << "\n" |
270 | 0 | "# You can edit this file to change values found and used by cmake." |
271 | 0 | "\n" |
272 | 0 | "# If you do not want to change any of the values, simply exit the " |
273 | 0 | "editor.\n" |
274 | 0 | "# If you do want to change a value, simply edit, save, and exit " |
275 | 0 | "the editor.\n" |
276 | 0 | "# The syntax for the file is as follows:\n" |
277 | 0 | "# KEY:TYPE=VALUE\n" |
278 | 0 | "# KEY is the name of a variable in the cache.\n" |
279 | 0 | "# TYPE is a hint to GUIs for the type of VALUE, DO NOT EDIT TYPE!." |
280 | 0 | "\n" |
281 | 0 | "# VALUE is the current value for the KEY.\n" |
282 | 0 | "\n" |
283 | 0 | "########################\n" |
284 | 0 | "# EXTERNAL cache entries\n" |
285 | 0 | "########################\n" |
286 | 0 | "\n"; |
287 | | /* clang-format on */ |
288 | |
|
289 | 0 | for (auto const& i : this->Cache) { |
290 | 0 | CacheEntry const& ce = i.second; |
291 | 0 | cmStateEnums::CacheEntryType t = ce.Type; |
292 | 0 | if (!ce.Initialized) { |
293 | | /* |
294 | | // This should be added in, but is not for now. |
295 | | cmSystemTools::Error(cmStrCat("Cache entry \"", i.first, "\" is |
296 | | uninitialized")); |
297 | | */ |
298 | 0 | } else if (t != cmStateEnums::INTERNAL) { |
299 | | // Format is key:type=value |
300 | 0 | if (cmValue help = ce.GetProperty("HELPSTRING")) { |
301 | 0 | cmCacheManager::OutputHelpString(fout, *help); |
302 | 0 | } else { |
303 | 0 | cmCacheManager::OutputHelpString(fout, "Missing description"); |
304 | 0 | } |
305 | 0 | cmCacheManager::OutputKey(fout, i.first); |
306 | 0 | fout << ':' << cmState::CacheEntryTypeToString(t) << '='; |
307 | 0 | cmCacheManager::OutputValue(fout, ce.Value); |
308 | 0 | fout << '\n'; |
309 | 0 | cmCacheManager::OutputNewlineTruncationWarning(fout, i.first, ce.Value, |
310 | 0 | messenger); |
311 | 0 | fout << '\n'; |
312 | 0 | } |
313 | 0 | } |
314 | |
|
315 | 0 | fout << "\n" |
316 | 0 | "########################\n" |
317 | 0 | "# INTERNAL cache entries\n" |
318 | 0 | "########################\n" |
319 | 0 | "\n"; |
320 | |
|
321 | 0 | for (auto const& i : this->Cache) { |
322 | 0 | if (!i.second.Initialized) { |
323 | 0 | continue; |
324 | 0 | } |
325 | | |
326 | 0 | cmStateEnums::CacheEntryType t = i.second.GetType(); |
327 | 0 | this->WritePropertyEntries(fout, i.first, i.second, messenger); |
328 | 0 | if (t == cmStateEnums::INTERNAL) { |
329 | | // Format is key:type=value |
330 | 0 | if (cmValue help = i.second.GetProperty("HELPSTRING")) { |
331 | 0 | cmCacheManager::OutputHelpString(fout, *help); |
332 | 0 | } |
333 | 0 | cmCacheManager::OutputKey(fout, i.first); |
334 | 0 | fout << ':' << cmState::CacheEntryTypeToString(t) << '='; |
335 | 0 | cmCacheManager::OutputValue(fout, i.second.GetValue()); |
336 | 0 | fout << '\n'; |
337 | 0 | cmCacheManager::OutputNewlineTruncationWarning( |
338 | 0 | fout, i.first, i.second.GetValue(), messenger); |
339 | 0 | } |
340 | 0 | } |
341 | 0 | fout << '\n'; |
342 | 0 | fout.Close(); |
343 | 0 | std::string checkCacheFile = cmStrCat(path, "/CMakeFiles"); |
344 | 0 | cmSystemTools::MakeDirectory(checkCacheFile); |
345 | 0 | checkCacheFile = cmStrCat(std::move(checkCacheFile), "/cmake.check_cache"); |
346 | 0 | cmsys::ofstream checkCache(checkCacheFile.c_str()); |
347 | 0 | if (!checkCache) { |
348 | 0 | cmSystemTools::Error( |
349 | 0 | cmStrCat("Unable to open check cache file for write. ", |
350 | 0 | std::move(checkCacheFile))); |
351 | 0 | return false; |
352 | 0 | } |
353 | 0 | checkCache << "# This file is generated by cmake for dependency checking " |
354 | 0 | "of the CMakeCache.txt file\n"; |
355 | 0 | return true; |
356 | 0 | } |
357 | | |
358 | | bool cmCacheManager::DeleteCache(std::string const& path) |
359 | 0 | { |
360 | 0 | std::string cacheFile = path; |
361 | 0 | cmSystemTools::ConvertToUnixSlashes(cacheFile); |
362 | 0 | std::string cmakeFiles = cacheFile; |
363 | 0 | cacheFile += "/CMakeCache.txt"; |
364 | 0 | if (cmSystemTools::FileExists(cacheFile)) { |
365 | 0 | cmSystemTools::RemoveFile(cacheFile); |
366 | | // now remove the files in the CMakeFiles directory |
367 | | // this cleans up language cache files |
368 | 0 | cmakeFiles += "/CMakeFiles"; |
369 | 0 | if (cmSystemTools::FileIsDirectory(cmakeFiles)) { |
370 | 0 | cmSystemTools::RemoveADirectory(cmakeFiles); |
371 | 0 | } |
372 | 0 | } |
373 | 0 | return true; |
374 | 0 | } |
375 | | |
376 | | void cmCacheManager::OutputKey(std::ostream& fout, std::string const& key) |
377 | 0 | { |
378 | | // support : in key name by double quoting |
379 | 0 | char const* q = |
380 | 0 | (key.find(':') != std::string::npos || cmHasLiteralPrefix(key, "//")) |
381 | 0 | ? "\"" |
382 | 0 | : ""; |
383 | 0 | fout << q << key << q; |
384 | 0 | } |
385 | | |
386 | | void cmCacheManager::OutputValue(std::ostream& fout, std::string const& value) |
387 | 0 | { |
388 | | // look for and truncate newlines |
389 | 0 | std::string::size_type newline = value.find('\n'); |
390 | 0 | if (newline != std::string::npos) { |
391 | 0 | std::string truncated = value.substr(0, newline); |
392 | 0 | OutputValueNoNewlines(fout, truncated); |
393 | 0 | } else { |
394 | 0 | OutputValueNoNewlines(fout, value); |
395 | 0 | } |
396 | 0 | } |
397 | | |
398 | | void cmCacheManager::OutputValueNoNewlines(std::ostream& fout, |
399 | | std::string const& value) |
400 | 0 | { |
401 | | // if value has trailing space or tab, enclose it in single quotes |
402 | 0 | if (!value.empty() && (value.back() == ' ' || value.back() == '\t')) { |
403 | 0 | fout << '\'' << value << '\''; |
404 | 0 | } else { |
405 | 0 | fout << value; |
406 | 0 | } |
407 | 0 | } |
408 | | |
409 | | void cmCacheManager::OutputHelpString(std::ostream& fout, |
410 | | std::string const& helpString) |
411 | 0 | { |
412 | 0 | std::string::size_type end = helpString.size(); |
413 | 0 | if (end == 0) { |
414 | 0 | return; |
415 | 0 | } |
416 | 0 | std::string oneLine; |
417 | 0 | std::string::size_type pos = 0; |
418 | 0 | for (std::string::size_type i = 1; i <= end; i++) { |
419 | 0 | if ((i == end) || (helpString[i] == '\n') || |
420 | 0 | ((i - pos >= 60) && (helpString[i] == ' '))) { |
421 | 0 | fout << "//"; |
422 | 0 | if (helpString[pos] == '\n') { |
423 | 0 | pos++; |
424 | 0 | fout << "\\n"; |
425 | 0 | } |
426 | 0 | oneLine = helpString.substr(pos, i - pos); |
427 | 0 | fout << oneLine << '\n'; |
428 | 0 | pos = i; |
429 | 0 | } |
430 | 0 | } |
431 | 0 | } |
432 | | |
433 | | void cmCacheManager::OutputWarningComment(std::ostream& fout, |
434 | | std::string const& message, |
435 | | bool wrapSpaces) |
436 | 0 | { |
437 | 0 | std::string::size_type end = message.size(); |
438 | 0 | std::string oneLine; |
439 | 0 | std::string::size_type pos = 0; |
440 | 0 | for (std::string::size_type i = 0; i <= end; i++) { |
441 | 0 | if ((i == end) || (message[i] == '\n') || |
442 | 0 | ((i - pos >= 60) && (message[i] == ' ') && wrapSpaces)) { |
443 | 0 | fout << "# "; |
444 | 0 | if (message[pos] == '\n') { |
445 | 0 | pos++; |
446 | 0 | fout << "\\n"; |
447 | 0 | } |
448 | 0 | oneLine = message.substr(pos, i - pos); |
449 | 0 | fout << oneLine << '\n'; |
450 | 0 | pos = i; |
451 | 0 | } |
452 | 0 | } |
453 | 0 | } |
454 | | |
455 | | void cmCacheManager::OutputNewlineTruncationWarning(std::ostream& fout, |
456 | | std::string const& key, |
457 | | std::string const& value, |
458 | | cmMessenger* messenger) |
459 | 0 | { |
460 | 0 | if (value.find('\n') != std::string::npos) { |
461 | 0 | if (messenger) { |
462 | 0 | std::string message = |
463 | 0 | cmStrCat("Value of ", key, " contained a newline; truncating"); |
464 | 0 | messenger->IssueMessage(MessageType::WARNING, message); |
465 | 0 | } |
466 | |
|
467 | 0 | std::string comment = |
468 | 0 | cmStrCat("WARNING: Value of ", key, |
469 | 0 | " contained a newline and was truncated. Original value:"); |
470 | |
|
471 | 0 | OutputWarningComment(fout, comment, true); |
472 | 0 | OutputWarningComment(fout, value, false); |
473 | 0 | } |
474 | 0 | } |
475 | | |
476 | | void cmCacheManager::RemoveCacheEntry(std::string const& key) |
477 | 0 | { |
478 | 0 | this->Cache.erase(key); |
479 | 0 | } |
480 | | |
481 | | cmCacheManager::CacheEntry* cmCacheManager::GetCacheEntry( |
482 | | std::string const& key) |
483 | 0 | { |
484 | 0 | auto i = this->Cache.find(key); |
485 | 0 | if (i != this->Cache.end()) { |
486 | 0 | return &i->second; |
487 | 0 | } |
488 | 0 | return nullptr; |
489 | 0 | } |
490 | | |
491 | | cmCacheManager::CacheEntry const* cmCacheManager::GetCacheEntry( |
492 | | std::string const& key) const |
493 | 3 | { |
494 | 3 | auto i = this->Cache.find(key); |
495 | 3 | if (i != this->Cache.end()) { |
496 | 0 | return &i->second; |
497 | 0 | } |
498 | 3 | return nullptr; |
499 | 3 | } |
500 | | |
501 | | cmValue cmCacheManager::GetInitializedCacheValue(std::string const& key) const |
502 | 3 | { |
503 | 3 | if (auto const* entry = this->GetCacheEntry(key)) { |
504 | 0 | if (entry->Initialized) { |
505 | 0 | return cmValue(entry->GetValue()); |
506 | 0 | } |
507 | 0 | } |
508 | 3 | return nullptr; |
509 | 3 | } |
510 | | |
511 | | void cmCacheManager::PrintCache(std::ostream& out) const |
512 | 0 | { |
513 | 0 | out << "=================================================\n" |
514 | 0 | "CMakeCache Contents:\n"; |
515 | 0 | for (auto const& i : this->Cache) { |
516 | 0 | if (i.second.Type != cmStateEnums::INTERNAL) { |
517 | 0 | out << i.first << " = " << i.second.Value << '\n'; |
518 | 0 | } |
519 | 0 | } |
520 | 0 | out << "\n\n" |
521 | 0 | "To change values in the CMakeCache, \n" |
522 | 0 | "edit CMakeCache.txt in your output directory.\n" |
523 | 0 | "=================================================\n"; |
524 | 0 | } |
525 | | |
526 | | void cmCacheManager::AddCacheEntry(std::string const& key, cmValue value, |
527 | | cmValue helpString, |
528 | | cmStateEnums::CacheEntryType type) |
529 | 3 | { |
530 | 3 | CacheEntry& e = this->Cache[key]; |
531 | 3 | e.SetValue(value); |
532 | 3 | e.Type = type; |
533 | | // make sure we only use unix style paths |
534 | 3 | if (type == cmStateEnums::FILEPATH || type == cmStateEnums::PATH) { |
535 | 0 | if (e.Value.find(';') != std::string::npos) { |
536 | 0 | cmList paths{ e.Value }; |
537 | 0 | for (std::string& i : paths) { |
538 | 0 | cmSystemTools::ConvertToUnixSlashes(i); |
539 | 0 | } |
540 | 0 | e.Value = paths.to_string(); |
541 | 0 | } else { |
542 | 0 | cmSystemTools::ConvertToUnixSlashes(e.Value); |
543 | 0 | } |
544 | 0 | } |
545 | 3 | e.SetProperty( |
546 | 3 | "HELPSTRING", |
547 | 3 | helpString ? *helpString |
548 | 3 | : std::string{ |
549 | 0 | "(This variable does not exist and should not be used)" }); |
550 | 3 | } |
551 | | |
552 | | void cmCacheManager::CacheEntry::SetValue(cmValue value) |
553 | 3 | { |
554 | 3 | if (value) { |
555 | 3 | this->Value = *value; |
556 | 3 | this->Initialized = true; |
557 | 3 | } else { |
558 | 0 | this->Value.clear(); |
559 | 0 | } |
560 | 3 | } |
561 | | |
562 | | std::vector<std::string> cmCacheManager::CacheEntry::GetPropertyList() const |
563 | 0 | { |
564 | 0 | return this->Properties.GetKeys(); |
565 | 0 | } |
566 | | |
567 | | cmValue cmCacheManager::CacheEntry::GetProperty(std::string const& prop) const |
568 | 0 | { |
569 | 0 | if (prop == "TYPE") { |
570 | 0 | return cmValue(cmState::CacheEntryTypeToString(this->Type)); |
571 | 0 | } |
572 | 0 | if (prop == "VALUE") { |
573 | 0 | return cmValue(this->Value); |
574 | 0 | } |
575 | 0 | return this->Properties.GetPropertyValue(prop); |
576 | 0 | } |
577 | | |
578 | | bool cmCacheManager::CacheEntry::GetPropertyAsBool( |
579 | | std::string const& prop) const |
580 | 0 | { |
581 | 0 | return this->GetProperty(prop).IsOn(); |
582 | 0 | } |
583 | | |
584 | | void cmCacheManager::CacheEntry::SetProperty(std::string const& prop, |
585 | | std::string const& value) |
586 | 3 | { |
587 | 3 | if (prop == "TYPE") { |
588 | 0 | this->Type = cmState::StringToCacheEntryType(value); |
589 | 3 | } else if (prop == "VALUE") { |
590 | 0 | this->Value = value; |
591 | 3 | } else { |
592 | 3 | this->Properties.SetProperty(prop, value); |
593 | 3 | } |
594 | 3 | } |
595 | | |
596 | | void cmCacheManager::CacheEntry::SetProperty(std::string const& p, bool v) |
597 | 0 | { |
598 | 0 | this->SetProperty(p, v ? std::string{ "ON" } : std::string{ "OFF" }); |
599 | 0 | } |
600 | | |
601 | | void cmCacheManager::CacheEntry::RemoveProperty(std::string const& prop) |
602 | 0 | { |
603 | 0 | if (prop == "TYPE") { |
604 | 0 | this->Type = cmState::StringToCacheEntryType("STRING"); |
605 | 0 | } else if (prop == "VALUE") { |
606 | 0 | this->Value.clear(); |
607 | 0 | } else { |
608 | 0 | this->Properties.RemoveProperty(prop); |
609 | 0 | } |
610 | 0 | } |
611 | | |
612 | | void cmCacheManager::CacheEntry::AppendProperty(std::string const& prop, |
613 | | std::string const& value, |
614 | | bool asString) |
615 | 0 | { |
616 | 0 | if (prop == "TYPE") { |
617 | 0 | this->Type = |
618 | 0 | cmState::StringToCacheEntryType(!value.empty() ? value : "STRING"); |
619 | 0 | } else if (prop == "VALUE") { |
620 | 0 | if (!value.empty()) { |
621 | 0 | if (!this->Value.empty() && !asString) { |
622 | 0 | this->Value += ";"; |
623 | 0 | } |
624 | 0 | this->Value += value; |
625 | 0 | } |
626 | 0 | } else { |
627 | 0 | this->Properties.AppendProperty(prop, value, asString); |
628 | 0 | } |
629 | 0 | } |