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