/src/CMake/Source/cmGlobVerificationManager.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 "cmGlobVerificationManager.h" |
4 | | |
5 | | #include <sstream> |
6 | | |
7 | | #include "cmsys/FStream.hxx" |
8 | | |
9 | | #include "cmGeneratedFileStream.h" |
10 | | #include "cmGlobCacheEntry.h" |
11 | | #include "cmListFileCache.h" |
12 | | #include "cmMessageType.h" |
13 | | #include "cmMessenger.h" |
14 | | #include "cmStringAlgorithms.h" |
15 | | #include "cmSystemTools.h" |
16 | | #include "cmVersion.h" |
17 | | |
18 | | bool cmGlobVerificationManager::SaveVerificationScript(std::string const& path, |
19 | | cmMessenger* messenger) |
20 | 0 | { |
21 | 0 | if (this->Cache.empty()) { |
22 | 0 | return true; |
23 | 0 | } |
24 | | |
25 | 0 | std::string scriptFile = cmStrCat(path, "/CMakeFiles"); |
26 | 0 | std::string stampFile = scriptFile; |
27 | 0 | cmSystemTools::MakeDirectory(scriptFile); |
28 | 0 | scriptFile += "/VerifyGlobs.cmake"; |
29 | 0 | stampFile += "/cmake.verify_globs"; |
30 | 0 | cmGeneratedFileStream verifyScriptFile(scriptFile); |
31 | 0 | verifyScriptFile.SetCopyIfDifferent(true); |
32 | 0 | if (!verifyScriptFile) { |
33 | 0 | cmSystemTools::Error("Unable to open verification script file for save. " + |
34 | 0 | scriptFile); |
35 | 0 | cmSystemTools::ReportLastSystemError(""); |
36 | 0 | return false; |
37 | 0 | } |
38 | | |
39 | 0 | verifyScriptFile << std::boolalpha; |
40 | 0 | verifyScriptFile << "# CMAKE generated file: DO NOT EDIT!\n" |
41 | 0 | << "# Generated by CMake Version " |
42 | 0 | << cmVersion::GetMajorVersion() << "." |
43 | 0 | << cmVersion::GetMinorVersion() << "\n"; |
44 | |
|
45 | 0 | for (auto const& i : this->Cache) { |
46 | 0 | CacheEntryKey k = std::get<0>(i); |
47 | 0 | CacheEntryValue v = std::get<1>(i); |
48 | |
|
49 | 0 | if (!v.Initialized) { |
50 | 0 | continue; |
51 | 0 | } |
52 | | |
53 | 0 | verifyScriptFile << "\n"; |
54 | |
|
55 | 0 | for (auto const& bt : v.Backtraces) { |
56 | 0 | verifyScriptFile << "# " << std::get<0>(bt); |
57 | 0 | messenger->PrintBacktraceTitle(verifyScriptFile, std::get<1>(bt)); |
58 | 0 | verifyScriptFile << "\n"; |
59 | 0 | } |
60 | |
|
61 | 0 | k.PrintGlobCommand(verifyScriptFile, "NEW_GLOB"); |
62 | 0 | verifyScriptFile << "\n"; |
63 | |
|
64 | 0 | verifyScriptFile << "set(OLD_GLOB\n"; |
65 | 0 | for (std::string const& file : v.Files) { |
66 | 0 | verifyScriptFile << " \"" << file << "\"\n"; |
67 | 0 | } |
68 | 0 | verifyScriptFile << " )\n"; |
69 | |
|
70 | 0 | verifyScriptFile << "if(NOT \"${NEW_GLOB}\" STREQUAL \"${OLD_GLOB}\")\n" |
71 | 0 | << " message(\"-- GLOB mismatch!\")\n" |
72 | 0 | << " set(NEW_ONLY ${NEW_GLOB})\n" |
73 | 0 | << " set(OLD_ONLY ${OLD_GLOB})\n" |
74 | 0 | << " list(REMOVE_ITEM NEW_ONLY ${OLD_GLOB})\n" |
75 | 0 | << " list(REMOVE_ITEM OLD_ONLY ${NEW_GLOB})\n" |
76 | 0 | << " if(NEW_ONLY)\n" |
77 | 0 | << " message(\"The following files were added:\")\n" |
78 | 0 | << " foreach(VAR_FILE IN LISTS NEW_ONLY)\n" |
79 | 0 | << " message(\" +${VAR_FILE}\")\n" |
80 | 0 | << " endforeach()\n" |
81 | 0 | << " endif()\n" |
82 | 0 | << " if(OLD_ONLY)\n" |
83 | 0 | << " message(\"The following files were removed:\")\n" |
84 | 0 | << " foreach(VAR_FILE IN LISTS OLD_ONLY)\n" |
85 | 0 | << " message(\" -${VAR_FILE}\")\n" |
86 | 0 | << " endforeach()\n" |
87 | 0 | << " endif()\n" |
88 | 0 | << " file(TOUCH_NOCREATE \"" << stampFile << "\")\n" |
89 | 0 | << "endif()\n"; |
90 | 0 | } |
91 | 0 | verifyScriptFile.Close(); |
92 | |
|
93 | 0 | cmsys::ofstream verifyStampFile(stampFile.c_str()); |
94 | 0 | if (!verifyStampFile) { |
95 | 0 | cmSystemTools::Error("Unable to open verification stamp file for write. " + |
96 | 0 | stampFile); |
97 | 0 | return false; |
98 | 0 | } |
99 | 0 | verifyStampFile << "# This file is generated by CMake for checking of the " |
100 | 0 | "VerifyGlobs.cmake file\n"; |
101 | 0 | this->VerifyScript = scriptFile; |
102 | 0 | this->VerifyStamp = stampFile; |
103 | 0 | return true; |
104 | 0 | } |
105 | | |
106 | | bool cmGlobVerificationManager::DoWriteVerifyTarget() const |
107 | 0 | { |
108 | 0 | return !this->VerifyScript.empty() && !this->VerifyStamp.empty(); |
109 | 0 | } |
110 | | |
111 | | bool cmGlobVerificationManager::CacheEntryKey::operator<( |
112 | | CacheEntryKey const& r) const |
113 | 0 | { |
114 | 0 | if (this->Recurse < r.Recurse) { |
115 | 0 | return true; |
116 | 0 | } |
117 | 0 | if (this->Recurse > r.Recurse) { |
118 | 0 | return false; |
119 | 0 | } |
120 | 0 | if (this->ListDirectories < r.ListDirectories) { |
121 | 0 | return true; |
122 | 0 | } |
123 | 0 | if (this->ListDirectories > r.ListDirectories) { |
124 | 0 | return false; |
125 | 0 | } |
126 | 0 | if (this->FollowSymlinks < r.FollowSymlinks) { |
127 | 0 | return true; |
128 | 0 | } |
129 | 0 | if (this->FollowSymlinks > r.FollowSymlinks) { |
130 | 0 | return false; |
131 | 0 | } |
132 | 0 | if (this->Relative < r.Relative) { |
133 | 0 | return true; |
134 | 0 | } |
135 | 0 | if (this->Relative > r.Relative) { |
136 | 0 | return false; |
137 | 0 | } |
138 | 0 | if (this->Expression < r.Expression) { |
139 | 0 | return true; |
140 | 0 | } |
141 | 0 | if (this->Expression > r.Expression) { |
142 | 0 | return false; |
143 | 0 | } |
144 | 0 | return false; |
145 | 0 | } |
146 | | |
147 | | void cmGlobVerificationManager::CacheEntryKey::PrintGlobCommand( |
148 | | std::ostream& out, std::string const& cmdVar) |
149 | 0 | { |
150 | 0 | out << "file(GLOB" << (this->Recurse ? "_RECURSE " : " "); |
151 | 0 | out << cmdVar << " "; |
152 | 0 | if (this->Recurse && this->FollowSymlinks) { |
153 | 0 | out << "FOLLOW_SYMLINKS "; |
154 | 0 | } |
155 | 0 | out << "LIST_DIRECTORIES " << this->ListDirectories << " "; |
156 | 0 | if (!this->Relative.empty()) { |
157 | 0 | out << "RELATIVE \"" << this->Relative << "\" "; |
158 | 0 | } |
159 | 0 | out << "\"" << this->Expression << "\")"; |
160 | 0 | } |
161 | | |
162 | | void cmGlobVerificationManager::AddCacheEntry( |
163 | | cmGlobCacheEntry const& entry, std::string const& variable, |
164 | | cmListFileBacktrace const& backtrace, cmMessenger* messenger) |
165 | 0 | { |
166 | 0 | CacheEntryKey key = |
167 | 0 | CacheEntryKey(entry.Recurse, entry.ListDirectories, entry.FollowSymlinks, |
168 | 0 | entry.Relative, entry.Expression); |
169 | 0 | CacheEntryValue& value = this->Cache[key]; |
170 | 0 | if (!value.Initialized) { |
171 | 0 | value.Files = entry.Files; |
172 | 0 | value.Initialized = true; |
173 | 0 | value.Backtraces.emplace_back(variable, backtrace); |
174 | 0 | } else if (value.Initialized && value.Files != entry.Files) { |
175 | 0 | std::ostringstream message; |
176 | 0 | message << std::boolalpha; |
177 | 0 | message << "The glob expression\n "; |
178 | 0 | key.PrintGlobCommand(message, variable); |
179 | 0 | message << "\nwas already present in the glob cache but the directory " |
180 | 0 | "contents have changed during the configuration run.\n"; |
181 | 0 | message << "Matching glob expressions:"; |
182 | 0 | for (auto const& bt : value.Backtraces) { |
183 | 0 | message << "\n " << std::get<0>(bt); |
184 | 0 | messenger->PrintBacktraceTitle(message, std::get<1>(bt)); |
185 | 0 | } |
186 | 0 | messenger->IssueMessage(MessageType::FATAL_ERROR, message.str(), |
187 | 0 | backtrace); |
188 | 0 | } else { |
189 | 0 | value.Backtraces.emplace_back(variable, backtrace); |
190 | 0 | } |
191 | 0 | } |
192 | | |
193 | | std::vector<cmGlobCacheEntry> cmGlobVerificationManager::GetCacheEntries() |
194 | | const |
195 | 0 | { |
196 | 0 | std::vector<cmGlobCacheEntry> entries; |
197 | 0 | for (auto const& i : this->Cache) { |
198 | 0 | CacheEntryKey k = std::get<0>(i); |
199 | 0 | CacheEntryValue v = std::get<1>(i); |
200 | 0 | if (v.Initialized) { |
201 | 0 | entries.emplace_back(k.Recurse, k.ListDirectories, k.FollowSymlinks, |
202 | 0 | k.Relative, k.Expression, v.Files); |
203 | 0 | } |
204 | 0 | } |
205 | 0 | return entries; |
206 | 0 | } |
207 | | |
208 | | void cmGlobVerificationManager::Reset() |
209 | 1 | { |
210 | 1 | this->Cache.clear(); |
211 | 1 | this->VerifyScript.clear(); |
212 | 1 | this->VerifyStamp.clear(); |
213 | 1 | } |