/src/CMake/Source/cmFindPackageCommand.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 "cmFindPackageCommand.h" |
4 | | |
5 | | #include <algorithm> |
6 | | #include <cassert> |
7 | | #include <cstdio> |
8 | | #include <deque> |
9 | | #include <functional> |
10 | | #include <iterator> |
11 | | #include <sstream> |
12 | | #include <unordered_set> |
13 | | #include <utility> |
14 | | |
15 | | #include <cm/memory> |
16 | | #include <cm/optional> |
17 | | #include <cmext/algorithm> |
18 | | #include <cmext/string_view> |
19 | | |
20 | | #include "cmsys/Directory.hxx" |
21 | | #include "cmsys/FStream.hxx" |
22 | | #include "cmsys/Glob.hxx" |
23 | | #include "cmsys/RegularExpression.hxx" |
24 | | #include "cmsys/String.h" |
25 | | |
26 | | #include "cmAlgorithms.h" |
27 | | #include "cmConfigureLog.h" |
28 | | #include "cmDependencyProvider.h" |
29 | | #include "cmExecutionStatus.h" |
30 | | #include "cmExperimental.h" |
31 | | #include "cmFindPackageStack.h" |
32 | | #include "cmList.h" |
33 | | #include "cmListFileCache.h" |
34 | | #include "cmMakefile.h" |
35 | | #include "cmMessageType.h" |
36 | | #include "cmPackageState.h" |
37 | | #include "cmPolicies.h" |
38 | | #include "cmRange.h" |
39 | | #include "cmSearchPath.h" |
40 | | #include "cmState.h" |
41 | | #include "cmStateSnapshot.h" |
42 | | #include "cmStateTypes.h" |
43 | | #include "cmStringAlgorithms.h" |
44 | | #include "cmSystemTools.h" |
45 | | #include "cmValue.h" |
46 | | #include "cmVersionMacros.h" |
47 | | #include "cmWindowsRegistry.h" |
48 | | |
49 | | #if defined(__HAIKU__) |
50 | | # include <FindDirectory.h> |
51 | | # include <StorageDefs.h> |
52 | | #endif |
53 | | |
54 | | #if defined(_WIN32) && !defined(__CYGWIN__) |
55 | | # include <windows.h> |
56 | | // http://msdn.microsoft.com/en-us/library/aa384253%28v=vs.85%29.aspx |
57 | | # if !defined(KEY_WOW64_32KEY) |
58 | | # define KEY_WOW64_32KEY 0x0200 |
59 | | # endif |
60 | | # if !defined(KEY_WOW64_64KEY) |
61 | | # define KEY_WOW64_64KEY 0x0100 |
62 | | # endif |
63 | | #endif |
64 | | |
65 | | namespace { |
66 | | |
67 | | using pdt = cmFindPackageCommand::PackageDescriptionType; |
68 | | using ParsedVersion = cmPackageInfoReader::Pep440Version; |
69 | | |
70 | | template <template <typename> class Op> |
71 | | struct StrverscmpOp |
72 | | { |
73 | | bool operator()(std::string const& lhs, std::string const& rhs) const |
74 | 0 | { |
75 | 0 | return Op<int>()(cmSystemTools::strverscmp(lhs, rhs), 0); |
76 | 0 | } Unexecuted instantiation: cmFindPackageCommand.cxx:(anonymous namespace)::StrverscmpOp<std::__1::greater>::operator()(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) const Unexecuted instantiation: cmFindPackageCommand.cxx:(anonymous namespace)::StrverscmpOp<std::__1::less>::operator()(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) const |
77 | | }; |
78 | | |
79 | | std::size_t collectPathsForDebug(std::string& buffer, |
80 | | cmSearchPath const& searchPath, |
81 | | std::size_t const startIndex = 0) |
82 | 0 | { |
83 | 0 | auto const& paths = searchPath.GetPaths(); |
84 | 0 | if (paths.empty()) { |
85 | 0 | buffer += " none\n"; |
86 | 0 | return 0; |
87 | 0 | } |
88 | 0 | for (auto i = startIndex; i < paths.size(); i++) { |
89 | 0 | buffer += cmStrCat(" ", paths[i].Path, '\n'); |
90 | 0 | } |
91 | 0 | return paths.size(); |
92 | 0 | } |
93 | | |
94 | | #if !(defined(_WIN32) && !defined(__CYGWIN__)) |
95 | | class cmFindPackageCommandHoldFile |
96 | | { |
97 | | char const* File; |
98 | | |
99 | | public: |
100 | | cmFindPackageCommandHoldFile(char const* const f) |
101 | 0 | : File(f) |
102 | 0 | { |
103 | 0 | } |
104 | | ~cmFindPackageCommandHoldFile() |
105 | 0 | { |
106 | 0 | if (this->File) { |
107 | 0 | cmSystemTools::RemoveFile(this->File); |
108 | 0 | } |
109 | 0 | } |
110 | | cmFindPackageCommandHoldFile(cmFindPackageCommandHoldFile const&) = delete; |
111 | | cmFindPackageCommandHoldFile& operator=( |
112 | | cmFindPackageCommandHoldFile const&) = delete; |
113 | 0 | void Release() { this->File = nullptr; } |
114 | | }; |
115 | | #endif |
116 | | |
117 | | bool isDirentryToIgnore(char const* const fname) |
118 | 0 | { |
119 | 0 | assert(fname); |
120 | 0 | assert(fname[0] != 0); |
121 | 0 | return fname[0] == '.' && |
122 | 0 | (fname[1] == 0 || (fname[1] == '.' && fname[2] == 0)); |
123 | 0 | } |
124 | | |
125 | | class cmAppendPathSegmentGenerator |
126 | | { |
127 | | public: |
128 | | cmAppendPathSegmentGenerator(cm::string_view dirName) |
129 | 0 | : DirName{ dirName } |
130 | 0 | { |
131 | 0 | } |
132 | | |
133 | | std::string GetNextCandidate(std::string const& parent) |
134 | 0 | { |
135 | 0 | if (this->NeedReset) { |
136 | 0 | return {}; |
137 | 0 | } |
138 | 0 | this->NeedReset = true; |
139 | 0 | return cmStrCat(parent, this->DirName, '/'); |
140 | 0 | } |
141 | | |
142 | 0 | void Reset() { this->NeedReset = false; } |
143 | | |
144 | | private: |
145 | | cm::string_view const DirName; |
146 | | bool NeedReset = false; |
147 | | }; |
148 | | |
149 | | class cmEnumPathSegmentsGenerator |
150 | | { |
151 | | public: |
152 | | cmEnumPathSegmentsGenerator(std::vector<cm::string_view> const& init) |
153 | 0 | : Names{ init } |
154 | 0 | , Current{ this->Names.get().cbegin() } |
155 | 0 | { |
156 | 0 | } |
157 | | |
158 | | std::string GetNextCandidate(std::string const& parent) |
159 | 0 | { |
160 | 0 | if (this->Current != this->Names.get().cend()) { |
161 | 0 | return cmStrCat(parent, *this->Current++, '/'); |
162 | 0 | } |
163 | 0 | return {}; |
164 | 0 | } |
165 | | |
166 | 0 | void Reset() { this->Current = this->Names.get().cbegin(); } |
167 | | |
168 | | private: |
169 | | std::reference_wrapper<std::vector<cm::string_view> const> Names; |
170 | | std::vector<cm::string_view>::const_iterator Current; |
171 | | }; |
172 | | |
173 | | class cmCaseInsensitiveDirectoryListGenerator |
174 | | { |
175 | | public: |
176 | | cmCaseInsensitiveDirectoryListGenerator(cm::string_view name) |
177 | 0 | : DirName{ name } |
178 | 0 | { |
179 | 0 | } |
180 | | |
181 | | std::string GetNextCandidate(std::string const& parent) |
182 | 0 | { |
183 | 0 | if (!this->Loaded) { |
184 | 0 | this->CurrentIdx = 0ul; |
185 | 0 | this->Loaded = true; |
186 | 0 | if (!this->DirectoryLister.Load(parent)) { |
187 | 0 | return {}; |
188 | 0 | } |
189 | 0 | } |
190 | | |
191 | 0 | while (this->CurrentIdx < this->DirectoryLister.GetNumberOfFiles()) { |
192 | 0 | char const* const fname = |
193 | 0 | this->DirectoryLister.GetFile(this->CurrentIdx++); |
194 | 0 | if (isDirentryToIgnore(fname)) { |
195 | 0 | continue; |
196 | 0 | } |
197 | 0 | if (cmsysString_strcasecmp(fname, this->DirName.data()) == 0) { |
198 | 0 | auto candidate = cmStrCat(parent, fname, '/'); |
199 | 0 | if (cmSystemTools::FileIsDirectory(candidate)) { |
200 | 0 | return candidate; |
201 | 0 | } |
202 | 0 | } |
203 | 0 | } |
204 | 0 | return {}; |
205 | 0 | } |
206 | | |
207 | 0 | void Reset() { this->Loaded = false; } |
208 | | |
209 | | private: |
210 | | cmsys::Directory DirectoryLister; |
211 | | cm::string_view const DirName; |
212 | | unsigned long CurrentIdx = 0ul; |
213 | | bool Loaded = false; |
214 | | }; |
215 | | |
216 | | class cmDirectoryListGenerator |
217 | | { |
218 | | public: |
219 | | cmDirectoryListGenerator(std::vector<std::string> const* names, |
220 | | bool exactMatch) |
221 | 0 | : Names{ names } |
222 | 0 | , ExactMatch{ exactMatch } |
223 | 0 | , Current{ this->Matches.cbegin() } |
224 | 0 | { |
225 | 0 | assert(names || !exactMatch); |
226 | 0 | assert(!names || !names->empty()); |
227 | 0 | } |
228 | 0 | virtual ~cmDirectoryListGenerator() = default; |
229 | | |
230 | | std::string GetNextCandidate(std::string const& parent) |
231 | 0 | { |
232 | | // Construct a list of matches if not yet |
233 | 0 | if (this->Matches.empty()) { |
234 | 0 | cmsys::Directory directoryLister; |
235 | | // ALERT `Directory::Load()` keeps only names |
236 | | // internally and LOST entry type from `dirent`. |
237 | | // So, `Directory::FileIsDirectory` gonna use |
238 | | // `SystemTools::FileIsDirectory()` and waste a syscall. |
239 | | // TODO Need to enhance the `Directory` class. |
240 | 0 | directoryLister.Load(parent); |
241 | | |
242 | | // ATTENTION Is it guaranteed that first two entries are |
243 | | // `.` and `..`? |
244 | | // TODO If so, just start with index 2 and drop the |
245 | | // `isDirentryToIgnore(i)` condition to check. |
246 | 0 | for (auto i = 0ul; i < directoryLister.GetNumberOfFiles(); ++i) { |
247 | 0 | char const* const fname = directoryLister.GetFile(i); |
248 | | // Skip entries to ignore or that aren't directories. |
249 | 0 | if (isDirentryToIgnore(fname)) { |
250 | 0 | continue; |
251 | 0 | } |
252 | | |
253 | 0 | if (!this->Names) { |
254 | 0 | if (directoryLister.FileIsDirectory(i)) { |
255 | 0 | this->Matches.emplace_back(fname); |
256 | 0 | } |
257 | 0 | } else { |
258 | 0 | for (auto const& n : *this->Names) { |
259 | | // NOTE Customization point for |
260 | | // `cmMacProjectDirectoryListGenerator` |
261 | 0 | auto const name = this->TransformNameBeforeCmp(n); |
262 | | // Skip entries that don't match. |
263 | 0 | auto const equal = |
264 | 0 | ((this->ExactMatch |
265 | 0 | ? cmsysString_strcasecmp(fname, name.c_str()) |
266 | 0 | : cmsysString_strncasecmp(fname, name.c_str(), |
267 | 0 | name.length())) == 0); |
268 | 0 | if (equal) { |
269 | 0 | if (directoryLister.FileIsDirectory(i)) { |
270 | 0 | this->Matches.emplace_back(fname); |
271 | 0 | } |
272 | 0 | break; |
273 | 0 | } |
274 | 0 | } |
275 | 0 | } |
276 | 0 | } |
277 | | // NOTE Customization point for `cmProjectDirectoryListGenerator` |
278 | 0 | this->OnMatchesLoaded(); |
279 | |
|
280 | 0 | this->Current = this->Matches.cbegin(); |
281 | 0 | } |
282 | |
|
283 | 0 | if (this->Current != this->Matches.cend()) { |
284 | 0 | auto candidate = cmStrCat(parent, *this->Current++, '/'); |
285 | 0 | return candidate; |
286 | 0 | } |
287 | | |
288 | 0 | return {}; |
289 | 0 | } |
290 | | |
291 | | void Reset() |
292 | 0 | { |
293 | 0 | this->Matches.clear(); |
294 | 0 | this->Current = this->Matches.cbegin(); |
295 | 0 | } |
296 | | |
297 | | protected: |
298 | 0 | virtual void OnMatchesLoaded() {} |
299 | 0 | virtual std::string TransformNameBeforeCmp(std::string same) { return same; } |
300 | | |
301 | | std::vector<std::string> const* Names; |
302 | | bool const ExactMatch; |
303 | | std::vector<std::string> Matches; |
304 | | std::vector<std::string>::const_iterator Current; |
305 | | }; |
306 | | |
307 | | class cmProjectDirectoryListGenerator : public cmDirectoryListGenerator |
308 | | { |
309 | | public: |
310 | | cmProjectDirectoryListGenerator(std::vector<std::string> const* names, |
311 | | cmFindPackageCommand::SortOrderType so, |
312 | | cmFindPackageCommand::SortDirectionType sd, |
313 | | bool exactMatch) |
314 | 0 | : cmDirectoryListGenerator{ names, exactMatch } |
315 | 0 | , SortOrder{ so } |
316 | 0 | , SortDirection{ sd } |
317 | 0 | { |
318 | 0 | } |
319 | | |
320 | | protected: |
321 | | void OnMatchesLoaded() override |
322 | 0 | { |
323 | | // check if there is a specific sorting order to perform |
324 | 0 | if (this->SortOrder != cmFindPackageCommand::None) { |
325 | 0 | cmFindPackageCommand::Sort(this->Matches.begin(), this->Matches.end(), |
326 | 0 | this->SortOrder, this->SortDirection); |
327 | 0 | } |
328 | 0 | } |
329 | | |
330 | | private: |
331 | | // sort parameters |
332 | | cmFindPackageCommand::SortOrderType const SortOrder; |
333 | | cmFindPackageCommand::SortDirectionType const SortDirection; |
334 | | }; |
335 | | |
336 | | class cmMacProjectDirectoryListGenerator : public cmDirectoryListGenerator |
337 | | { |
338 | | public: |
339 | | cmMacProjectDirectoryListGenerator(std::vector<std::string> const* names, |
340 | | cm::string_view ext) |
341 | 0 | : cmDirectoryListGenerator{ names, true } |
342 | 0 | , Extension{ ext } |
343 | 0 | { |
344 | 0 | } |
345 | | |
346 | | protected: |
347 | | std::string TransformNameBeforeCmp(std::string name) override |
348 | 0 | { |
349 | 0 | return cmStrCat(name, this->Extension); |
350 | 0 | } |
351 | | |
352 | | private: |
353 | | cm::string_view const Extension; |
354 | | }; |
355 | | |
356 | | class cmAnyDirectoryListGenerator : public cmProjectDirectoryListGenerator |
357 | | { |
358 | | public: |
359 | | cmAnyDirectoryListGenerator(cmFindPackageCommand::SortOrderType so, |
360 | | cmFindPackageCommand::SortDirectionType sd) |
361 | 0 | : cmProjectDirectoryListGenerator(nullptr, so, sd, false) |
362 | 0 | { |
363 | 0 | } |
364 | | }; |
365 | | |
366 | | #if defined(__LCC__) |
367 | | # define CM_LCC_DIAG_SUPPRESS_1222 |
368 | | # pragma diag_suppress 1222 // invalid error number (3288, but works anyway) |
369 | | # define CM_LCC_DIAG_SUPPRESS_3288 |
370 | | # pragma diag_suppress 3288 // parameter was declared but never referenced |
371 | | # define CM_LCC_DIAG_SUPPRESS_3301 |
372 | | # pragma diag_suppress 3301 // parameter was declared but never referenced |
373 | | # define CM_LCC_DIAG_SUPPRESS_3308 |
374 | | # pragma diag_suppress 3308 // parameter was declared but never referenced |
375 | | #endif |
376 | | |
377 | | void ResetGenerator() |
378 | 0 | { |
379 | 0 | } |
380 | | |
381 | | template <typename Generator> |
382 | | void ResetGenerator(Generator&& generator) |
383 | 0 | { |
384 | 0 | std::forward<Generator&&>(generator).Reset(); |
385 | 0 | } Unexecuted instantiation: cmFindPackageCommand.cxx:void (anonymous namespace)::ResetGenerator<(anonymous namespace)::cmProjectDirectoryListGenerator&>((anonymous namespace)::cmProjectDirectoryListGenerator&) Unexecuted instantiation: cmFindPackageCommand.cxx:void (anonymous namespace)::ResetGenerator<(anonymous namespace)::cmCaseInsensitiveDirectoryListGenerator&>((anonymous namespace)::cmCaseInsensitiveDirectoryListGenerator&) Unexecuted instantiation: cmFindPackageCommand.cxx:void (anonymous namespace)::ResetGenerator<(anonymous namespace)::cmAnyDirectoryListGenerator&>((anonymous namespace)::cmAnyDirectoryListGenerator&) Unexecuted instantiation: cmFindPackageCommand.cxx:void (anonymous namespace)::ResetGenerator<(anonymous namespace)::cmEnumPathSegmentsGenerator&>((anonymous namespace)::cmEnumPathSegmentsGenerator&) Unexecuted instantiation: cmFindPackageCommand.cxx:void (anonymous namespace)::ResetGenerator<(anonymous namespace)::cmAppendPathSegmentGenerator&>((anonymous namespace)::cmAppendPathSegmentGenerator&) Unexecuted instantiation: cmFindPackageCommand.cxx:void (anonymous namespace)::ResetGenerator<(anonymous namespace)::cmMacProjectDirectoryListGenerator&>((anonymous namespace)::cmMacProjectDirectoryListGenerator&) Unexecuted instantiation: cmFindPackageCommand.cxx:void (anonymous namespace)::ResetGenerator<(anonymous namespace)::cmCaseInsensitiveDirectoryListGenerator>((anonymous namespace)::cmCaseInsensitiveDirectoryListGenerator&&) Unexecuted instantiation: cmFindPackageCommand.cxx:void (anonymous namespace)::ResetGenerator<(anonymous namespace)::cmAppendPathSegmentGenerator>((anonymous namespace)::cmAppendPathSegmentGenerator&&) |
386 | | |
387 | | template <typename Generator, typename... Generators> |
388 | | void ResetGenerator(Generator&& generator, Generators&&... generators) |
389 | 0 | { |
390 | 0 | ResetGenerator(std::forward<Generator&&>(generator)); |
391 | 0 | ResetGenerator(std::forward<Generators&&>(generators)...); |
392 | 0 | } Unexecuted instantiation: cmFindPackageCommand.cxx:void (anonymous namespace)::ResetGenerator<(anonymous namespace)::cmCaseInsensitiveDirectoryListGenerator&, (anonymous namespace)::cmAnyDirectoryListGenerator&>((anonymous namespace)::cmCaseInsensitiveDirectoryListGenerator&, (anonymous namespace)::cmAnyDirectoryListGenerator&) Unexecuted instantiation: cmFindPackageCommand.cxx:void (anonymous namespace)::ResetGenerator<(anonymous namespace)::cmProjectDirectoryListGenerator&, (anonymous namespace)::cmAnyDirectoryListGenerator&>((anonymous namespace)::cmProjectDirectoryListGenerator&, (anonymous namespace)::cmAnyDirectoryListGenerator&) Unexecuted instantiation: cmFindPackageCommand.cxx:void (anonymous namespace)::ResetGenerator<(anonymous namespace)::cmCaseInsensitiveDirectoryListGenerator&, (anonymous namespace)::cmProjectDirectoryListGenerator&>((anonymous namespace)::cmCaseInsensitiveDirectoryListGenerator&, (anonymous namespace)::cmProjectDirectoryListGenerator&) Unexecuted instantiation: cmFindPackageCommand.cxx:void (anonymous namespace)::ResetGenerator<(anonymous namespace)::cmAppendPathSegmentGenerator&, (anonymous namespace)::cmProjectDirectoryListGenerator&>((anonymous namespace)::cmAppendPathSegmentGenerator&, (anonymous namespace)::cmProjectDirectoryListGenerator&) Unexecuted instantiation: cmFindPackageCommand.cxx:void (anonymous namespace)::ResetGenerator<(anonymous namespace)::cmAppendPathSegmentGenerator&, (anonymous namespace)::cmProjectDirectoryListGenerator&, (anonymous namespace)::cmAnyDirectoryListGenerator&>((anonymous namespace)::cmAppendPathSegmentGenerator&, (anonymous namespace)::cmProjectDirectoryListGenerator&, (anonymous namespace)::cmAnyDirectoryListGenerator&) Unexecuted instantiation: cmFindPackageCommand.cxx:void (anonymous namespace)::ResetGenerator<(anonymous namespace)::cmProjectDirectoryListGenerator&, (anonymous namespace)::cmCaseInsensitiveDirectoryListGenerator&>((anonymous namespace)::cmProjectDirectoryListGenerator&, (anonymous namespace)::cmCaseInsensitiveDirectoryListGenerator&) Unexecuted instantiation: cmFindPackageCommand.cxx:void (anonymous namespace)::ResetGenerator<(anonymous namespace)::cmEnumPathSegmentsGenerator&, (anonymous namespace)::cmAppendPathSegmentGenerator&, (anonymous namespace)::cmProjectDirectoryListGenerator&>((anonymous namespace)::cmEnumPathSegmentsGenerator&, (anonymous namespace)::cmAppendPathSegmentGenerator&, (anonymous namespace)::cmProjectDirectoryListGenerator&) Unexecuted instantiation: cmFindPackageCommand.cxx:void (anonymous namespace)::ResetGenerator<(anonymous namespace)::cmEnumPathSegmentsGenerator&, (anonymous namespace)::cmProjectDirectoryListGenerator&>((anonymous namespace)::cmEnumPathSegmentsGenerator&, (anonymous namespace)::cmProjectDirectoryListGenerator&) Unexecuted instantiation: cmFindPackageCommand.cxx:void (anonymous namespace)::ResetGenerator<(anonymous namespace)::cmEnumPathSegmentsGenerator&, (anonymous namespace)::cmProjectDirectoryListGenerator&, (anonymous namespace)::cmCaseInsensitiveDirectoryListGenerator&>((anonymous namespace)::cmEnumPathSegmentsGenerator&, (anonymous namespace)::cmProjectDirectoryListGenerator&, (anonymous namespace)::cmCaseInsensitiveDirectoryListGenerator&) Unexecuted instantiation: cmFindPackageCommand.cxx:void (anonymous namespace)::ResetGenerator<(anonymous namespace)::cmAppendPathSegmentGenerator&, (anonymous namespace)::cmAnyDirectoryListGenerator&, (anonymous namespace)::cmAppendPathSegmentGenerator&, (anonymous namespace)::cmCaseInsensitiveDirectoryListGenerator&>((anonymous namespace)::cmAppendPathSegmentGenerator&, (anonymous namespace)::cmAnyDirectoryListGenerator&, (anonymous namespace)::cmAppendPathSegmentGenerator&, (anonymous namespace)::cmCaseInsensitiveDirectoryListGenerator&) Unexecuted instantiation: cmFindPackageCommand.cxx:void (anonymous namespace)::ResetGenerator<(anonymous namespace)::cmAnyDirectoryListGenerator&, (anonymous namespace)::cmAppendPathSegmentGenerator&, (anonymous namespace)::cmCaseInsensitiveDirectoryListGenerator&>((anonymous namespace)::cmAnyDirectoryListGenerator&, (anonymous namespace)::cmAppendPathSegmentGenerator&, (anonymous namespace)::cmCaseInsensitiveDirectoryListGenerator&) Unexecuted instantiation: cmFindPackageCommand.cxx:void (anonymous namespace)::ResetGenerator<(anonymous namespace)::cmAppendPathSegmentGenerator&, (anonymous namespace)::cmCaseInsensitiveDirectoryListGenerator&>((anonymous namespace)::cmAppendPathSegmentGenerator&, (anonymous namespace)::cmCaseInsensitiveDirectoryListGenerator&) Unexecuted instantiation: cmFindPackageCommand.cxx:void (anonymous namespace)::ResetGenerator<(anonymous namespace)::cmAppendPathSegmentGenerator&, (anonymous namespace)::cmAnyDirectoryListGenerator&, (anonymous namespace)::cmAppendPathSegmentGenerator&>((anonymous namespace)::cmAppendPathSegmentGenerator&, (anonymous namespace)::cmAnyDirectoryListGenerator&, (anonymous namespace)::cmAppendPathSegmentGenerator&) Unexecuted instantiation: cmFindPackageCommand.cxx:void (anonymous namespace)::ResetGenerator<(anonymous namespace)::cmAnyDirectoryListGenerator&, (anonymous namespace)::cmAppendPathSegmentGenerator&>((anonymous namespace)::cmAnyDirectoryListGenerator&, (anonymous namespace)::cmAppendPathSegmentGenerator&) Unexecuted instantiation: cmFindPackageCommand.cxx:void (anonymous namespace)::ResetGenerator<(anonymous namespace)::cmAppendPathSegmentGenerator&, (anonymous namespace)::cmCaseInsensitiveDirectoryListGenerator>((anonymous namespace)::cmAppendPathSegmentGenerator&, (anonymous namespace)::cmCaseInsensitiveDirectoryListGenerator&&) |
393 | | |
394 | | template <typename CallbackFn> |
395 | | bool TryGeneratedPaths(CallbackFn&& filesCollector, |
396 | | cmFindPackageCommand::PackageDescriptionType type, |
397 | | std::string const& fullPath) |
398 | 0 | { |
399 | 0 | assert(!fullPath.empty() && fullPath.back() == '/'); |
400 | 0 | return std::forward<CallbackFn&&>(filesCollector)(fullPath, type); |
401 | 0 | } Unexecuted instantiation: cmFindPackageCommand.cxx:bool (anonymous namespace)::TryGeneratedPaths<cmFindPackageCommand::SearchPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&>(cmFindPackageCommand::SearchPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, cmFindPackageCommand::PackageDescriptionType, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) Unexecuted instantiation: cmFindPackageCommand.cxx:bool (anonymous namespace)::TryGeneratedPaths<cmFindPackageCommand::SearchFrameworkPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&>(cmFindPackageCommand::SearchFrameworkPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, cmFindPackageCommand::PackageDescriptionType, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) Unexecuted instantiation: cmFindPackageCommand.cxx:bool (anonymous namespace)::TryGeneratedPaths<cmFindPackageCommand::SearchAppBundlePrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&>(cmFindPackageCommand::SearchAppBundlePrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, cmFindPackageCommand::PackageDescriptionType, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) Unexecuted instantiation: cmFindPackageCommand.cxx:bool (anonymous namespace)::TryGeneratedPaths<cmFindPackageCommand::SearchEnvironmentPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&>(cmFindPackageCommand::SearchEnvironmentPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, cmFindPackageCommand::PackageDescriptionType, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) |
402 | | |
403 | | template <typename CallbackFn, typename Generator, typename... Rest> |
404 | | bool TryGeneratedPaths(CallbackFn&& filesCollector, |
405 | | cmFindPackageCommand::PackageDescriptionType type, |
406 | | std::string const& startPath, Generator&& gen, |
407 | | Rest&&... tail) |
408 | 0 | { |
409 | 0 | ResetGenerator(std::forward<Generator&&>(gen)); |
410 | 0 | for (auto path = gen.GetNextCandidate(startPath); !path.empty(); |
411 | 0 | path = gen.GetNextCandidate(startPath)) { |
412 | 0 | ResetGenerator(std::forward<Rest&&>(tail)...); |
413 | 0 | if (TryGeneratedPaths(std::forward<CallbackFn&&>(filesCollector), type, |
414 | 0 | path, std::forward<Rest&&>(tail)...)) { |
415 | 0 | return true; |
416 | 0 | } |
417 | 0 | } |
418 | 0 | return false; |
419 | 0 | } Unexecuted instantiation: cmFindPackageCommand.cxx:bool (anonymous namespace)::TryGeneratedPaths<cmFindPackageCommand::SearchPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, (anonymous namespace)::cmProjectDirectoryListGenerator&, (anonymous namespace)::cmCaseInsensitiveDirectoryListGenerator&>(cmFindPackageCommand::SearchPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, cmFindPackageCommand::PackageDescriptionType, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, (anonymous namespace)::cmProjectDirectoryListGenerator&, (anonymous namespace)::cmCaseInsensitiveDirectoryListGenerator&) Unexecuted instantiation: cmFindPackageCommand.cxx:bool (anonymous namespace)::TryGeneratedPaths<cmFindPackageCommand::SearchPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, (anonymous namespace)::cmProjectDirectoryListGenerator&, (anonymous namespace)::cmCaseInsensitiveDirectoryListGenerator&, (anonymous namespace)::cmAnyDirectoryListGenerator&>(cmFindPackageCommand::SearchPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, cmFindPackageCommand::PackageDescriptionType, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, (anonymous namespace)::cmProjectDirectoryListGenerator&, (anonymous namespace)::cmCaseInsensitiveDirectoryListGenerator&, (anonymous namespace)::cmAnyDirectoryListGenerator&) Unexecuted instantiation: cmFindPackageCommand.cxx:bool (anonymous namespace)::TryGeneratedPaths<cmFindPackageCommand::SearchPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, (anonymous namespace)::cmCaseInsensitiveDirectoryListGenerator&, (anonymous namespace)::cmAnyDirectoryListGenerator&>(cmFindPackageCommand::SearchPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, cmFindPackageCommand::PackageDescriptionType, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, (anonymous namespace)::cmCaseInsensitiveDirectoryListGenerator&, (anonymous namespace)::cmAnyDirectoryListGenerator&) Unexecuted instantiation: cmFindPackageCommand.cxx:bool (anonymous namespace)::TryGeneratedPaths<cmFindPackageCommand::SearchPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, (anonymous namespace)::cmAnyDirectoryListGenerator&>(cmFindPackageCommand::SearchPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, cmFindPackageCommand::PackageDescriptionType, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, (anonymous namespace)::cmAnyDirectoryListGenerator&) Unexecuted instantiation: cmFindPackageCommand.cxx:bool (anonymous namespace)::TryGeneratedPaths<cmFindPackageCommand::SearchPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, (anonymous namespace)::cmCaseInsensitiveDirectoryListGenerator&, (anonymous namespace)::cmProjectDirectoryListGenerator&>(cmFindPackageCommand::SearchPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, cmFindPackageCommand::PackageDescriptionType, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, (anonymous namespace)::cmCaseInsensitiveDirectoryListGenerator&, (anonymous namespace)::cmProjectDirectoryListGenerator&) Unexecuted instantiation: cmFindPackageCommand.cxx:bool (anonymous namespace)::TryGeneratedPaths<cmFindPackageCommand::SearchPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, (anonymous namespace)::cmCaseInsensitiveDirectoryListGenerator&, (anonymous namespace)::cmProjectDirectoryListGenerator&, (anonymous namespace)::cmAnyDirectoryListGenerator&>(cmFindPackageCommand::SearchPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, cmFindPackageCommand::PackageDescriptionType, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, (anonymous namespace)::cmCaseInsensitiveDirectoryListGenerator&, (anonymous namespace)::cmProjectDirectoryListGenerator&, (anonymous namespace)::cmAnyDirectoryListGenerator&) Unexecuted instantiation: cmFindPackageCommand.cxx:bool (anonymous namespace)::TryGeneratedPaths<cmFindPackageCommand::SearchPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, (anonymous namespace)::cmProjectDirectoryListGenerator&, (anonymous namespace)::cmAnyDirectoryListGenerator&>(cmFindPackageCommand::SearchPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, cmFindPackageCommand::PackageDescriptionType, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, (anonymous namespace)::cmProjectDirectoryListGenerator&, (anonymous namespace)::cmAnyDirectoryListGenerator&) Unexecuted instantiation: cmFindPackageCommand.cxx:bool (anonymous namespace)::TryGeneratedPaths<cmFindPackageCommand::SearchPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, (anonymous namespace)::cmCaseInsensitiveDirectoryListGenerator&>(cmFindPackageCommand::SearchPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, cmFindPackageCommand::PackageDescriptionType, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, (anonymous namespace)::cmCaseInsensitiveDirectoryListGenerator&) Unexecuted instantiation: cmFindPackageCommand.cxx:bool (anonymous namespace)::TryGeneratedPaths<cmFindPackageCommand::SearchPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, (anonymous namespace)::cmProjectDirectoryListGenerator&>(cmFindPackageCommand::SearchPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, cmFindPackageCommand::PackageDescriptionType, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, (anonymous namespace)::cmProjectDirectoryListGenerator&) Unexecuted instantiation: cmFindPackageCommand.cxx:bool (anonymous namespace)::TryGeneratedPaths<cmFindPackageCommand::SearchPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, (anonymous namespace)::cmProjectDirectoryListGenerator&, (anonymous namespace)::cmCaseInsensitiveDirectoryListGenerator&, (anonymous namespace)::cmProjectDirectoryListGenerator&>(cmFindPackageCommand::SearchPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, cmFindPackageCommand::PackageDescriptionType, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, (anonymous namespace)::cmProjectDirectoryListGenerator&, (anonymous namespace)::cmCaseInsensitiveDirectoryListGenerator&, (anonymous namespace)::cmProjectDirectoryListGenerator&) Unexecuted instantiation: cmFindPackageCommand.cxx:bool (anonymous namespace)::TryGeneratedPaths<cmFindPackageCommand::SearchPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, (anonymous namespace)::cmEnumPathSegmentsGenerator&, (anonymous namespace)::cmAppendPathSegmentGenerator&, (anonymous namespace)::cmProjectDirectoryListGenerator&>(cmFindPackageCommand::SearchPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, cmFindPackageCommand::PackageDescriptionType, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, (anonymous namespace)::cmEnumPathSegmentsGenerator&, (anonymous namespace)::cmAppendPathSegmentGenerator&, (anonymous namespace)::cmProjectDirectoryListGenerator&) Unexecuted instantiation: cmFindPackageCommand.cxx:bool (anonymous namespace)::TryGeneratedPaths<cmFindPackageCommand::SearchPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, (anonymous namespace)::cmAppendPathSegmentGenerator&, (anonymous namespace)::cmProjectDirectoryListGenerator&>(cmFindPackageCommand::SearchPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, cmFindPackageCommand::PackageDescriptionType, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, (anonymous namespace)::cmAppendPathSegmentGenerator&, (anonymous namespace)::cmProjectDirectoryListGenerator&) Unexecuted instantiation: cmFindPackageCommand.cxx:bool (anonymous namespace)::TryGeneratedPaths<cmFindPackageCommand::SearchPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, (anonymous namespace)::cmEnumPathSegmentsGenerator&, (anonymous namespace)::cmAppendPathSegmentGenerator&, (anonymous namespace)::cmProjectDirectoryListGenerator&, (anonymous namespace)::cmAnyDirectoryListGenerator&>(cmFindPackageCommand::SearchPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, cmFindPackageCommand::PackageDescriptionType, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, (anonymous namespace)::cmEnumPathSegmentsGenerator&, (anonymous namespace)::cmAppendPathSegmentGenerator&, (anonymous namespace)::cmProjectDirectoryListGenerator&, (anonymous namespace)::cmAnyDirectoryListGenerator&) Unexecuted instantiation: cmFindPackageCommand.cxx:bool (anonymous namespace)::TryGeneratedPaths<cmFindPackageCommand::SearchPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, (anonymous namespace)::cmAppendPathSegmentGenerator&, (anonymous namespace)::cmProjectDirectoryListGenerator&, (anonymous namespace)::cmAnyDirectoryListGenerator&>(cmFindPackageCommand::SearchPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, cmFindPackageCommand::PackageDescriptionType, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, (anonymous namespace)::cmAppendPathSegmentGenerator&, (anonymous namespace)::cmProjectDirectoryListGenerator&, (anonymous namespace)::cmAnyDirectoryListGenerator&) Unexecuted instantiation: cmFindPackageCommand.cxx:bool (anonymous namespace)::TryGeneratedPaths<cmFindPackageCommand::SearchPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, (anonymous namespace)::cmEnumPathSegmentsGenerator&, (anonymous namespace)::cmAppendPathSegmentGenerator&>(cmFindPackageCommand::SearchPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, cmFindPackageCommand::PackageDescriptionType, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, (anonymous namespace)::cmEnumPathSegmentsGenerator&, (anonymous namespace)::cmAppendPathSegmentGenerator&) Unexecuted instantiation: cmFindPackageCommand.cxx:bool (anonymous namespace)::TryGeneratedPaths<cmFindPackageCommand::SearchPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, (anonymous namespace)::cmAppendPathSegmentGenerator&>(cmFindPackageCommand::SearchPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, cmFindPackageCommand::PackageDescriptionType, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, (anonymous namespace)::cmAppendPathSegmentGenerator&) Unexecuted instantiation: cmFindPackageCommand.cxx:bool (anonymous namespace)::TryGeneratedPaths<cmFindPackageCommand::SearchPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, (anonymous namespace)::cmEnumPathSegmentsGenerator&, (anonymous namespace)::cmProjectDirectoryListGenerator&>(cmFindPackageCommand::SearchPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, cmFindPackageCommand::PackageDescriptionType, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, (anonymous namespace)::cmEnumPathSegmentsGenerator&, (anonymous namespace)::cmProjectDirectoryListGenerator&) Unexecuted instantiation: cmFindPackageCommand.cxx:bool (anonymous namespace)::TryGeneratedPaths<cmFindPackageCommand::SearchPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, (anonymous namespace)::cmEnumPathSegmentsGenerator&, (anonymous namespace)::cmProjectDirectoryListGenerator&, (anonymous namespace)::cmCaseInsensitiveDirectoryListGenerator&>(cmFindPackageCommand::SearchPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, cmFindPackageCommand::PackageDescriptionType, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, (anonymous namespace)::cmEnumPathSegmentsGenerator&, (anonymous namespace)::cmProjectDirectoryListGenerator&, (anonymous namespace)::cmCaseInsensitiveDirectoryListGenerator&) Unexecuted instantiation: cmFindPackageCommand.cxx:bool (anonymous namespace)::TryGeneratedPaths<cmFindPackageCommand::SearchPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, (anonymous namespace)::cmProjectDirectoryListGenerator&, (anonymous namespace)::cmEnumPathSegmentsGenerator&, (anonymous namespace)::cmAppendPathSegmentGenerator&, (anonymous namespace)::cmProjectDirectoryListGenerator&>(cmFindPackageCommand::SearchPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, cmFindPackageCommand::PackageDescriptionType, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, (anonymous namespace)::cmProjectDirectoryListGenerator&, (anonymous namespace)::cmEnumPathSegmentsGenerator&, (anonymous namespace)::cmAppendPathSegmentGenerator&, (anonymous namespace)::cmProjectDirectoryListGenerator&) Unexecuted instantiation: cmFindPackageCommand.cxx:bool (anonymous namespace)::TryGeneratedPaths<cmFindPackageCommand::SearchPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, (anonymous namespace)::cmProjectDirectoryListGenerator&, (anonymous namespace)::cmEnumPathSegmentsGenerator&, (anonymous namespace)::cmProjectDirectoryListGenerator&>(cmFindPackageCommand::SearchPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, cmFindPackageCommand::PackageDescriptionType, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, (anonymous namespace)::cmProjectDirectoryListGenerator&, (anonymous namespace)::cmEnumPathSegmentsGenerator&, (anonymous namespace)::cmProjectDirectoryListGenerator&) Unexecuted instantiation: cmFindPackageCommand.cxx:bool (anonymous namespace)::TryGeneratedPaths<cmFindPackageCommand::SearchPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, (anonymous namespace)::cmProjectDirectoryListGenerator&, (anonymous namespace)::cmEnumPathSegmentsGenerator&, (anonymous namespace)::cmProjectDirectoryListGenerator&, (anonymous namespace)::cmCaseInsensitiveDirectoryListGenerator&>(cmFindPackageCommand::SearchPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, cmFindPackageCommand::PackageDescriptionType, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, (anonymous namespace)::cmProjectDirectoryListGenerator&, (anonymous namespace)::cmEnumPathSegmentsGenerator&, (anonymous namespace)::cmProjectDirectoryListGenerator&, (anonymous namespace)::cmCaseInsensitiveDirectoryListGenerator&) Unexecuted instantiation: cmFindPackageCommand.cxx:bool (anonymous namespace)::TryGeneratedPaths<cmFindPackageCommand::SearchFrameworkPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, (anonymous namespace)::cmMacProjectDirectoryListGenerator&, (anonymous namespace)::cmAppendPathSegmentGenerator&, (anonymous namespace)::cmAnyDirectoryListGenerator&, (anonymous namespace)::cmAppendPathSegmentGenerator&, (anonymous namespace)::cmCaseInsensitiveDirectoryListGenerator&>(cmFindPackageCommand::SearchFrameworkPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, cmFindPackageCommand::PackageDescriptionType, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, (anonymous namespace)::cmMacProjectDirectoryListGenerator&, (anonymous namespace)::cmAppendPathSegmentGenerator&, (anonymous namespace)::cmAnyDirectoryListGenerator&, (anonymous namespace)::cmAppendPathSegmentGenerator&, (anonymous namespace)::cmCaseInsensitiveDirectoryListGenerator&) Unexecuted instantiation: cmFindPackageCommand.cxx:bool (anonymous namespace)::TryGeneratedPaths<cmFindPackageCommand::SearchFrameworkPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, (anonymous namespace)::cmAppendPathSegmentGenerator&, (anonymous namespace)::cmAnyDirectoryListGenerator&, (anonymous namespace)::cmAppendPathSegmentGenerator&, (anonymous namespace)::cmCaseInsensitiveDirectoryListGenerator&>(cmFindPackageCommand::SearchFrameworkPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, cmFindPackageCommand::PackageDescriptionType, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, (anonymous namespace)::cmAppendPathSegmentGenerator&, (anonymous namespace)::cmAnyDirectoryListGenerator&, (anonymous namespace)::cmAppendPathSegmentGenerator&, (anonymous namespace)::cmCaseInsensitiveDirectoryListGenerator&) Unexecuted instantiation: cmFindPackageCommand.cxx:bool (anonymous namespace)::TryGeneratedPaths<cmFindPackageCommand::SearchFrameworkPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, (anonymous namespace)::cmAnyDirectoryListGenerator&, (anonymous namespace)::cmAppendPathSegmentGenerator&, (anonymous namespace)::cmCaseInsensitiveDirectoryListGenerator&>(cmFindPackageCommand::SearchFrameworkPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, cmFindPackageCommand::PackageDescriptionType, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, (anonymous namespace)::cmAnyDirectoryListGenerator&, (anonymous namespace)::cmAppendPathSegmentGenerator&, (anonymous namespace)::cmCaseInsensitiveDirectoryListGenerator&) Unexecuted instantiation: cmFindPackageCommand.cxx:bool (anonymous namespace)::TryGeneratedPaths<cmFindPackageCommand::SearchFrameworkPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, (anonymous namespace)::cmAppendPathSegmentGenerator&, (anonymous namespace)::cmCaseInsensitiveDirectoryListGenerator&>(cmFindPackageCommand::SearchFrameworkPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, cmFindPackageCommand::PackageDescriptionType, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, (anonymous namespace)::cmAppendPathSegmentGenerator&, (anonymous namespace)::cmCaseInsensitiveDirectoryListGenerator&) Unexecuted instantiation: cmFindPackageCommand.cxx:bool (anonymous namespace)::TryGeneratedPaths<cmFindPackageCommand::SearchFrameworkPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, (anonymous namespace)::cmCaseInsensitiveDirectoryListGenerator&>(cmFindPackageCommand::SearchFrameworkPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, cmFindPackageCommand::PackageDescriptionType, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, (anonymous namespace)::cmCaseInsensitiveDirectoryListGenerator&) Unexecuted instantiation: cmFindPackageCommand.cxx:bool (anonymous namespace)::TryGeneratedPaths<cmFindPackageCommand::SearchFrameworkPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, (anonymous namespace)::cmMacProjectDirectoryListGenerator&, (anonymous namespace)::cmAppendPathSegmentGenerator&, (anonymous namespace)::cmCaseInsensitiveDirectoryListGenerator&>(cmFindPackageCommand::SearchFrameworkPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, cmFindPackageCommand::PackageDescriptionType, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, (anonymous namespace)::cmMacProjectDirectoryListGenerator&, (anonymous namespace)::cmAppendPathSegmentGenerator&, (anonymous namespace)::cmCaseInsensitiveDirectoryListGenerator&) Unexecuted instantiation: cmFindPackageCommand.cxx:bool (anonymous namespace)::TryGeneratedPaths<cmFindPackageCommand::SearchFrameworkPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, (anonymous namespace)::cmMacProjectDirectoryListGenerator&, (anonymous namespace)::cmAppendPathSegmentGenerator&>(cmFindPackageCommand::SearchFrameworkPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, cmFindPackageCommand::PackageDescriptionType, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, (anonymous namespace)::cmMacProjectDirectoryListGenerator&, (anonymous namespace)::cmAppendPathSegmentGenerator&) Unexecuted instantiation: cmFindPackageCommand.cxx:bool (anonymous namespace)::TryGeneratedPaths<cmFindPackageCommand::SearchFrameworkPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, (anonymous namespace)::cmAppendPathSegmentGenerator&>(cmFindPackageCommand::SearchFrameworkPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, cmFindPackageCommand::PackageDescriptionType, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, (anonymous namespace)::cmAppendPathSegmentGenerator&) Unexecuted instantiation: cmFindPackageCommand.cxx:bool (anonymous namespace)::TryGeneratedPaths<cmFindPackageCommand::SearchFrameworkPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, (anonymous namespace)::cmMacProjectDirectoryListGenerator&, (anonymous namespace)::cmAppendPathSegmentGenerator&, (anonymous namespace)::cmAnyDirectoryListGenerator&, (anonymous namespace)::cmAppendPathSegmentGenerator&>(cmFindPackageCommand::SearchFrameworkPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, cmFindPackageCommand::PackageDescriptionType, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, (anonymous namespace)::cmMacProjectDirectoryListGenerator&, (anonymous namespace)::cmAppendPathSegmentGenerator&, (anonymous namespace)::cmAnyDirectoryListGenerator&, (anonymous namespace)::cmAppendPathSegmentGenerator&) Unexecuted instantiation: cmFindPackageCommand.cxx:bool (anonymous namespace)::TryGeneratedPaths<cmFindPackageCommand::SearchFrameworkPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, (anonymous namespace)::cmAppendPathSegmentGenerator&, (anonymous namespace)::cmAnyDirectoryListGenerator&, (anonymous namespace)::cmAppendPathSegmentGenerator&>(cmFindPackageCommand::SearchFrameworkPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, cmFindPackageCommand::PackageDescriptionType, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, (anonymous namespace)::cmAppendPathSegmentGenerator&, (anonymous namespace)::cmAnyDirectoryListGenerator&, (anonymous namespace)::cmAppendPathSegmentGenerator&) Unexecuted instantiation: cmFindPackageCommand.cxx:bool (anonymous namespace)::TryGeneratedPaths<cmFindPackageCommand::SearchFrameworkPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, (anonymous namespace)::cmAnyDirectoryListGenerator&, (anonymous namespace)::cmAppendPathSegmentGenerator&>(cmFindPackageCommand::SearchFrameworkPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, cmFindPackageCommand::PackageDescriptionType, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, (anonymous namespace)::cmAnyDirectoryListGenerator&, (anonymous namespace)::cmAppendPathSegmentGenerator&) Unexecuted instantiation: cmFindPackageCommand.cxx:bool (anonymous namespace)::TryGeneratedPaths<cmFindPackageCommand::SearchAppBundlePrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, (anonymous namespace)::cmMacProjectDirectoryListGenerator&, (anonymous namespace)::cmAppendPathSegmentGenerator&, (anonymous namespace)::cmCaseInsensitiveDirectoryListGenerator>(cmFindPackageCommand::SearchAppBundlePrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, cmFindPackageCommand::PackageDescriptionType, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, (anonymous namespace)::cmMacProjectDirectoryListGenerator&, (anonymous namespace)::cmAppendPathSegmentGenerator&, (anonymous namespace)::cmCaseInsensitiveDirectoryListGenerator&&) Unexecuted instantiation: cmFindPackageCommand.cxx:bool (anonymous namespace)::TryGeneratedPaths<cmFindPackageCommand::SearchAppBundlePrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, (anonymous namespace)::cmAppendPathSegmentGenerator&, (anonymous namespace)::cmCaseInsensitiveDirectoryListGenerator>(cmFindPackageCommand::SearchAppBundlePrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, cmFindPackageCommand::PackageDescriptionType, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, (anonymous namespace)::cmAppendPathSegmentGenerator&, (anonymous namespace)::cmCaseInsensitiveDirectoryListGenerator&&) Unexecuted instantiation: cmFindPackageCommand.cxx:bool (anonymous namespace)::TryGeneratedPaths<cmFindPackageCommand::SearchAppBundlePrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, (anonymous namespace)::cmCaseInsensitiveDirectoryListGenerator>(cmFindPackageCommand::SearchAppBundlePrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, cmFindPackageCommand::PackageDescriptionType, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, (anonymous namespace)::cmCaseInsensitiveDirectoryListGenerator&&) Unexecuted instantiation: cmFindPackageCommand.cxx:bool (anonymous namespace)::TryGeneratedPaths<cmFindPackageCommand::SearchAppBundlePrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, (anonymous namespace)::cmMacProjectDirectoryListGenerator&, (anonymous namespace)::cmAppendPathSegmentGenerator&>(cmFindPackageCommand::SearchAppBundlePrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, cmFindPackageCommand::PackageDescriptionType, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, (anonymous namespace)::cmMacProjectDirectoryListGenerator&, (anonymous namespace)::cmAppendPathSegmentGenerator&) Unexecuted instantiation: cmFindPackageCommand.cxx:bool (anonymous namespace)::TryGeneratedPaths<cmFindPackageCommand::SearchAppBundlePrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, (anonymous namespace)::cmAppendPathSegmentGenerator&>(cmFindPackageCommand::SearchAppBundlePrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, cmFindPackageCommand::PackageDescriptionType, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, (anonymous namespace)::cmAppendPathSegmentGenerator&) Unexecuted instantiation: cmFindPackageCommand.cxx:bool (anonymous namespace)::TryGeneratedPaths<cmFindPackageCommand::SearchEnvironmentPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, (anonymous namespace)::cmProjectDirectoryListGenerator&, (anonymous namespace)::cmAppendPathSegmentGenerator>(cmFindPackageCommand::SearchEnvironmentPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, cmFindPackageCommand::PackageDescriptionType, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, (anonymous namespace)::cmProjectDirectoryListGenerator&, (anonymous namespace)::cmAppendPathSegmentGenerator&&) Unexecuted instantiation: cmFindPackageCommand.cxx:bool (anonymous namespace)::TryGeneratedPaths<cmFindPackageCommand::SearchEnvironmentPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, (anonymous namespace)::cmAppendPathSegmentGenerator>(cmFindPackageCommand::SearchEnvironmentPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, cmFindPackageCommand::PackageDescriptionType, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, (anonymous namespace)::cmAppendPathSegmentGenerator&&) Unexecuted instantiation: cmFindPackageCommand.cxx:bool (anonymous namespace)::TryGeneratedPaths<cmFindPackageCommand::SearchEnvironmentPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, (anonymous namespace)::cmProjectDirectoryListGenerator&>(cmFindPackageCommand::SearchEnvironmentPrefix(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0&, cmFindPackageCommand::PackageDescriptionType, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, (anonymous namespace)::cmProjectDirectoryListGenerator&) |
420 | | |
421 | | #ifdef CM_LCC_DIAG_SUPPRESS_3308 |
422 | | # undef CM_LCC_DIAG_SUPPRESS_3308 |
423 | | # pragma diag_default 3308 |
424 | | #endif |
425 | | |
426 | | #ifdef CM_LCC_DIAG_SUPPRESS_3301 |
427 | | # undef CM_LCC_DIAG_SUPPRESS_3301 |
428 | | # pragma diag_default 3301 |
429 | | #endif |
430 | | |
431 | | #ifdef CM_LCC_DIAG_SUPPRESS_3288 |
432 | | # undef CM_LCC_DIAG_SUPPRESS_3288 |
433 | | # pragma diag_default 3288 |
434 | | #endif |
435 | | |
436 | | #ifdef CM_LCC_DIAG_SUPPRESS_1222 |
437 | | # undef CM_LCC_DIAG_SUPPRESS_1222 |
438 | | # pragma diag_default 1222 |
439 | | #endif |
440 | | |
441 | | // Parse the version number and store the results that were |
442 | | // successfully parsed. |
443 | | unsigned int parseVersion(std::string const& version, unsigned int& major, |
444 | | unsigned int& minor, unsigned int& patch, |
445 | | unsigned int& tweak) |
446 | 0 | { |
447 | 0 | return static_cast<unsigned int>(std::sscanf( |
448 | 0 | version.c_str(), "%u.%u.%u.%u", &major, &minor, &patch, &tweak)); |
449 | 0 | } |
450 | | |
451 | | } // anonymous namespace |
452 | | |
453 | | class cmFindPackageCommand::FlushDebugBufferOnExit |
454 | | { |
455 | | cmFindPackageCommand& Command; |
456 | | |
457 | | public: |
458 | | FlushDebugBufferOnExit(cmFindPackageCommand& command) |
459 | 0 | : Command(command) |
460 | 0 | { |
461 | 0 | } |
462 | | ~FlushDebugBufferOnExit() |
463 | 0 | { |
464 | 0 | if (!Command.DebugBuffer.empty()) { |
465 | 0 | Command.DebugMessage(Command.DebugBuffer); |
466 | 0 | } |
467 | 0 | } |
468 | | }; |
469 | | |
470 | | class cmFindPackageCommand::PushPopRootPathStack |
471 | | { |
472 | | cmFindPackageCommand& Command; |
473 | | |
474 | | public: |
475 | | PushPopRootPathStack(cmFindPackageCommand& command) |
476 | 0 | : Command(command) |
477 | 0 | { |
478 | 0 | Command.PushFindPackageRootPathStack(); |
479 | 0 | } |
480 | 0 | ~PushPopRootPathStack() { Command.PopFindPackageRootPathStack(); } |
481 | | }; |
482 | | |
483 | | class cmFindPackageCommand::SetRestoreFindDefinitions |
484 | | { |
485 | | cmFindPackageCommand& Command; |
486 | | |
487 | | public: |
488 | | SetRestoreFindDefinitions(cmFindPackageCommand& command) |
489 | 0 | : Command(command) |
490 | 0 | { |
491 | 0 | Command.SetModuleVariables(); |
492 | 0 | } |
493 | 0 | ~SetRestoreFindDefinitions() { Command.RestoreFindDefinitions(); } |
494 | | }; |
495 | | |
496 | | cmFindPackageCommand::PathLabel |
497 | | cmFindPackageCommand::PathLabel::PackageRedirect("PACKAGE_REDIRECT"); |
498 | | cmFindPackageCommand::PathLabel cmFindPackageCommand::PathLabel::UserRegistry( |
499 | | "PACKAGE_REGISTRY"); |
500 | | cmFindPackageCommand::PathLabel cmFindPackageCommand::PathLabel::Builds( |
501 | | "BUILDS"); |
502 | | cmFindPackageCommand::PathLabel |
503 | | cmFindPackageCommand::PathLabel::SystemRegistry("SYSTEM_PACKAGE_REGISTRY"); |
504 | | |
505 | | cm::string_view const cmFindPackageCommand::VERSION_ENDPOINT_INCLUDED( |
506 | | "INCLUDE"); |
507 | | cm::string_view const cmFindPackageCommand::VERSION_ENDPOINT_EXCLUDED( |
508 | | "EXCLUDE"); |
509 | | |
510 | | void cmFindPackageCommand::Sort(std::vector<std::string>::iterator begin, |
511 | | std::vector<std::string>::iterator end, |
512 | | SortOrderType const order, |
513 | | SortDirectionType const dir) |
514 | 0 | { |
515 | 0 | if (order == Name_order) { |
516 | 0 | if (dir == Dec) { |
517 | 0 | std::sort(begin, end, std::greater<std::string>()); |
518 | 0 | } else { |
519 | 0 | std::sort(begin, end); |
520 | 0 | } |
521 | 0 | } else if (order == Natural) { |
522 | | // natural order uses letters and numbers (contiguous numbers digit are |
523 | | // compared such that e.g. 000 00 < 01 < 010 < 09 < 0 < 1 < 9 < 10 |
524 | 0 | if (dir == Dec) { |
525 | 0 | std::sort(begin, end, StrverscmpOp<std::greater>()); |
526 | 0 | } else { |
527 | 0 | std::sort(begin, end, StrverscmpOp<std::less>()); |
528 | 0 | } |
529 | 0 | } |
530 | | // else do not sort |
531 | 0 | } |
532 | | |
533 | | cmFindPackageCommand::cmFindPackageCommand(cmExecutionStatus& status) |
534 | 0 | : cmFindCommon(status) |
535 | 0 | , VersionRangeMin(VERSION_ENDPOINT_INCLUDED) |
536 | 0 | , VersionRangeMax(VERSION_ENDPOINT_INCLUDED) |
537 | 0 | { |
538 | 0 | this->CMakePathName = "PACKAGE"; |
539 | 0 | this->AppendSearchPathGroups(); |
540 | |
|
541 | 0 | this->DeprecatedFindModules["Boost"] = cmPolicies::CMP0167; |
542 | 0 | this->DeprecatedFindModules["CABLE"] = cmPolicies::CMP0191; |
543 | 0 | this->DeprecatedFindModules["CUDA"] = cmPolicies::CMP0146; |
544 | 0 | this->DeprecatedFindModules["Dart"] = cmPolicies::CMP0145; |
545 | 0 | this->DeprecatedFindModules["GCCXML"] = cmPolicies::CMP0188; |
546 | 0 | this->DeprecatedFindModules["PythonInterp"] = cmPolicies::CMP0148; |
547 | 0 | this->DeprecatedFindModules["PythonLibs"] = cmPolicies::CMP0148; |
548 | 0 | this->DeprecatedFindModules["Qt"] = cmPolicies::CMP0084; |
549 | 0 | } |
550 | | |
551 | | cmFindPackageCommand::~cmFindPackageCommand() |
552 | 0 | { |
553 | 0 | if (this->DebugState) { |
554 | 0 | this->DebugState->Write(); |
555 | 0 | } |
556 | 0 | } |
557 | | |
558 | | void cmFindPackageCommand::AppendSearchPathGroups() |
559 | 0 | { |
560 | | // Update the All group with new paths. Note that package redirection must |
561 | | // take precedence over everything else, so it has to be first in the array. |
562 | 0 | std::vector<cmFindCommon::PathLabel>* const labels = |
563 | 0 | &this->PathGroupLabelMap[PathGroup::All]; |
564 | 0 | labels->insert(labels->begin(), PathLabel::PackageRedirect); |
565 | 0 | labels->insert( |
566 | 0 | std::find(labels->begin(), labels->end(), PathLabel::CMakeSystem), |
567 | 0 | PathLabel::UserRegistry); |
568 | 0 | labels->insert( |
569 | 0 | std::find(labels->begin(), labels->end(), PathLabel::CMakeSystem), |
570 | 0 | PathLabel::Builds); |
571 | 0 | labels->insert(std::find(labels->begin(), labels->end(), PathLabel::Guess), |
572 | 0 | PathLabel::SystemRegistry); |
573 | | |
574 | | // Create the new path objects |
575 | 0 | this->LabeledPaths.emplace(PathLabel::PackageRedirect, cmSearchPath{ this }); |
576 | 0 | this->LabeledPaths.emplace(PathLabel::UserRegistry, cmSearchPath{ this }); |
577 | 0 | this->LabeledPaths.emplace(PathLabel::Builds, cmSearchPath{ this }); |
578 | 0 | this->LabeledPaths.emplace(PathLabel::SystemRegistry, cmSearchPath{ this }); |
579 | 0 | } |
580 | | |
581 | | void cmFindPackageCommand::InheritOptions(cmFindPackageCommand* other) |
582 | 0 | { |
583 | 0 | this->RequiredCMakeVersion = other->RequiredCMakeVersion; |
584 | 0 | this->LibraryArchitecture = other->LibraryArchitecture; |
585 | 0 | this->UseLib32Paths = other->UseLib32Paths; |
586 | 0 | this->UseLib64Paths = other->UseLib64Paths; |
587 | 0 | this->UseLibx32Paths = other->UseLibx32Paths; |
588 | 0 | this->NoUserRegistry = other->NoUserRegistry; |
589 | 0 | this->NoSystemRegistry = other->NoSystemRegistry; |
590 | 0 | this->UseRealPath = other->UseRealPath; |
591 | 0 | this->SortOrder = other->SortOrder; |
592 | 0 | this->SortDirection = other->SortDirection; |
593 | |
|
594 | 0 | this->GlobalScope = other->GlobalScope; |
595 | 0 | this->RegistryView = other->RegistryView; |
596 | 0 | this->NoDefaultPath = other->NoDefaultPath; |
597 | 0 | this->NoPackageRootPath = other->NoPackageRootPath; |
598 | 0 | this->NoCMakePath = other->NoCMakePath; |
599 | 0 | this->NoCMakeEnvironmentPath = other->NoCMakeEnvironmentPath; |
600 | 0 | this->NoSystemEnvironmentPath = other->NoSystemEnvironmentPath; |
601 | 0 | this->NoCMakeSystemPath = other->NoCMakeSystemPath; |
602 | 0 | this->NoCMakeInstallPath = other->NoCMakeInstallPath; |
603 | 0 | this->FindRootPathMode = other->FindRootPathMode; |
604 | |
|
605 | 0 | this->SearchFrameworkLast = other->SearchFrameworkLast; |
606 | 0 | this->SearchFrameworkFirst = other->SearchFrameworkFirst; |
607 | 0 | this->SearchFrameworkOnly = other->SearchFrameworkOnly; |
608 | 0 | this->SearchAppBundleLast = other->SearchAppBundleLast; |
609 | 0 | this->SearchAppBundleFirst = other->SearchAppBundleFirst; |
610 | 0 | this->SearchAppBundleOnly = other->SearchAppBundleOnly; |
611 | 0 | this->SearchPathSuffixes = other->SearchPathSuffixes; |
612 | |
|
613 | 0 | this->Quiet = other->Quiet; |
614 | 0 | } |
615 | | |
616 | | bool cmFindPackageCommand::IsFound() const |
617 | 0 | { |
618 | 0 | return this->InitialState == FindState::Found; |
619 | 0 | } |
620 | | |
621 | | bool cmFindPackageCommand::IsDefined() const |
622 | 0 | { |
623 | 0 | return this->InitialState == FindState::Found || |
624 | 0 | this->InitialState == FindState::NotFound; |
625 | 0 | } |
626 | | |
627 | | bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args) |
628 | 0 | { |
629 | 0 | if (args.empty()) { |
630 | 0 | this->SetError("called with incorrect number of arguments"); |
631 | 0 | return false; |
632 | 0 | } |
633 | | |
634 | 0 | if (this->Makefile->GetStateSnapshot().GetUnwindState() == |
635 | 0 | cmStateEnums::UNWINDING) { |
636 | 0 | this->SetError("called while already in an UNWIND state"); |
637 | 0 | return false; |
638 | 0 | } |
639 | | |
640 | | // Lookup required version of CMake. |
641 | 0 | if (cmValue const rv = |
642 | 0 | this->Makefile->GetDefinition("CMAKE_MINIMUM_REQUIRED_VERSION")) { |
643 | 0 | unsigned int v[3] = { 0, 0, 0 }; |
644 | 0 | std::sscanf(rv->c_str(), "%u.%u.%u", &v[0], &v[1], &v[2]); |
645 | 0 | this->RequiredCMakeVersion = CMake_VERSION_ENCODE(v[0], v[1], v[2]); |
646 | 0 | } |
647 | | |
648 | | // Lookup target architecture, if any. |
649 | 0 | if (cmValue const arch = |
650 | 0 | this->Makefile->GetDefinition("CMAKE_LIBRARY_ARCHITECTURE")) { |
651 | 0 | this->LibraryArchitecture = *arch; |
652 | 0 | } |
653 | | |
654 | | // Lookup whether lib32 paths should be used. |
655 | 0 | if (this->Makefile->PlatformIs32Bit() && |
656 | 0 | this->Makefile->GetState()->GetGlobalPropertyAsBool( |
657 | 0 | "FIND_LIBRARY_USE_LIB32_PATHS")) { |
658 | 0 | this->UseLib32Paths = true; |
659 | 0 | } |
660 | | |
661 | | // Lookup whether lib64 paths should be used. |
662 | 0 | if (this->Makefile->PlatformIs64Bit() && |
663 | 0 | this->Makefile->GetState()->GetGlobalPropertyAsBool( |
664 | 0 | "FIND_LIBRARY_USE_LIB64_PATHS")) { |
665 | 0 | this->UseLib64Paths = true; |
666 | 0 | } |
667 | | |
668 | | // Lookup whether libx32 paths should be used. |
669 | 0 | if (this->Makefile->PlatformIsx32() && |
670 | 0 | this->Makefile->GetState()->GetGlobalPropertyAsBool( |
671 | 0 | "FIND_LIBRARY_USE_LIBX32_PATHS")) { |
672 | 0 | this->UseLibx32Paths = true; |
673 | 0 | } |
674 | | |
675 | | // Check if User Package Registry should be disabled |
676 | | // The `CMAKE_FIND_USE_PACKAGE_REGISTRY` has |
677 | | // priority over the deprecated CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY |
678 | 0 | if (cmValue const def = |
679 | 0 | this->Makefile->GetDefinition("CMAKE_FIND_USE_PACKAGE_REGISTRY")) { |
680 | 0 | this->NoUserRegistry = !def.IsOn(); |
681 | 0 | } else if (this->Makefile->IsOn("CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY")) { |
682 | 0 | this->NoUserRegistry = true; |
683 | 0 | } |
684 | | |
685 | | // Check if System Package Registry should be disabled |
686 | | // The `CMAKE_FIND_USE_SYSTEM_PACKAGE_REGISTRY` has |
687 | | // priority over the deprecated CMAKE_FIND_PACKAGE_NO_SYSTEM_PACKAGE_REGISTRY |
688 | 0 | if (cmValue const def = this->Makefile->GetDefinition( |
689 | 0 | "CMAKE_FIND_USE_SYSTEM_PACKAGE_REGISTRY")) { |
690 | 0 | this->NoSystemRegistry = !def.IsOn(); |
691 | 0 | } else if (this->Makefile->IsOn( |
692 | 0 | "CMAKE_FIND_PACKAGE_NO_SYSTEM_PACKAGE_REGISTRY")) { |
693 | 0 | this->NoSystemRegistry = true; |
694 | 0 | } |
695 | | |
696 | | // Check whether we should resolve symlinks when finding packages |
697 | 0 | if (this->Makefile->IsOn("CMAKE_FIND_PACKAGE_RESOLVE_SYMLINKS")) { |
698 | 0 | this->UseRealPath = true; |
699 | 0 | } |
700 | | |
701 | | // Check if Sorting should be enabled |
702 | 0 | if (cmValue const so = |
703 | 0 | this->Makefile->GetDefinition("CMAKE_FIND_PACKAGE_SORT_ORDER")) { |
704 | |
|
705 | 0 | if (*so == "NAME") { |
706 | 0 | this->SortOrder = Name_order; |
707 | 0 | } else if (*so == "NATURAL") { |
708 | 0 | this->SortOrder = Natural; |
709 | 0 | } else { |
710 | 0 | this->SortOrder = None; |
711 | 0 | } |
712 | 0 | } |
713 | 0 | if (cmValue const sd = |
714 | 0 | this->Makefile->GetDefinition("CMAKE_FIND_PACKAGE_SORT_DIRECTION")) { |
715 | 0 | this->SortDirection = (*sd == "DEC") ? Dec : Asc; |
716 | 0 | } |
717 | | |
718 | | // Find what search path locations have been enabled/disable. |
719 | 0 | this->SelectDefaultSearchModes(); |
720 | | |
721 | | // Find the current root path mode. |
722 | 0 | this->SelectDefaultRootPathMode(); |
723 | | |
724 | | // Find the current bundle/framework search policy. |
725 | 0 | this->SelectDefaultMacMode(); |
726 | | |
727 | | // Record options. |
728 | 0 | this->Name = args[0]; |
729 | 0 | cm::string_view componentsSep = ""_s; |
730 | | |
731 | | // Always search directly in a generated path. |
732 | 0 | this->SearchPathSuffixes.emplace_back(); |
733 | | |
734 | | // Process debug mode |
735 | 0 | cmMakefile::DebugFindPkgRAII debugFindPkgRAII(this->Makefile, this->Name); |
736 | 0 | this->FullDebugMode = this->ComputeIfDebugModeWanted(); |
737 | 0 | if (this->FullDebugMode || !this->ComputeIfImplicitDebugModeSuppressed()) { |
738 | 0 | this->DebugState = cm::make_unique<cmFindPackageDebugState>(this); |
739 | 0 | } |
740 | | |
741 | | // Parse the arguments. |
742 | 0 | enum Doing |
743 | 0 | { |
744 | 0 | DoingNone, |
745 | 0 | DoingComponents, |
746 | 0 | DoingOptionalComponents, |
747 | 0 | DoingNames, |
748 | 0 | DoingPaths, |
749 | 0 | DoingPathSuffixes, |
750 | 0 | DoingConfigs, |
751 | 0 | DoingHints |
752 | 0 | }; |
753 | 0 | Doing doing = DoingNone; |
754 | 0 | cmsys::RegularExpression versionRegex( |
755 | 0 | R"V(^([0-9]+(\.[0-9]+)*)(\.\.\.(<?)([0-9]+(\.[0-9]+)*))?$)V"); |
756 | 0 | bool haveVersion = false; |
757 | 0 | std::vector<std::size_t> configArgs; |
758 | 0 | std::vector<std::size_t> moduleArgs; |
759 | 0 | for (std::size_t i = 1u; i < args.size(); ++i) { |
760 | 0 | if (args[i] == "QUIET") { |
761 | 0 | this->Quiet = true; |
762 | 0 | doing = DoingNone; |
763 | 0 | } else if (args[i] == "BYPASS_PROVIDER") { |
764 | 0 | this->BypassProvider = true; |
765 | 0 | doing = DoingNone; |
766 | 0 | } else if (args[i] == "EXACT") { |
767 | 0 | this->VersionExact = true; |
768 | 0 | doing = DoingNone; |
769 | 0 | } else if (args[i] == "GLOBAL") { |
770 | 0 | this->GlobalScope = true; |
771 | 0 | doing = DoingNone; |
772 | 0 | } else if (args[i] == "MODULE") { |
773 | 0 | moduleArgs.push_back(i); |
774 | 0 | doing = DoingNone; |
775 | | // XXX(clang-tidy): https://bugs.llvm.org/show_bug.cgi?id=44165 |
776 | | // NOLINTNEXTLINE(bugprone-branch-clone) |
777 | 0 | } else if (args[i] == "CONFIG") { |
778 | 0 | configArgs.push_back(i); |
779 | 0 | doing = DoingNone; |
780 | | // XXX(clang-tidy): https://bugs.llvm.org/show_bug.cgi?id=44165 |
781 | | // NOLINTNEXTLINE(bugprone-branch-clone) |
782 | 0 | } else if (args[i] == "NO_MODULE") { |
783 | 0 | configArgs.push_back(i); |
784 | 0 | doing = DoingNone; |
785 | 0 | } else if (args[i] == "REQUIRED") { |
786 | 0 | if (this->Required == RequiredStatus::OptionalExplicit) { |
787 | 0 | this->SetError("cannot be both REQUIRED and OPTIONAL"); |
788 | 0 | return false; |
789 | 0 | } |
790 | 0 | this->Required = RequiredStatus::RequiredExplicit; |
791 | 0 | doing = DoingComponents; |
792 | 0 | } else if (args[i] == "OPTIONAL") { |
793 | 0 | if (this->Required == RequiredStatus::RequiredExplicit) { |
794 | 0 | this->SetError("cannot be both REQUIRED and OPTIONAL"); |
795 | 0 | return false; |
796 | 0 | } |
797 | 0 | this->Required = RequiredStatus::OptionalExplicit; |
798 | 0 | doing = DoingComponents; |
799 | 0 | } else if (args[i] == "COMPONENTS") { |
800 | 0 | doing = DoingComponents; |
801 | 0 | } else if (args[i] == "OPTIONAL_COMPONENTS") { |
802 | 0 | doing = DoingOptionalComponents; |
803 | 0 | } else if (args[i] == "NAMES") { |
804 | 0 | configArgs.push_back(i); |
805 | 0 | doing = DoingNames; |
806 | 0 | } else if (args[i] == "PATHS") { |
807 | 0 | configArgs.push_back(i); |
808 | 0 | doing = DoingPaths; |
809 | 0 | } else if (args[i] == "HINTS") { |
810 | 0 | configArgs.push_back(i); |
811 | 0 | doing = DoingHints; |
812 | 0 | } else if (args[i] == "PATH_SUFFIXES") { |
813 | 0 | configArgs.push_back(i); |
814 | 0 | doing = DoingPathSuffixes; |
815 | 0 | } else if (args[i] == "CONFIGS") { |
816 | 0 | configArgs.push_back(i); |
817 | 0 | doing = DoingConfigs; |
818 | 0 | } else if (args[i] == "NO_POLICY_SCOPE") { |
819 | 0 | this->PolicyScope = false; |
820 | 0 | doing = DoingNone; |
821 | 0 | } else if (args[i] == "NO_CMAKE_PACKAGE_REGISTRY") { |
822 | 0 | this->NoUserRegistry = true; |
823 | 0 | configArgs.push_back(i); |
824 | 0 | doing = DoingNone; |
825 | 0 | } else if (args[i] == "NO_CMAKE_SYSTEM_PACKAGE_REGISTRY") { |
826 | 0 | this->NoSystemRegistry = true; |
827 | 0 | configArgs.push_back(i); |
828 | 0 | doing = DoingNone; |
829 | | // XXX(clang-tidy): https://bugs.llvm.org/show_bug.cgi?id=44165 |
830 | | // NOLINTNEXTLINE(bugprone-branch-clone) |
831 | 0 | } else if (args[i] == "NO_CMAKE_BUILDS_PATH") { |
832 | | // Ignore legacy option. |
833 | 0 | configArgs.push_back(i); |
834 | 0 | doing = DoingNone; |
835 | 0 | } else if (args[i] == "REGISTRY_VIEW") { |
836 | 0 | if (++i == args.size()) { |
837 | 0 | this->SetError("missing required argument for REGISTRY_VIEW"); |
838 | 0 | return false; |
839 | 0 | } |
840 | 0 | auto view = cmWindowsRegistry::ToView(args[i]); |
841 | 0 | if (view) { |
842 | 0 | this->RegistryView = *view; |
843 | 0 | this->RegistryViewDefined = true; |
844 | 0 | } else { |
845 | 0 | this->SetError( |
846 | 0 | cmStrCat("given invalid value for REGISTRY_VIEW: ", args[i])); |
847 | 0 | return false; |
848 | 0 | } |
849 | 0 | } else if (args[i] == "UNWIND_INCLUDE") { |
850 | 0 | if (this->Makefile->GetStateSnapshot().GetUnwindType() != |
851 | 0 | cmStateEnums::CAN_UNWIND) { |
852 | 0 | this->SetError("called with UNWIND_INCLUDE in an invalid context"); |
853 | 0 | return false; |
854 | 0 | } |
855 | 0 | this->ScopeUnwind = true; |
856 | 0 | doing = DoingNone; |
857 | 0 | } else if (this->CheckCommonArgument(args[i])) { |
858 | 0 | configArgs.push_back(i); |
859 | 0 | doing = DoingNone; |
860 | 0 | } else if ((doing == DoingComponents) || |
861 | 0 | (doing == DoingOptionalComponents)) { |
862 | | // Set a variable telling the find script whether this component |
863 | | // is required. |
864 | 0 | if (doing == DoingOptionalComponents) { |
865 | 0 | this->OptionalComponents.insert(args[i]); |
866 | 0 | } else { |
867 | 0 | this->RequiredComponents.insert(args[i]); |
868 | 0 | } |
869 | | |
870 | | // Append to the list of required components. |
871 | 0 | this->Components += componentsSep; |
872 | 0 | this->Components += args[i]; |
873 | 0 | componentsSep = ";"_s; |
874 | 0 | } else if (doing == DoingNames) { |
875 | 0 | this->Names.push_back(args[i]); |
876 | 0 | } else if (doing == DoingPaths) { |
877 | 0 | this->UserGuessArgs.push_back(args[i]); |
878 | 0 | } else if (doing == DoingHints) { |
879 | 0 | this->UserHintsArgs.push_back(args[i]); |
880 | 0 | } else if (doing == DoingPathSuffixes) { |
881 | 0 | this->AddPathSuffix(args[i]); |
882 | 0 | } else if (doing == DoingConfigs) { |
883 | 0 | if (args[i].find_first_of(":/\\") != std::string::npos || |
884 | 0 | !cmHasSuffix(args[i], ".cmake"_s)) { |
885 | 0 | this->SetError(cmStrCat( |
886 | 0 | "given CONFIGS option followed by invalid file name \"", args[i], |
887 | 0 | "\". The names given must be file names without " |
888 | 0 | "a path and with a \".cmake\" extension.")); |
889 | 0 | return false; |
890 | 0 | } |
891 | 0 | this->Configs.emplace_back(args[i], pdt::CMake); |
892 | 0 | } else if (!haveVersion && versionRegex.find(args[i])) { |
893 | 0 | haveVersion = true; |
894 | 0 | this->VersionComplete = args[i]; |
895 | 0 | } else { |
896 | 0 | this->SetError( |
897 | 0 | cmStrCat("called with invalid argument \"", args[i], '"')); |
898 | 0 | return false; |
899 | 0 | } |
900 | 0 | } |
901 | | |
902 | 0 | if (this->Required == RequiredStatus::Optional && |
903 | 0 | this->Makefile->IsOn("CMAKE_FIND_REQUIRED")) { |
904 | 0 | this->Required = RequiredStatus::RequiredFromFindVar; |
905 | 0 | } |
906 | |
|
907 | 0 | if (!this->GlobalScope) { |
908 | 0 | cmValue value( |
909 | 0 | this->Makefile->GetDefinition("CMAKE_FIND_PACKAGE_TARGETS_GLOBAL")); |
910 | 0 | this->GlobalScope = value.IsOn(); |
911 | 0 | } |
912 | |
|
913 | 0 | std::vector<std::string> doubledComponents; |
914 | 0 | std::set_intersection( |
915 | 0 | this->RequiredComponents.begin(), this->RequiredComponents.end(), |
916 | 0 | this->OptionalComponents.begin(), this->OptionalComponents.end(), |
917 | 0 | std::back_inserter(doubledComponents)); |
918 | 0 | if (!doubledComponents.empty()) { |
919 | 0 | this->SetError( |
920 | 0 | cmStrCat("called with components that are both required and " |
921 | 0 | "optional:\n", |
922 | 0 | cmWrap(" ", doubledComponents, "", "\n"), '\n')); |
923 | 0 | return false; |
924 | 0 | } |
925 | | |
926 | | // Check and eliminate search modes not allowed by the args provided |
927 | 0 | this->UseFindModules = configArgs.empty(); |
928 | 0 | this->UseConfigFiles = moduleArgs.empty(); |
929 | 0 | if (this->UseConfigFiles && |
930 | 0 | cmExperimental::HasSupportEnabled( |
931 | 0 | *this->Makefile, cmExperimental::Feature::ImportPackageInfo)) { |
932 | 0 | this->UseCpsFiles = this->Configs.empty(); |
933 | 0 | } else { |
934 | 0 | this->UseCpsFiles = false; |
935 | 0 | } |
936 | 0 | if (!this->UseFindModules && !this->UseConfigFiles) { |
937 | 0 | std::ostringstream e; |
938 | 0 | e << "given options exclusive to Module mode:\n"; |
939 | 0 | for (auto si : moduleArgs) { |
940 | 0 | e << " " << args[si] << "\n"; |
941 | 0 | } |
942 | 0 | e << "and options exclusive to Config mode:\n"; |
943 | 0 | for (auto si : configArgs) { |
944 | 0 | e << " " << args[si] << "\n"; |
945 | 0 | } |
946 | 0 | e << "The options are incompatible."; |
947 | 0 | this->SetError(e.str()); |
948 | 0 | return false; |
949 | 0 | } |
950 | | |
951 | 0 | bool canBeIrrelevant = true; |
952 | 0 | if (this->UseConfigFiles || this->UseCpsFiles) { |
953 | 0 | canBeIrrelevant = false; |
954 | 0 | if (cmValue v = this->Makefile->GetState()->GetCacheEntryValue( |
955 | 0 | cmStrCat(this->Name, "_DIR"))) { |
956 | 0 | if (!v.IsNOTFOUND()) { |
957 | 0 | this->InitialState = FindState::Found; |
958 | 0 | } else { |
959 | 0 | this->InitialState = FindState::NotFound; |
960 | 0 | } |
961 | 0 | } |
962 | 0 | } |
963 | |
|
964 | 0 | if (this->UseFindModules && |
965 | 0 | (this->InitialState == FindState::Undefined || |
966 | 0 | this->InitialState == FindState::NotFound)) { |
967 | | // There are no definitive cache variables to know if a given `Find` module |
968 | | // has been searched for or not. However, if we have a `_FOUND` variable, |
969 | | // use that as an indication of a previous search. |
970 | 0 | if (cmValue v = |
971 | 0 | this->Makefile->GetDefinition(cmStrCat(this->Name, "_FOUND"))) { |
972 | 0 | if (v.IsOn()) { |
973 | 0 | this->InitialState = FindState::Found; |
974 | 0 | } else { |
975 | 0 | this->InitialState = FindState::NotFound; |
976 | 0 | } |
977 | 0 | } |
978 | 0 | } |
979 | | |
980 | | // If there is no signaling variable and there's no reason to expect a cache |
981 | | // variable, mark the initial state as "irrelevant". |
982 | 0 | if (this->InitialState == FindState::Undefined && canBeIrrelevant) { |
983 | 0 | this->InitialState = FindState::Irrelevant; |
984 | 0 | } |
985 | | |
986 | | // Ignore EXACT with no version. |
987 | 0 | if (this->VersionComplete.empty() && this->VersionExact) { |
988 | 0 | this->VersionExact = false; |
989 | 0 | this->Makefile->IssueMessage( |
990 | 0 | MessageType::AUTHOR_WARNING, |
991 | 0 | "Ignoring EXACT since no version is requested."); |
992 | 0 | } |
993 | |
|
994 | 0 | if (this->VersionComplete.empty() || this->Components.empty()) { |
995 | | // Check whether we are recursing inside "Find<name>.cmake" within |
996 | | // another find_package(<name>) call. |
997 | 0 | std::string const mod = cmStrCat(this->Name, "_FIND_MODULE"); |
998 | 0 | if (this->Makefile->IsOn(mod)) { |
999 | 0 | if (this->VersionComplete.empty()) { |
1000 | | // Get version information from the outer call if necessary. |
1001 | | // Requested version string. |
1002 | 0 | std::string const ver = cmStrCat(this->Name, "_FIND_VERSION_COMPLETE"); |
1003 | 0 | this->VersionComplete = this->Makefile->GetSafeDefinition(ver); |
1004 | | |
1005 | | // Whether an exact version is required. |
1006 | 0 | std::string const exact = cmStrCat(this->Name, "_FIND_VERSION_EXACT"); |
1007 | 0 | this->VersionExact = this->Makefile->IsOn(exact); |
1008 | 0 | } |
1009 | 0 | if (this->Components.empty()) { |
1010 | 0 | std::string const componentsVar = this->Name + "_FIND_COMPONENTS"; |
1011 | 0 | this->Components = this->Makefile->GetSafeDefinition(componentsVar); |
1012 | 0 | for (auto const& component : cmList{ this->Components }) { |
1013 | 0 | std::string const crVar = |
1014 | 0 | cmStrCat(this->Name, "_FIND_REQUIRED_"_s, component); |
1015 | 0 | if (this->Makefile->GetDefinition(crVar).IsOn()) { |
1016 | 0 | this->RequiredComponents.insert(component); |
1017 | 0 | } else { |
1018 | 0 | this->OptionalComponents.insert(component); |
1019 | 0 | } |
1020 | 0 | } |
1021 | 0 | } |
1022 | 0 | } |
1023 | 0 | } |
1024 | | |
1025 | | // fill various parts of version specification |
1026 | 0 | if (!this->VersionComplete.empty()) { |
1027 | 0 | if (!versionRegex.find(this->VersionComplete)) { |
1028 | 0 | this->SetError("called with invalid version specification."); |
1029 | 0 | return false; |
1030 | 0 | } |
1031 | | |
1032 | 0 | this->Version = versionRegex.match(1); |
1033 | 0 | this->VersionMax = versionRegex.match(5); |
1034 | 0 | if (versionRegex.match(4) == "<"_s) { |
1035 | 0 | this->VersionRangeMax = VERSION_ENDPOINT_EXCLUDED; |
1036 | 0 | } |
1037 | 0 | if (!this->VersionMax.empty()) { |
1038 | 0 | this->VersionRange = this->VersionComplete; |
1039 | 0 | } |
1040 | 0 | } |
1041 | | |
1042 | 0 | if (!this->VersionRange.empty()) { |
1043 | | // version range must not be empty |
1044 | 0 | if ((this->VersionRangeMax == VERSION_ENDPOINT_INCLUDED && |
1045 | 0 | cmSystemTools::VersionCompareGreater(this->Version, |
1046 | 0 | this->VersionMax)) || |
1047 | 0 | (this->VersionRangeMax == VERSION_ENDPOINT_EXCLUDED && |
1048 | 0 | cmSystemTools::VersionCompareGreaterEq(this->Version, |
1049 | 0 | this->VersionMax))) { |
1050 | 0 | this->SetError("specified version range is empty."); |
1051 | 0 | return false; |
1052 | 0 | } |
1053 | 0 | } |
1054 | | |
1055 | 0 | if (this->VersionExact && !this->VersionRange.empty()) { |
1056 | 0 | this->SetError("EXACT cannot be specified with a version range."); |
1057 | 0 | return false; |
1058 | 0 | } |
1059 | | |
1060 | 0 | if (!this->Version.empty()) { |
1061 | 0 | this->VersionCount = |
1062 | 0 | parseVersion(this->Version, this->VersionMajor, this->VersionMinor, |
1063 | 0 | this->VersionPatch, this->VersionTweak); |
1064 | 0 | } |
1065 | 0 | if (!this->VersionMax.empty()) { |
1066 | 0 | this->VersionMaxCount = parseVersion( |
1067 | 0 | this->VersionMax, this->VersionMaxMajor, this->VersionMaxMinor, |
1068 | 0 | this->VersionMaxPatch, this->VersionMaxTweak); |
1069 | 0 | } |
1070 | |
|
1071 | 0 | bool result = this->FindPackage( |
1072 | 0 | this->BypassProvider ? std::vector<std::string>{} : args); |
1073 | |
|
1074 | 0 | std::string const foundVar = cmStrCat(this->Name, "_FOUND"); |
1075 | 0 | bool const isFound = this->Makefile->IsOn(foundVar) || |
1076 | 0 | this->Makefile->IsOn(cmSystemTools::UpperCase(foundVar)); |
1077 | |
|
1078 | 0 | if (this->ScopeUnwind && (!result || !isFound)) { |
1079 | 0 | this->Makefile->GetStateSnapshot().SetUnwindState(cmStateEnums::UNWINDING); |
1080 | 0 | } |
1081 | |
|
1082 | 0 | return result; |
1083 | 0 | } |
1084 | | |
1085 | | bool cmFindPackageCommand::FindPackage( |
1086 | | std::vector<std::string> const& argsForProvider) |
1087 | 0 | { |
1088 | 0 | std::string const makePackageRequiredVar = |
1089 | 0 | cmStrCat("CMAKE_REQUIRE_FIND_PACKAGE_", this->Name); |
1090 | 0 | bool const makePackageRequiredSet = |
1091 | 0 | this->Makefile->IsOn(makePackageRequiredVar); |
1092 | 0 | if (makePackageRequiredSet) { |
1093 | 0 | if (this->IsRequired()) { |
1094 | 0 | this->Makefile->IssueMessage( |
1095 | 0 | MessageType::WARNING, |
1096 | 0 | cmStrCat("for module ", this->Name, |
1097 | 0 | " already called with REQUIRED, thus ", |
1098 | 0 | makePackageRequiredVar, " has no effect.")); |
1099 | 0 | } else { |
1100 | 0 | this->Required = RequiredStatus::RequiredFromPackageVar; |
1101 | 0 | } |
1102 | 0 | } |
1103 | |
|
1104 | 0 | std::string const disableFindPackageVar = |
1105 | 0 | cmStrCat("CMAKE_DISABLE_FIND_PACKAGE_", this->Name); |
1106 | 0 | if (this->Makefile->IsOn(disableFindPackageVar)) { |
1107 | 0 | if (this->IsRequired()) { |
1108 | 0 | this->SetError( |
1109 | 0 | cmStrCat("for module ", this->Name, |
1110 | 0 | (makePackageRequiredSet |
1111 | 0 | ? " was made REQUIRED with " + makePackageRequiredVar |
1112 | 0 | : " called with REQUIRED, "), |
1113 | 0 | " but ", disableFindPackageVar, |
1114 | 0 | " is enabled. A REQUIRED package cannot be disabled.")); |
1115 | 0 | return false; |
1116 | 0 | } |
1117 | 0 | return true; |
1118 | 0 | } |
1119 | | |
1120 | | // Restore PACKAGE_PREFIX_DIR to its pre-call value when we return. If our |
1121 | | // caller is a file generated by configure_package_config_file(), and if |
1122 | | // the package we are about to load also has a config file created by that |
1123 | | // command, it will overwrite PACKAGE_PREFIX_DIR. We need to restore it in |
1124 | | // case something still refers to it in our caller's scope after we return. |
1125 | 0 | class RestoreVariableOnLeavingScope |
1126 | 0 | { |
1127 | 0 | cmMakefile* makefile_; |
1128 | 0 | cm::optional<std::string> value_; |
1129 | |
|
1130 | 0 | public: |
1131 | 0 | RestoreVariableOnLeavingScope(cmMakefile* makefile) |
1132 | 0 | : makefile_(makefile) |
1133 | 0 | { |
1134 | 0 | cmValue v = makefile->GetDefinition("PACKAGE_PREFIX_DIR"); |
1135 | 0 | if (v) { |
1136 | 0 | value_ = *v; |
1137 | 0 | } |
1138 | 0 | } |
1139 | 0 | ~RestoreVariableOnLeavingScope() |
1140 | 0 | { |
1141 | 0 | if (this->value_) { |
1142 | 0 | makefile_->AddDefinition("PACKAGE_PREFIX_DIR", *value_); |
1143 | 0 | } else { |
1144 | 0 | makefile_->RemoveDefinition("PACKAGE_PREFIX_DIR"); |
1145 | 0 | } |
1146 | 0 | } |
1147 | 0 | }; |
1148 | 0 | RestoreVariableOnLeavingScope restorePackagePrefixDir(this->Makefile); |
1149 | | |
1150 | | // Now choose what method(s) we will use to satisfy the request. Note that |
1151 | | // we still want all the above checking of arguments, etc. regardless of the |
1152 | | // method used. This will ensure ill-formed arguments are caught earlier, |
1153 | | // before things like dependency providers need to deal with them. |
1154 | | |
1155 | | // A dependency provider (if set) gets first look before other methods. |
1156 | | // We do this before modifying the package root path stack because a |
1157 | | // provider might use methods that ignore that. |
1158 | 0 | cmState* const state = this->Makefile->GetState(); |
1159 | 0 | cmState::Command const providerCommand = state->GetDependencyProviderCommand( |
1160 | 0 | cmDependencyProvider::Method::FindPackage); |
1161 | 0 | if (argsForProvider.empty()) { |
1162 | 0 | if (this->DebugModeEnabled() && providerCommand) { |
1163 | 0 | this->DebugMessage( |
1164 | 0 | "BYPASS_PROVIDER given, skipping dependency provider"); |
1165 | 0 | } |
1166 | 0 | } else if (providerCommand) { |
1167 | 0 | if (this->DebugModeEnabled()) { |
1168 | 0 | this->DebugMessage(cmStrCat("Trying dependency provider command: ", |
1169 | 0 | state->GetDependencyProvider()->GetCommand(), |
1170 | 0 | "()")); |
1171 | 0 | } |
1172 | 0 | std::vector<cmListFileArgument> listFileArgs(argsForProvider.size() + 1); |
1173 | 0 | listFileArgs[0] = |
1174 | 0 | cmListFileArgument("FIND_PACKAGE"_s, cmListFileArgument::Unquoted, 0); |
1175 | 0 | std::transform(argsForProvider.begin(), argsForProvider.end(), |
1176 | 0 | listFileArgs.begin() + 1, [](std::string const& arg) { |
1177 | 0 | return cmListFileArgument(arg, |
1178 | 0 | cmListFileArgument::Bracket, 0); |
1179 | 0 | }); |
1180 | 0 | if (!providerCommand(listFileArgs, this->Status)) { |
1181 | 0 | return false; |
1182 | 0 | } |
1183 | 0 | std::string providerName; |
1184 | 0 | if (auto depProvider = state->GetDependencyProvider()) { |
1185 | 0 | providerName = depProvider->GetCommand(); |
1186 | 0 | } else { |
1187 | 0 | providerName = "<no provider?>"; |
1188 | 0 | } |
1189 | 0 | auto searchPath = cmStrCat("dependency_provider::", providerName); |
1190 | 0 | if (this->Makefile->IsOn(cmStrCat(this->Name, "_FOUND"))) { |
1191 | 0 | if (this->DebugModeEnabled()) { |
1192 | 0 | this->DebugMessage("Package was found by the dependency provider"); |
1193 | 0 | } |
1194 | 0 | if (this->DebugState) { |
1195 | 0 | this->DebugState->FoundAt(searchPath); |
1196 | 0 | } |
1197 | 0 | this->FileFound = searchPath; |
1198 | 0 | this->FileFoundMode = FoundPackageMode::Provider; |
1199 | 0 | this->AppendSuccessInformation(); |
1200 | 0 | return true; |
1201 | 0 | } |
1202 | 0 | this->ConsideredPaths.emplace_back(searchPath, FoundPackageMode::Provider, |
1203 | 0 | SearchResult::NotFound); |
1204 | 0 | } |
1205 | | |
1206 | | // Limit package nesting depth well below the recursion depth limit because |
1207 | | // find_package nesting uses more stack space than normal recursion. |
1208 | 0 | { |
1209 | 0 | static std::size_t const findPackageDepthMinMax = 100; |
1210 | 0 | std::size_t const findPackageDepthMax = std::max( |
1211 | 0 | this->Makefile->GetRecursionDepthLimit() / 2, findPackageDepthMinMax); |
1212 | 0 | std::size_t const findPackageDepth = |
1213 | 0 | this->Makefile->FindPackageRootPathStack.size() + 1; |
1214 | 0 | if (findPackageDepth > findPackageDepthMax) { |
1215 | 0 | this->SetError(cmStrCat("maximum nesting depth of ", findPackageDepthMax, |
1216 | 0 | " exceeded.")); |
1217 | 0 | return false; |
1218 | 0 | } |
1219 | 0 | } |
1220 | | |
1221 | | // RAII objects to ensure we leave this function with consistent state. |
1222 | 0 | FlushDebugBufferOnExit flushDebugBufferOnExit(*this); |
1223 | 0 | PushPopRootPathStack pushPopRootPathStack(*this); |
1224 | 0 | SetRestoreFindDefinitions setRestoreFindDefinitions(*this); |
1225 | 0 | cmFindPackageStackRAII findPackageStackRAII(this->Makefile, this->Name); |
1226 | |
|
1227 | 0 | findPackageStackRAII.BindTop(this->CurrentPackageInfo); |
1228 | | |
1229 | | // See if we have been told to delegate to FetchContent or some other |
1230 | | // redirected config package first. We have to check all names that |
1231 | | // find_package() may look for, but only need to invoke the override for the |
1232 | | // first one that matches. |
1233 | 0 | auto overrideNames = this->Names; |
1234 | 0 | if (overrideNames.empty()) { |
1235 | 0 | overrideNames.push_back(this->Name); |
1236 | 0 | } |
1237 | 0 | bool forceConfigMode = false; |
1238 | 0 | auto const redirectsDir = |
1239 | 0 | this->Makefile->GetSafeDefinition("CMAKE_FIND_PACKAGE_REDIRECTS_DIR"); |
1240 | 0 | for (auto const& overrideName : overrideNames) { |
1241 | 0 | auto const nameLower = cmSystemTools::LowerCase(overrideName); |
1242 | 0 | auto const delegatePropName = |
1243 | 0 | cmStrCat("_FetchContent_", nameLower, "_override_find_package"); |
1244 | 0 | cmValue const delegateToFetchContentProp = |
1245 | 0 | this->Makefile->GetState()->GetGlobalProperty(delegatePropName); |
1246 | 0 | if (delegateToFetchContentProp.IsOn()) { |
1247 | | // When this property is set, the FetchContent module has already been |
1248 | | // included at least once, so we know the FetchContent_MakeAvailable() |
1249 | | // command will be defined. Any future find_package() calls after this |
1250 | | // one for this package will by-pass this once-only delegation. |
1251 | | // The following call will typically create a <name>-config.cmake file |
1252 | | // in the redirectsDir, which we still want to process like any other |
1253 | | // config file to ensure we follow normal find_package() processing. |
1254 | 0 | cmListFileFunction func( |
1255 | 0 | "FetchContent_MakeAvailable", 0, 0, |
1256 | 0 | { cmListFileArgument(overrideName, cmListFileArgument::Unquoted, 0) }); |
1257 | 0 | if (!this->Makefile->ExecuteCommand(func, this->Status)) { |
1258 | 0 | return false; |
1259 | 0 | } |
1260 | 0 | } |
1261 | | |
1262 | 0 | if (cmSystemTools::FileExists( |
1263 | 0 | cmStrCat(redirectsDir, '/', nameLower, "-config.cmake")) || |
1264 | 0 | cmSystemTools::FileExists( |
1265 | 0 | cmStrCat(redirectsDir, '/', overrideName, "Config.cmake"))) { |
1266 | | // Force the use of this redirected config package file, regardless of |
1267 | | // the type of find_package() call. Files in the redirectsDir must always |
1268 | | // take priority over everything else. |
1269 | 0 | forceConfigMode = true; |
1270 | 0 | this->UseConfigFiles = true; |
1271 | 0 | this->UseFindModules = false; |
1272 | 0 | this->Names.clear(); |
1273 | 0 | this->Names.emplace_back(overrideName); // Force finding this one |
1274 | 0 | this->Variable = cmStrCat(this->Name, "_DIR"); |
1275 | 0 | this->CurrentPackageInfo->Directory = redirectsDir; |
1276 | 0 | this->CurrentPackageInfo->Version = this->VersionFound; |
1277 | 0 | this->SetConfigDirCacheVariable(redirectsDir); |
1278 | 0 | break; |
1279 | 0 | } |
1280 | 0 | } |
1281 | | |
1282 | | // See if there is a Find<PackageName>.cmake module. |
1283 | 0 | bool loadedPackage = false; |
1284 | 0 | if (forceConfigMode) { |
1285 | 0 | loadedPackage = this->FindPackageUsingConfigMode(); |
1286 | 0 | } else if (this->Makefile->IsOn("CMAKE_FIND_PACKAGE_PREFER_CONFIG")) { |
1287 | 0 | if (this->UseConfigFiles && this->FindPackageUsingConfigMode()) { |
1288 | 0 | loadedPackage = true; |
1289 | 0 | } else { |
1290 | 0 | if (this->FindPackageUsingModuleMode()) { |
1291 | 0 | loadedPackage = true; |
1292 | 0 | } else { |
1293 | | // The package was not loaded. Report errors. |
1294 | 0 | if (this->HandlePackageMode(HandlePackageModeType::Module)) { |
1295 | 0 | loadedPackage = true; |
1296 | 0 | } |
1297 | 0 | } |
1298 | 0 | } |
1299 | 0 | } else { |
1300 | 0 | if (this->UseFindModules && this->FindPackageUsingModuleMode()) { |
1301 | 0 | loadedPackage = true; |
1302 | 0 | } else { |
1303 | | // Handle CMAKE_FIND_PACKAGE_WARN_NO_MODULE (warn when CONFIG mode is |
1304 | | // implicitly assumed) |
1305 | 0 | if (this->UseFindModules && this->UseConfigFiles && |
1306 | 0 | this->Makefile->IsOn("CMAKE_FIND_PACKAGE_WARN_NO_MODULE")) { |
1307 | 0 | std::ostringstream aw; |
1308 | 0 | if (this->RequiredCMakeVersion >= CMake_VERSION_ENCODE(2, 8, 8)) { |
1309 | 0 | aw << "find_package called without either MODULE or CONFIG option " |
1310 | 0 | "and " |
1311 | 0 | "no Find" |
1312 | 0 | << this->Name |
1313 | 0 | << ".cmake module is in CMAKE_MODULE_PATH. " |
1314 | 0 | "Add MODULE to exclusively request Module mode and fail if " |
1315 | 0 | "Find" |
1316 | 0 | << this->Name |
1317 | 0 | << ".cmake is missing. " |
1318 | 0 | "Add CONFIG to exclusively request Config mode and search for " |
1319 | 0 | "a " |
1320 | 0 | "package configuration file provided by " |
1321 | 0 | << this->Name << " (" << this->Name << "Config.cmake or " |
1322 | 0 | << cmSystemTools::LowerCase(this->Name) << "-config.cmake). "; |
1323 | 0 | } else { |
1324 | 0 | aw << "find_package called without NO_MODULE option and no " |
1325 | 0 | "Find" |
1326 | 0 | << this->Name |
1327 | 0 | << ".cmake module is in CMAKE_MODULE_PATH. " |
1328 | 0 | "Add NO_MODULE to exclusively request Config mode and search " |
1329 | 0 | "for a " |
1330 | 0 | "package configuration file provided by " |
1331 | 0 | << this->Name << " (" << this->Name << "Config.cmake or " |
1332 | 0 | << cmSystemTools::LowerCase(this->Name) |
1333 | 0 | << "-config.cmake). Otherwise make Find" << this->Name |
1334 | 0 | << ".cmake available in CMAKE_MODULE_PATH."; |
1335 | 0 | } |
1336 | 0 | aw << "\n" |
1337 | 0 | "(Variable CMAKE_FIND_PACKAGE_WARN_NO_MODULE enabled this " |
1338 | 0 | "warning.)"; |
1339 | 0 | this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, aw.str()); |
1340 | 0 | } |
1341 | |
|
1342 | 0 | if (this->FindPackageUsingConfigMode()) { |
1343 | 0 | loadedPackage = true; |
1344 | 0 | } |
1345 | 0 | } |
1346 | 0 | } |
1347 | |
|
1348 | 0 | this->AppendSuccessInformation(); |
1349 | 0 | return loadedPackage; |
1350 | 0 | } |
1351 | | |
1352 | | bool cmFindPackageCommand::FindPackageUsingModuleMode() |
1353 | 0 | { |
1354 | 0 | bool foundModule = false; |
1355 | 0 | if (!this->FindModule(foundModule)) { |
1356 | 0 | return false; |
1357 | 0 | } |
1358 | 0 | return foundModule; |
1359 | 0 | } |
1360 | | |
1361 | | bool cmFindPackageCommand::FindPackageUsingConfigMode() |
1362 | 0 | { |
1363 | 0 | this->Variable = cmStrCat(this->Name, "_DIR"); |
1364 | | |
1365 | | // Add the default name. |
1366 | 0 | if (this->Names.empty()) { |
1367 | 0 | this->Names.push_back(this->Name); |
1368 | 0 | } |
1369 | | |
1370 | | // Add the default configs. |
1371 | 0 | if (this->Configs.empty()) { |
1372 | 0 | for (std::string const& n : this->Names) { |
1373 | 0 | std::string config; |
1374 | 0 | if (this->UseCpsFiles) { |
1375 | 0 | config = cmStrCat(n, ".cps"); |
1376 | 0 | this->Configs.emplace_back(std::move(config), pdt::Cps); |
1377 | |
|
1378 | 0 | config = cmStrCat(cmSystemTools::LowerCase(n), ".cps"); |
1379 | 0 | if (config != this->Configs.back().Name) { |
1380 | 0 | this->Configs.emplace_back(std::move(config), pdt::Cps); |
1381 | 0 | } |
1382 | 0 | } |
1383 | |
|
1384 | 0 | config = cmStrCat(n, "Config.cmake"); |
1385 | 0 | this->Configs.emplace_back(std::move(config), pdt::CMake); |
1386 | |
|
1387 | 0 | config = cmStrCat(cmSystemTools::LowerCase(n), "-config.cmake"); |
1388 | 0 | this->Configs.emplace_back(std::move(config), pdt::CMake); |
1389 | 0 | } |
1390 | 0 | } |
1391 | | |
1392 | | // get igonored paths from vars and reroot them. |
1393 | 0 | std::vector<std::string> ignored; |
1394 | 0 | this->GetIgnoredPaths(ignored); |
1395 | 0 | this->RerootPaths(ignored); |
1396 | | |
1397 | | // Construct a set of ignored paths |
1398 | 0 | this->IgnoredPaths.clear(); |
1399 | 0 | this->IgnoredPaths.insert(ignored.begin(), ignored.end()); |
1400 | | |
1401 | | // get igonored prefix paths from vars and reroot them. |
1402 | 0 | std::vector<std::string> ignoredPrefixes; |
1403 | 0 | this->GetIgnoredPrefixPaths(ignoredPrefixes); |
1404 | 0 | this->RerootPaths(ignoredPrefixes); |
1405 | | |
1406 | | // Construct a set of ignored prefix paths |
1407 | 0 | this->IgnoredPrefixPaths.clear(); |
1408 | 0 | this->IgnoredPrefixPaths.insert(ignoredPrefixes.begin(), |
1409 | 0 | ignoredPrefixes.end()); |
1410 | | |
1411 | | // Find and load the package. |
1412 | 0 | return this->HandlePackageMode(HandlePackageModeType::Config); |
1413 | 0 | } |
1414 | | |
1415 | | void cmFindPackageCommand::SetVersionVariables( |
1416 | | std::function<void(std::string const&, cm::string_view)> const& |
1417 | | addDefinition, |
1418 | | std::string const& prefix, std::string const& version, |
1419 | | unsigned int const count, unsigned int const major, unsigned int const minor, |
1420 | | unsigned int const patch, unsigned int const tweak) |
1421 | 0 | { |
1422 | 0 | addDefinition(prefix, version); |
1423 | |
|
1424 | 0 | char buf[64]; |
1425 | 0 | snprintf(buf, sizeof(buf), "%u", major); |
1426 | 0 | addDefinition(prefix + "_MAJOR", buf); |
1427 | 0 | snprintf(buf, sizeof(buf), "%u", minor); |
1428 | 0 | addDefinition(prefix + "_MINOR", buf); |
1429 | 0 | snprintf(buf, sizeof(buf), "%u", patch); |
1430 | 0 | addDefinition(prefix + "_PATCH", buf); |
1431 | 0 | snprintf(buf, sizeof(buf), "%u", tweak); |
1432 | 0 | addDefinition(prefix + "_TWEAK", buf); |
1433 | 0 | snprintf(buf, sizeof(buf), "%u", count); |
1434 | 0 | addDefinition(prefix + "_COUNT", buf); |
1435 | 0 | } |
1436 | | |
1437 | | void cmFindPackageCommand::SetModuleVariables() |
1438 | 0 | { |
1439 | 0 | this->AddFindDefinition("CMAKE_FIND_PACKAGE_NAME", this->Name); |
1440 | | |
1441 | | // Nested find calls are not automatically required. |
1442 | 0 | this->AddFindDefinition("CMAKE_FIND_REQUIRED", ""_s); |
1443 | | |
1444 | | // Store the list of components and associated variable definitions. |
1445 | 0 | std::string components_var = this->Name + "_FIND_COMPONENTS"; |
1446 | 0 | this->AddFindDefinition(components_var, this->Components); |
1447 | 0 | for (auto const& component : this->OptionalComponents) { |
1448 | 0 | this->AddFindDefinition( |
1449 | 0 | cmStrCat(this->Name, "_FIND_REQUIRED_"_s, component), "0"_s); |
1450 | 0 | } |
1451 | 0 | for (auto const& component : this->RequiredComponents) { |
1452 | 0 | this->AddFindDefinition( |
1453 | 0 | cmStrCat(this->Name, "_FIND_REQUIRED_"_s, component), "1"_s); |
1454 | 0 | } |
1455 | |
|
1456 | 0 | if (this->Quiet) { |
1457 | | // Tell the module that is about to be read that it should find |
1458 | | // quietly. |
1459 | 0 | std::string quietly = cmStrCat(this->Name, "_FIND_QUIETLY"); |
1460 | 0 | this->AddFindDefinition(quietly, "1"_s); |
1461 | 0 | } |
1462 | |
|
1463 | 0 | if (this->IsRequired()) { |
1464 | | // Tell the module that is about to be read that it should report |
1465 | | // a fatal error if the package is not found. |
1466 | 0 | std::string req = cmStrCat(this->Name, "_FIND_REQUIRED"); |
1467 | 0 | this->AddFindDefinition(req, "1"_s); |
1468 | 0 | } |
1469 | |
|
1470 | 0 | if (!this->VersionComplete.empty()) { |
1471 | 0 | std::string req = cmStrCat(this->Name, "_FIND_VERSION_COMPLETE"); |
1472 | 0 | this->AddFindDefinition(req, this->VersionComplete); |
1473 | 0 | } |
1474 | | |
1475 | | // Tell the module that is about to be read what version of the |
1476 | | // package has been requested. |
1477 | 0 | auto addDefinition = [this](std::string const& variable, |
1478 | 0 | cm::string_view value) { |
1479 | 0 | this->AddFindDefinition(variable, value); |
1480 | 0 | }; |
1481 | |
|
1482 | 0 | if (!this->Version.empty()) { |
1483 | 0 | auto prefix = cmStrCat(this->Name, "_FIND_VERSION"_s); |
1484 | 0 | this->SetVersionVariables(addDefinition, prefix, this->Version, |
1485 | 0 | this->VersionCount, this->VersionMajor, |
1486 | 0 | this->VersionMinor, this->VersionPatch, |
1487 | 0 | this->VersionTweak); |
1488 | | |
1489 | | // Tell the module whether an exact version has been requested. |
1490 | 0 | auto exact = cmStrCat(this->Name, "_FIND_VERSION_EXACT"); |
1491 | 0 | this->AddFindDefinition(exact, this->VersionExact ? "1"_s : "0"_s); |
1492 | 0 | } |
1493 | 0 | if (!this->VersionRange.empty()) { |
1494 | 0 | auto prefix = cmStrCat(this->Name, "_FIND_VERSION_MIN"_s); |
1495 | 0 | this->SetVersionVariables(addDefinition, prefix, this->Version, |
1496 | 0 | this->VersionCount, this->VersionMajor, |
1497 | 0 | this->VersionMinor, this->VersionPatch, |
1498 | 0 | this->VersionTweak); |
1499 | |
|
1500 | 0 | prefix = cmStrCat(this->Name, "_FIND_VERSION_MAX"_s); |
1501 | 0 | this->SetVersionVariables(addDefinition, prefix, this->VersionMax, |
1502 | 0 | this->VersionMaxCount, this->VersionMaxMajor, |
1503 | 0 | this->VersionMaxMinor, this->VersionMaxPatch, |
1504 | 0 | this->VersionMaxTweak); |
1505 | |
|
1506 | 0 | auto id = cmStrCat(this->Name, "_FIND_VERSION_RANGE"); |
1507 | 0 | this->AddFindDefinition(id, this->VersionRange); |
1508 | 0 | id = cmStrCat(this->Name, "_FIND_VERSION_RANGE_MIN"); |
1509 | 0 | this->AddFindDefinition(id, this->VersionRangeMin); |
1510 | 0 | id = cmStrCat(this->Name, "_FIND_VERSION_RANGE_MAX"); |
1511 | 0 | this->AddFindDefinition(id, this->VersionRangeMax); |
1512 | 0 | } |
1513 | |
|
1514 | 0 | if (this->RegistryViewDefined) { |
1515 | 0 | this->AddFindDefinition(cmStrCat(this->Name, "_FIND_REGISTRY_VIEW"), |
1516 | 0 | cmWindowsRegistry::FromView(this->RegistryView)); |
1517 | 0 | } |
1518 | 0 | } |
1519 | | |
1520 | | void cmFindPackageCommand::AddFindDefinition(std::string const& var, |
1521 | | cm::string_view const value) |
1522 | 0 | { |
1523 | 0 | if (cmValue old = this->Makefile->GetDefinition(var)) { |
1524 | 0 | this->OriginalDefs[var].exists = true; |
1525 | 0 | this->OriginalDefs[var].value = *old; |
1526 | 0 | } else { |
1527 | 0 | this->OriginalDefs[var].exists = false; |
1528 | 0 | } |
1529 | 0 | this->Makefile->AddDefinition(var, value); |
1530 | 0 | } |
1531 | | |
1532 | | void cmFindPackageCommand::RestoreFindDefinitions() |
1533 | 0 | { |
1534 | 0 | for (auto const& i : this->OriginalDefs) { |
1535 | 0 | OriginalDef const& od = i.second; |
1536 | 0 | if (od.exists) { |
1537 | 0 | this->Makefile->AddDefinition(i.first, od.value); |
1538 | 0 | } else { |
1539 | 0 | this->Makefile->RemoveDefinition(i.first); |
1540 | 0 | } |
1541 | 0 | } |
1542 | 0 | } |
1543 | | |
1544 | | bool cmFindPackageCommand::FindModule(bool& found) |
1545 | 0 | { |
1546 | 0 | std::string moduleFileName = cmStrCat("Find", this->Name, ".cmake"); |
1547 | |
|
1548 | 0 | bool system = false; |
1549 | 0 | std::string debugBuffer = cmStrCat( |
1550 | 0 | "find_package considered the following paths for ", moduleFileName, ":\n"); |
1551 | 0 | std::string mfile = this->Makefile->GetModulesFile( |
1552 | 0 | moduleFileName, system, this->DebugModeEnabled(), debugBuffer); |
1553 | 0 | if (this->DebugModeEnabled()) { |
1554 | 0 | if (mfile.empty()) { |
1555 | 0 | debugBuffer = cmStrCat(debugBuffer, "The file was not found.\n"); |
1556 | 0 | } else { |
1557 | 0 | debugBuffer = |
1558 | 0 | cmStrCat(debugBuffer, "The file was found at\n ", mfile, '\n'); |
1559 | 0 | } |
1560 | 0 | this->DebugBuffer = cmStrCat(this->DebugBuffer, debugBuffer); |
1561 | 0 | } |
1562 | |
|
1563 | 0 | if (!mfile.empty()) { |
1564 | 0 | if (system) { |
1565 | 0 | auto const it = this->DeprecatedFindModules.find(this->Name); |
1566 | 0 | if (it != this->DeprecatedFindModules.end()) { |
1567 | 0 | cmPolicies::PolicyStatus status = |
1568 | 0 | this->Makefile->GetPolicyStatus(it->second); |
1569 | 0 | switch (status) { |
1570 | 0 | case cmPolicies::WARN: { |
1571 | 0 | this->Makefile->IssueMessage( |
1572 | 0 | MessageType::AUTHOR_WARNING, |
1573 | 0 | cmStrCat(cmPolicies::GetPolicyWarning(it->second), '\n')); |
1574 | 0 | CM_FALLTHROUGH; |
1575 | 0 | } |
1576 | 0 | case cmPolicies::OLD: |
1577 | 0 | break; |
1578 | 0 | case cmPolicies::NEW: |
1579 | 0 | return true; |
1580 | 0 | } |
1581 | 0 | } |
1582 | 0 | } |
1583 | | |
1584 | | // Load the module we found, and set "<name>_FIND_MODULE" to true |
1585 | | // while inside it. |
1586 | 0 | found = true; |
1587 | 0 | std::string const var = cmStrCat(this->Name, "_FIND_MODULE"); |
1588 | 0 | this->Makefile->AddDefinition(var, "1"); |
1589 | 0 | bool result = this->ReadListFile(mfile, DoPolicyScope); |
1590 | 0 | this->Makefile->RemoveDefinition(var); |
1591 | |
|
1592 | 0 | std::string const foundVar = cmStrCat(this->Name, "_FOUND"); |
1593 | 0 | if (this->Makefile->IsDefinitionSet(foundVar) && |
1594 | 0 | !this->Makefile->IsOn(foundVar)) { |
1595 | |
|
1596 | 0 | if (this->DebugModeEnabled()) { |
1597 | 0 | this->DebugBuffer = cmStrCat( |
1598 | 0 | this->DebugBuffer, "The module is considered not found due to ", |
1599 | 0 | foundVar, " being FALSE."); |
1600 | 0 | } |
1601 | |
|
1602 | 0 | this->ConsideredPaths.emplace_back(mfile, FoundPackageMode::Module, |
1603 | 0 | SearchResult::NotFound); |
1604 | 0 | std::string const notFoundMessageVar = |
1605 | 0 | cmStrCat(this->Name, "_NOT_FOUND_MESSAGE"); |
1606 | 0 | if (cmValue notFoundMessage = |
1607 | 0 | this->Makefile->GetDefinition(notFoundMessageVar)) { |
1608 | |
|
1609 | 0 | this->ConsideredPaths.back().Message = *notFoundMessage; |
1610 | 0 | } |
1611 | 0 | } else { |
1612 | 0 | if (this->DebugState) { |
1613 | 0 | this->DebugState->FoundAt(mfile); |
1614 | 0 | } |
1615 | 0 | this->FileFound = mfile; |
1616 | 0 | this->FileFoundMode = FoundPackageMode::Module; |
1617 | 0 | std::string const versionVar = cmStrCat(this->Name, "_VERSION"); |
1618 | 0 | if (cmValue version = this->Makefile->GetDefinition(versionVar)) { |
1619 | 0 | this->VersionFound = *version; |
1620 | 0 | } |
1621 | 0 | } |
1622 | 0 | return result; |
1623 | 0 | } |
1624 | 0 | return true; |
1625 | 0 | } |
1626 | | |
1627 | | bool cmFindPackageCommand::HandlePackageMode( |
1628 | | HandlePackageModeType const handlePackageModeType) |
1629 | 0 | { |
1630 | 0 | this->ConsideredConfigs.clear(); |
1631 | | |
1632 | | // Try to find the config file. |
1633 | 0 | cmValue def = this->Makefile->GetDefinition(this->Variable); |
1634 | | |
1635 | | // Try to load the config file if the directory is known |
1636 | 0 | bool fileFound = false; |
1637 | 0 | if (this->UseConfigFiles) { |
1638 | 0 | if (!def.IsOff()) { |
1639 | | // Get the directory from the variable value. |
1640 | 0 | std::string dir = *def; |
1641 | 0 | cmSystemTools::ConvertToUnixSlashes(dir); |
1642 | | |
1643 | | // Treat relative paths with respect to the current source dir. |
1644 | 0 | if (!cmSystemTools::FileIsFullPath(dir)) { |
1645 | 0 | dir = "/" + dir; |
1646 | 0 | dir = this->Makefile->GetCurrentSourceDirectory() + dir; |
1647 | 0 | } |
1648 | | // The file location was cached. Look for the correct file. |
1649 | 0 | std::string file; |
1650 | 0 | FoundPackageMode foundMode = FoundPackageMode::None; |
1651 | 0 | if (this->FindConfigFile(dir, pdt::Any, file, foundMode)) { |
1652 | 0 | if (this->DebugState) { |
1653 | 0 | this->DebugState->FoundAt(file); |
1654 | 0 | } |
1655 | 0 | this->FileFound = std::move(file); |
1656 | 0 | this->FileFoundMode = foundMode; |
1657 | 0 | fileFound = true; |
1658 | 0 | } |
1659 | 0 | def = this->Makefile->GetDefinition(this->Variable); |
1660 | 0 | } |
1661 | | |
1662 | | // Search for the config file if it is not already found. |
1663 | 0 | if (def.IsOff() || !fileFound) { |
1664 | 0 | fileFound = this->FindConfig(); |
1665 | 0 | } |
1666 | | |
1667 | | // Sanity check. |
1668 | 0 | if (fileFound && this->FileFound.empty()) { |
1669 | 0 | this->Makefile->IssueMessage( |
1670 | 0 | MessageType::INTERNAL_ERROR, |
1671 | 0 | "fileFound is true but FileFound is empty!"); |
1672 | 0 | fileFound = false; |
1673 | 0 | } |
1674 | |
|
1675 | 0 | if (fileFound) { |
1676 | 0 | this->CurrentPackageInfo->Directory = |
1677 | 0 | cmSystemTools::GetFilenamePath(this->FileFound); |
1678 | 0 | this->CurrentPackageInfo->Version = this->VersionFound; |
1679 | 0 | } |
1680 | 0 | } |
1681 | |
|
1682 | 0 | std::string const foundVar = cmStrCat(this->Name, "_FOUND"); |
1683 | 0 | std::string const notFoundMessageVar = |
1684 | 0 | cmStrCat(this->Name, "_NOT_FOUND_MESSAGE"); |
1685 | 0 | std::string notFoundMessage; |
1686 | | |
1687 | | // If the directory for the config file was found, try to read the file. |
1688 | 0 | bool result = true; |
1689 | 0 | bool found = false; |
1690 | 0 | bool configFileSetFOUNDFalse = false; |
1691 | 0 | std::vector<std::string> missingTargets; |
1692 | |
|
1693 | 0 | if (fileFound) { |
1694 | 0 | if (this->Makefile->IsDefinitionSet(foundVar) && |
1695 | 0 | !this->Makefile->IsOn(foundVar)) { |
1696 | | // by removing Foo_FOUND here if it is FALSE, we don't really change |
1697 | | // the situation for the Config file which is about to be included, |
1698 | | // but we make it possible to detect later on whether the Config file |
1699 | | // has set Foo_FOUND to FALSE itself: |
1700 | 0 | this->Makefile->RemoveDefinition(foundVar); |
1701 | 0 | } |
1702 | 0 | this->Makefile->RemoveDefinition(notFoundMessageVar); |
1703 | | |
1704 | | // Set the version variables before loading the config file. |
1705 | | // It may override them. |
1706 | 0 | this->StoreVersionFound(); |
1707 | | |
1708 | | // Parse the configuration file. |
1709 | 0 | if (this->CpsReader) { |
1710 | | // The package has been found. |
1711 | 0 | found = true; |
1712 | 0 | result = this->ReadPackage(); |
1713 | 0 | } else if (this->ReadListFile(this->FileFound, DoPolicyScope)) { |
1714 | | // The package has been found. |
1715 | 0 | found = true; |
1716 | | |
1717 | | // Check whether the Config file has set Foo_FOUND to FALSE: |
1718 | 0 | if (this->Makefile->IsDefinitionSet(foundVar) && |
1719 | 0 | !this->Makefile->IsOn(foundVar)) { |
1720 | | // we get here if the Config file has set Foo_FOUND actively to FALSE |
1721 | 0 | found = false; |
1722 | 0 | configFileSetFOUNDFalse = true; |
1723 | 0 | notFoundMessage = |
1724 | 0 | this->Makefile->GetSafeDefinition(notFoundMessageVar); |
1725 | 0 | } |
1726 | | |
1727 | | // Check whether the required targets are defined. |
1728 | 0 | if (found && !this->RequiredTargets.empty()) { |
1729 | 0 | for (std::string const& t : this->RequiredTargets) { |
1730 | 0 | std::string qualifiedTarget = cmStrCat(this->Name, "::"_s, t); |
1731 | 0 | if (!this->Makefile->FindImportedTarget(qualifiedTarget)) { |
1732 | 0 | missingTargets.emplace_back(std::move(qualifiedTarget)); |
1733 | 0 | found = false; |
1734 | 0 | } |
1735 | 0 | } |
1736 | 0 | } |
1737 | 0 | } else { |
1738 | | // The configuration file is invalid. |
1739 | 0 | result = false; |
1740 | 0 | } |
1741 | 0 | } |
1742 | |
|
1743 | 0 | if (this->UseFindModules && !found && |
1744 | 0 | handlePackageModeType == HandlePackageModeType::Config && |
1745 | 0 | this->Makefile->IsOn("CMAKE_FIND_PACKAGE_PREFER_CONFIG")) { |
1746 | | // Config mode failed. Allow Module case. |
1747 | 0 | result = false; |
1748 | 0 | } |
1749 | | |
1750 | | // package not found |
1751 | 0 | if (result && !found) { |
1752 | | // warn if package required or |
1753 | | // (neither quiet nor in config mode and not explicitly optional) |
1754 | 0 | if (this->IsRequired() || |
1755 | 0 | (!(this->Quiet || |
1756 | 0 | (this->UseConfigFiles && !this->UseFindModules && |
1757 | 0 | this->ConsideredConfigs.empty())) && |
1758 | 0 | this->Required != RequiredStatus::OptionalExplicit)) { |
1759 | | // The variable is not set. |
1760 | 0 | std::ostringstream e; |
1761 | 0 | std::ostringstream aw; |
1762 | 0 | if (configFileSetFOUNDFalse) { |
1763 | 0 | e << "Found package configuration file:\n" |
1764 | 0 | " " |
1765 | 0 | << this->FileFound |
1766 | 0 | << "\n" |
1767 | 0 | "but it set " |
1768 | 0 | << foundVar << " to FALSE so package \"" << this->Name |
1769 | 0 | << "\" is considered to be NOT FOUND."; |
1770 | 0 | if (!notFoundMessage.empty()) { |
1771 | 0 | e << " Reason given by package: \n" << notFoundMessage << "\n"; |
1772 | 0 | } |
1773 | 0 | } else if (!missingTargets.empty()) { |
1774 | 0 | e << "Found package configuration file:\n" |
1775 | 0 | " " |
1776 | 0 | << this->FileFound |
1777 | 0 | << "\n" |
1778 | 0 | "but the following required targets were not found:\n" |
1779 | 0 | " " |
1780 | 0 | << cmJoin(cmMakeRange(missingTargets), ", "_s); |
1781 | 0 | } else if (!this->ConsideredConfigs.empty()) { |
1782 | | // If there are files in ConsideredConfigs, it means that |
1783 | | // FooConfig.cmake have been found, but they didn't have appropriate |
1784 | | // versions. |
1785 | 0 | auto duplicate_end = cmRemoveDuplicates(this->ConsideredConfigs); |
1786 | 0 | e << "Could not find a configuration file for package \"" << this->Name |
1787 | 0 | << "\" that " |
1788 | 0 | << (this->VersionExact ? "exactly matches" : "is compatible with") |
1789 | 0 | << " requested version " |
1790 | 0 | << (this->VersionRange.empty() ? "" : "range ") << '"' |
1791 | 0 | << this->VersionComplete |
1792 | 0 | << "\".\n" |
1793 | 0 | "The following configuration files were considered but not " |
1794 | 0 | "accepted:\n"; |
1795 | |
|
1796 | 0 | for (ConfigFileInfo const& info : |
1797 | 0 | cmMakeRange(this->ConsideredConfigs.cbegin(), duplicate_end)) { |
1798 | 0 | e << " " << info.filename << ", version: " << info.version |
1799 | 0 | << "\n " << info.message << '\n'; |
1800 | 0 | } |
1801 | 0 | } else { |
1802 | 0 | std::string requestedVersionString; |
1803 | 0 | if (!this->VersionComplete.empty()) { |
1804 | 0 | requestedVersionString = |
1805 | 0 | cmStrCat(" (requested version ", this->VersionComplete, ')'); |
1806 | 0 | } |
1807 | |
|
1808 | 0 | if (this->UseConfigFiles) { |
1809 | 0 | if (this->UseFindModules) { |
1810 | 0 | e << "By not providing \"Find" << this->Name |
1811 | 0 | << ".cmake\" in " |
1812 | 0 | "CMAKE_MODULE_PATH this project has asked CMake to find a " |
1813 | 0 | "package configuration file provided by \"" |
1814 | 0 | << this->Name |
1815 | 0 | << "\", " |
1816 | 0 | "but CMake did not find one.\n"; |
1817 | 0 | } |
1818 | |
|
1819 | 0 | if (this->Configs.size() == 1) { |
1820 | 0 | e << "Could not find a package configuration file named \"" |
1821 | 0 | << this->Configs[0].Name << "\" provided by package \"" |
1822 | 0 | << this->Name << "\"" << requestedVersionString << ".\n"; |
1823 | 0 | } else { |
1824 | 0 | auto configs = cmMakeRange(this->Configs); |
1825 | 0 | auto configNames = |
1826 | 0 | configs.transform([](ConfigName const& cn) { return cn.Name; }); |
1827 | 0 | e << "Could not find a package configuration file provided by \"" |
1828 | 0 | << this->Name << "\"" << requestedVersionString |
1829 | 0 | << " with any of the following names:\n" |
1830 | 0 | << cmWrap(" "_s, configNames, ""_s, "\n"_s) << '\n'; |
1831 | 0 | } |
1832 | |
|
1833 | 0 | e << "Add the installation prefix of \"" << this->Name |
1834 | 0 | << "\" to CMAKE_PREFIX_PATH or set \"" << this->Variable |
1835 | 0 | << "\" to a directory containing one of the above files. " |
1836 | 0 | "If \"" |
1837 | 0 | << this->Name |
1838 | 0 | << "\" provides a separate development " |
1839 | 0 | "package or SDK, be sure it has been installed."; |
1840 | 0 | } else // if(!this->UseFindModules && !this->UseConfigFiles) |
1841 | 0 | { |
1842 | 0 | e << "No \"Find" << this->Name |
1843 | 0 | << ".cmake\" found in " |
1844 | 0 | "CMAKE_MODULE_PATH."; |
1845 | |
|
1846 | 0 | aw |
1847 | 0 | << "Find" << this->Name |
1848 | 0 | << ".cmake must either be part of this " |
1849 | 0 | "project itself, in this case adjust CMAKE_MODULE_PATH so that " |
1850 | 0 | "it points to the correct location inside its source tree.\n" |
1851 | 0 | "Or it must be installed by a package which has already been " |
1852 | 0 | "found via find_package(). In this case make sure that " |
1853 | 0 | "package has indeed been found and adjust CMAKE_MODULE_PATH to " |
1854 | 0 | "contain the location where that package has installed " |
1855 | 0 | "Find" |
1856 | 0 | << this->Name |
1857 | 0 | << ".cmake. This must be a location " |
1858 | 0 | "provided by that package. This error in general means that " |
1859 | 0 | "the buildsystem of this project is relying on a Find-module " |
1860 | 0 | "without ensuring that it is actually available.\n"; |
1861 | 0 | } |
1862 | 0 | } |
1863 | 0 | if (this->Required == RequiredStatus::RequiredFromFindVar) { |
1864 | 0 | e << "\nThis package is considered required because the " |
1865 | 0 | "CMAKE_FIND_REQUIRED variable has been enabled.\n"; |
1866 | 0 | } else if (this->Required == RequiredStatus::RequiredFromPackageVar) { |
1867 | 0 | e << "\nThis package is considered required because the " |
1868 | 0 | << cmStrCat("CMAKE_REQUIRE_FIND_PACKAGE_", this->Name) |
1869 | 0 | << " variable has been enabled.\n"; |
1870 | 0 | } |
1871 | |
|
1872 | 0 | this->Makefile->IssueMessage( |
1873 | 0 | this->IsRequired() ? MessageType::FATAL_ERROR : MessageType::WARNING, |
1874 | 0 | e.str()); |
1875 | 0 | if (this->IsRequired()) { |
1876 | 0 | cmSystemTools::SetFatalErrorOccurred(); |
1877 | 0 | } |
1878 | |
|
1879 | 0 | if (!aw.str().empty()) { |
1880 | 0 | this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, aw.str()); |
1881 | 0 | } |
1882 | 0 | } |
1883 | | // output result if in config mode but not in quiet mode |
1884 | 0 | else if (!this->Quiet) { |
1885 | 0 | this->Makefile->DisplayStatus(cmStrCat("Could NOT find ", this->Name, |
1886 | 0 | " (missing: ", this->Name, |
1887 | 0 | "_DIR)"), |
1888 | 0 | -1); |
1889 | 0 | } |
1890 | 0 | } |
1891 | | |
1892 | | // Set a variable marking whether the package was found. |
1893 | 0 | this->Makefile->AddDefinition(foundVar, found ? "1" : "0"); |
1894 | | |
1895 | | // Set a variable naming the configuration file that was found. |
1896 | 0 | std::string const fileVar = cmStrCat(this->Name, "_CONFIG"); |
1897 | 0 | if (found) { |
1898 | 0 | this->Makefile->AddDefinition(fileVar, this->FileFound); |
1899 | 0 | } else { |
1900 | 0 | this->Makefile->RemoveDefinition(fileVar); |
1901 | 0 | } |
1902 | |
|
1903 | 0 | std::string const consideredConfigsVar = |
1904 | 0 | cmStrCat(this->Name, "_CONSIDERED_CONFIGS"); |
1905 | 0 | std::string const consideredVersionsVar = |
1906 | 0 | cmStrCat(this->Name, "_CONSIDERED_VERSIONS"); |
1907 | |
|
1908 | 0 | std::string consideredConfigFiles; |
1909 | 0 | std::string consideredVersions; |
1910 | |
|
1911 | 0 | char const* sep = ""; |
1912 | 0 | for (ConfigFileInfo const& i : this->ConsideredConfigs) { |
1913 | 0 | consideredConfigFiles += sep; |
1914 | 0 | consideredVersions += sep; |
1915 | 0 | consideredConfigFiles += i.filename; |
1916 | 0 | consideredVersions += i.version; |
1917 | 0 | sep = ";"; |
1918 | 0 | } |
1919 | |
|
1920 | 0 | this->Makefile->AddDefinition(consideredConfigsVar, consideredConfigFiles); |
1921 | |
|
1922 | 0 | this->Makefile->AddDefinition(consideredVersionsVar, consideredVersions); |
1923 | |
|
1924 | 0 | return result; |
1925 | 0 | } |
1926 | | |
1927 | | bool cmFindPackageCommand::FindConfig() |
1928 | 0 | { |
1929 | | // Compute the set of search prefixes. |
1930 | 0 | this->ComputePrefixes(); |
1931 | | |
1932 | | // Look for the project's configuration file. |
1933 | 0 | bool found = false; |
1934 | 0 | if (this->DebugModeEnabled()) { |
1935 | 0 | this->DebugBuffer = cmStrCat(this->DebugBuffer, |
1936 | 0 | "find_package considered the following " |
1937 | 0 | "locations for ", |
1938 | 0 | this->Name, "'s Config module:\n"); |
1939 | 0 | } |
1940 | |
|
1941 | 0 | if (!found && this->UseCpsFiles) { |
1942 | 0 | found = this->FindEnvironmentConfig(); |
1943 | 0 | } |
1944 | | |
1945 | | // Search for frameworks. |
1946 | 0 | if (!found && (this->SearchFrameworkFirst || this->SearchFrameworkOnly)) { |
1947 | 0 | found = this->FindFrameworkConfig(); |
1948 | 0 | } |
1949 | | |
1950 | | // Search for apps. |
1951 | 0 | if (!found && (this->SearchAppBundleFirst || this->SearchAppBundleOnly)) { |
1952 | 0 | found = this->FindAppBundleConfig(); |
1953 | 0 | } |
1954 | | |
1955 | | // Search prefixes. |
1956 | 0 | if (!found && !(this->SearchFrameworkOnly || this->SearchAppBundleOnly)) { |
1957 | 0 | found = this->FindPrefixedConfig(); |
1958 | 0 | } |
1959 | | |
1960 | | // Search for frameworks. |
1961 | 0 | if (!found && this->SearchFrameworkLast) { |
1962 | 0 | found = this->FindFrameworkConfig(); |
1963 | 0 | } |
1964 | | |
1965 | | // Search for apps. |
1966 | 0 | if (!found && this->SearchAppBundleLast) { |
1967 | 0 | found = this->FindAppBundleConfig(); |
1968 | 0 | } |
1969 | |
|
1970 | 0 | if (this->DebugModeEnabled()) { |
1971 | 0 | if (found) { |
1972 | 0 | this->DebugBuffer = cmStrCat( |
1973 | 0 | this->DebugBuffer, "The file was found at\n ", this->FileFound, '\n'); |
1974 | 0 | } else { |
1975 | 0 | this->DebugBuffer = |
1976 | 0 | cmStrCat(this->DebugBuffer, "The file was not found.\n"); |
1977 | 0 | } |
1978 | 0 | } |
1979 | | |
1980 | | // Store the entry in the cache so it can be set by the user. |
1981 | 0 | std::string init; |
1982 | 0 | if (found) { |
1983 | 0 | init = cmSystemTools::GetFilenamePath(this->FileFound); |
1984 | 0 | } else { |
1985 | 0 | init = this->Variable + "-NOTFOUND"; |
1986 | 0 | } |
1987 | | // We force the value since we do not get here if it was already set. |
1988 | 0 | this->SetConfigDirCacheVariable(init); |
1989 | |
|
1990 | 0 | return found; |
1991 | 0 | } |
1992 | | |
1993 | | void cmFindPackageCommand::SetConfigDirCacheVariable(std::string const& value) |
1994 | 0 | { |
1995 | 0 | std::string const help = |
1996 | 0 | cmStrCat("The directory containing a CMake configuration file for ", |
1997 | 0 | this->Name, '.'); |
1998 | 0 | this->Makefile->AddCacheDefinition(this->Variable, value, help, |
1999 | 0 | cmStateEnums::PATH, true); |
2000 | 0 | if (this->Makefile->GetPolicyStatus(cmPolicies::CMP0126) == |
2001 | 0 | cmPolicies::NEW && |
2002 | 0 | this->Makefile->IsNormalDefinitionSet(this->Variable)) { |
2003 | 0 | this->Makefile->AddDefinition(this->Variable, value); |
2004 | 0 | } |
2005 | 0 | } |
2006 | | |
2007 | | bool cmFindPackageCommand::FindPrefixedConfig() |
2008 | 0 | { |
2009 | 0 | std::vector<std::string> const& prefixes = this->SearchPaths; |
2010 | 0 | return std::any_of( |
2011 | 0 | prefixes.begin(), prefixes.end(), |
2012 | 0 | [this](std::string const& p) -> bool { return this->SearchPrefix(p); }); |
2013 | 0 | } |
2014 | | |
2015 | | bool cmFindPackageCommand::FindFrameworkConfig() |
2016 | 0 | { |
2017 | 0 | std::vector<std::string> const& prefixes = this->SearchPaths; |
2018 | 0 | return std::any_of(prefixes.begin(), prefixes.end(), |
2019 | 0 | [this](std::string const& p) -> bool { |
2020 | 0 | return this->SearchFrameworkPrefix(p); |
2021 | 0 | }); |
2022 | 0 | } |
2023 | | |
2024 | | bool cmFindPackageCommand::FindAppBundleConfig() |
2025 | 0 | { |
2026 | 0 | std::vector<std::string> const& prefixes = this->SearchPaths; |
2027 | 0 | return std::any_of(prefixes.begin(), prefixes.end(), |
2028 | 0 | [this](std::string const& p) -> bool { |
2029 | 0 | return this->SearchAppBundlePrefix(p); |
2030 | 0 | }); |
2031 | 0 | } |
2032 | | |
2033 | | bool cmFindPackageCommand::FindEnvironmentConfig() |
2034 | 0 | { |
2035 | 0 | std::vector<std::string> const& prefixes = |
2036 | 0 | cmSystemTools::GetEnvPathNormalized("CPS_PATH"); |
2037 | 0 | return std::any_of(prefixes.begin(), prefixes.end(), |
2038 | 0 | [this](std::string const& p) -> bool { |
2039 | 0 | return this->SearchEnvironmentPrefix(p); |
2040 | 0 | }); |
2041 | 0 | } |
2042 | | |
2043 | | cmFindPackageCommand::AppendixMap cmFindPackageCommand::FindAppendices( |
2044 | | std::string const& base, cmPackageInfoReader const& baseReader) const |
2045 | 0 | { |
2046 | 0 | AppendixMap appendices; |
2047 | | |
2048 | | // Find package appendices. |
2049 | 0 | cmsys::Glob glob; |
2050 | 0 | glob.RecurseOff(); |
2051 | 0 | if (glob.FindFiles(cmStrCat(cmSystemTools::GetFilenamePath(base), "/"_s, |
2052 | 0 | cmSystemTools::GetFilenameWithoutExtension(base), |
2053 | 0 | "[-:]*.[Cc][Pp][Ss]"_s))) { |
2054 | | // Check glob results for valid appendices. |
2055 | 0 | for (std::string const& extra : glob.GetFiles()) { |
2056 | | // Exclude configuration-specific files for now; we look at them later |
2057 | | // when we load their respective configuration-agnostic appendices. |
2058 | 0 | if (extra.find('@') != std::string::npos) { |
2059 | 0 | continue; |
2060 | 0 | } |
2061 | | |
2062 | 0 | cmMakefile::CallRAII cs{ this->Makefile, extra, this->Status }; |
2063 | |
|
2064 | 0 | std::unique_ptr<cmPackageInfoReader> reader = |
2065 | 0 | cmPackageInfoReader::Read(this->Makefile, extra, &baseReader); |
2066 | |
|
2067 | 0 | if (reader && reader->GetName() == this->Name) { |
2068 | 0 | std::vector<std::string> components = reader->GetComponentNames(); |
2069 | 0 | Appendix appendix{ std::move(reader), std::move(components) }; |
2070 | 0 | appendices.emplace(extra, std::move(appendix)); |
2071 | 0 | } |
2072 | 0 | } |
2073 | 0 | } |
2074 | |
|
2075 | 0 | return appendices; |
2076 | 0 | } |
2077 | | |
2078 | | bool cmFindPackageCommand::ReadListFile(std::string const& f, |
2079 | | PolicyScopeRule const psr) |
2080 | 0 | { |
2081 | 0 | bool const noPolicyScope = !this->PolicyScope || psr == NoPolicyScope; |
2082 | |
|
2083 | 0 | using ITScope = cmMakefile::ImportedTargetScope; |
2084 | 0 | ITScope scope = this->GlobalScope ? ITScope::Global : ITScope::Local; |
2085 | 0 | cmMakefile::SetGlobalTargetImportScope globScope(this->Makefile, scope); |
2086 | |
|
2087 | 0 | auto oldUnwind = this->Makefile->GetStateSnapshot().GetUnwindType(); |
2088 | | |
2089 | | // This allows child snapshots to inherit the CAN_UNWIND state from us, we'll |
2090 | | // reset it immediately after the dependent file is done |
2091 | 0 | this->Makefile->GetStateSnapshot().SetUnwindType(cmStateEnums::CAN_UNWIND); |
2092 | 0 | bool result = this->Makefile->ReadDependentFile(f, noPolicyScope); |
2093 | |
|
2094 | 0 | this->Makefile->GetStateSnapshot().SetUnwindType(oldUnwind); |
2095 | 0 | this->Makefile->GetStateSnapshot().SetUnwindState( |
2096 | 0 | cmStateEnums::NOT_UNWINDING); |
2097 | |
|
2098 | 0 | if (!result) { |
2099 | 0 | std::string const e = |
2100 | 0 | cmStrCat("Error reading CMake code from \"", f, "\"."); |
2101 | 0 | this->SetError(e); |
2102 | 0 | } |
2103 | |
|
2104 | 0 | return result; |
2105 | 0 | } |
2106 | | |
2107 | | bool cmFindPackageCommand::ReadPackage() |
2108 | 0 | { |
2109 | | // Resolve any transitive dependencies for the root file. |
2110 | 0 | if (!FindPackageDependencies(this->FileFound, *this->CpsReader, |
2111 | 0 | this->Required)) { |
2112 | 0 | return false; |
2113 | 0 | } |
2114 | | |
2115 | 0 | bool const hasComponentsRequested = |
2116 | 0 | !this->RequiredComponents.empty() || !this->OptionalComponents.empty(); |
2117 | |
|
2118 | 0 | cmMakefile::CallRAII cs{ this->Makefile, this->FileFound, this->Status }; |
2119 | 0 | cmMakefile::PolicyPushPop ps{ this->Makefile }; |
2120 | |
|
2121 | 0 | this->Makefile->SetPolicy(cmPolicies::CMP0200, cmPolicies::NEW); |
2122 | | |
2123 | | // Loop over appendices. |
2124 | 0 | auto iter = this->CpsAppendices.begin(); |
2125 | 0 | while (iter != this->CpsAppendices.end()) { |
2126 | 0 | RequiredStatus required = RequiredStatus::Optional; |
2127 | 0 | bool important = false; |
2128 | | |
2129 | | // Check if this appendix provides any requested components. |
2130 | 0 | if (hasComponentsRequested) { |
2131 | 0 | auto providesAny = [&iter]( |
2132 | 0 | std::set<std::string> const& desiredComponents) { |
2133 | 0 | return std::any_of(iter->second.Components.begin(), |
2134 | 0 | iter->second.Components.end(), |
2135 | 0 | [&desiredComponents](std::string const& component) { |
2136 | 0 | return cm::contains(desiredComponents, component); |
2137 | 0 | }); |
2138 | 0 | }; |
2139 | |
|
2140 | 0 | if (providesAny(this->RequiredComponents)) { |
2141 | 0 | important = true; |
2142 | 0 | required = this->Required; |
2143 | 0 | } else if (!providesAny(this->OptionalComponents)) { |
2144 | | // This appendix doesn't provide any requested components; remove it |
2145 | | // from the set to be imported. |
2146 | 0 | iter = this->CpsAppendices.erase(iter); |
2147 | 0 | continue; |
2148 | 0 | } |
2149 | 0 | } |
2150 | | |
2151 | | // Resolve any transitive dependencies for the appendix. |
2152 | 0 | if (!this->FindPackageDependencies(iter->first, iter->second, required)) { |
2153 | 0 | if (important) { |
2154 | | // Some dependencies are missing, and we need(ed) this appendix; fail. |
2155 | 0 | return false; |
2156 | 0 | } |
2157 | | |
2158 | | // Some dependencies are missing, but we don't need this appendix; remove |
2159 | | // it from the set to be imported. |
2160 | 0 | iter = this->CpsAppendices.erase(iter); |
2161 | 0 | } else { |
2162 | 0 | ++iter; |
2163 | 0 | } |
2164 | 0 | } |
2165 | | |
2166 | | // If we made it here, we want to actually import something, but we also |
2167 | | // need to ensure we don't try to import the same file more than once (which |
2168 | | // will fail due to the targets already existing). Retrieve the package state |
2169 | | // so we can record what we're doing. |
2170 | 0 | cmPackageState& state = |
2171 | 0 | this->Makefile->GetStateSnapshot().GetPackageState(this->FileFound); |
2172 | | |
2173 | | // Import targets from root file. |
2174 | 0 | if (!this->ImportPackageTargets(state, this->FileFound, *this->CpsReader)) { |
2175 | 0 | return false; |
2176 | 0 | } |
2177 | | |
2178 | | // Import targets from appendices. |
2179 | | // NOLINTNEXTLINE(readability-use-anyofallof) |
2180 | 0 | for (auto const& appendix : this->CpsAppendices) { |
2181 | 0 | cmMakefile::CallRAII appendixScope{ this->Makefile, appendix.first, |
2182 | 0 | this->Status }; |
2183 | 0 | if (!this->ImportPackageTargets(state, appendix.first, appendix.second)) { |
2184 | 0 | return false; |
2185 | 0 | } |
2186 | 0 | } |
2187 | | |
2188 | 0 | return true; |
2189 | 0 | } |
2190 | | |
2191 | | bool cmFindPackageCommand::FindPackageDependencies( |
2192 | | std::string const& filePath, cmPackageInfoReader const& reader, |
2193 | | RequiredStatus required) |
2194 | 0 | { |
2195 | | // Get package requirements. |
2196 | 0 | for (cmPackageRequirement const& dep : reader.GetRequirements()) { |
2197 | 0 | cmExecutionStatus status{ *this->Makefile }; |
2198 | 0 | cmMakefile::CallRAII scope{ this->Makefile, filePath, status }; |
2199 | | |
2200 | | // For each requirement, set up a nested instance to find it. |
2201 | 0 | cmFindPackageCommand fp{ status }; |
2202 | 0 | fp.InheritOptions(this); |
2203 | |
|
2204 | 0 | fp.Name = dep.Name; |
2205 | 0 | fp.Required = required; |
2206 | 0 | fp.UseFindModules = false; |
2207 | 0 | fp.UseCpsFiles = true; |
2208 | |
|
2209 | 0 | fp.Version = dep.Version; |
2210 | 0 | fp.VersionComplete = dep.Version; |
2211 | 0 | fp.VersionCount = |
2212 | 0 | parseVersion(fp.Version, fp.VersionMajor, fp.VersionMinor, |
2213 | 0 | fp.VersionPatch, fp.VersionTweak); |
2214 | |
|
2215 | 0 | fp.Components = cmJoin(cmMakeRange(dep.Components), ";"_s); |
2216 | 0 | fp.OptionalComponents = |
2217 | 0 | std::set<std::string>{ dep.Components.begin(), dep.Components.end() }; |
2218 | 0 | fp.RequiredTargets = fp.OptionalComponents; |
2219 | | |
2220 | | // TODO set hints |
2221 | | |
2222 | | // Try to find the requirement; fail if we can't. |
2223 | 0 | if (!fp.FindPackage() || fp.FileFound.empty()) { |
2224 | 0 | this->SetError(cmStrCat("could not find "_s, dep.Name, |
2225 | 0 | ", required by "_s, this->Name, '.')); |
2226 | 0 | return false; |
2227 | 0 | } |
2228 | 0 | } |
2229 | | |
2230 | | // All requirements (if any) were found. |
2231 | 0 | return true; |
2232 | 0 | } |
2233 | | |
2234 | | bool cmFindPackageCommand::ImportPackageTargets(cmPackageState& packageState, |
2235 | | std::string const& filePath, |
2236 | | cmPackageInfoReader& reader) |
2237 | 0 | { |
2238 | | // Check if we've already imported this file. |
2239 | 0 | std::string fileName = cmSystemTools::GetFilenameName(filePath); |
2240 | 0 | if (cm::contains(packageState.ImportedFiles, fileName)) { |
2241 | 0 | return true; |
2242 | 0 | } |
2243 | | |
2244 | | // Import base file. |
2245 | 0 | if (!reader.ImportTargets(this->Makefile, this->Status, this->GlobalScope)) { |
2246 | 0 | return false; |
2247 | 0 | } |
2248 | | |
2249 | | // Find supplemental configuration files. |
2250 | 0 | cmsys::Glob glob; |
2251 | 0 | glob.RecurseOff(); |
2252 | 0 | if (glob.FindFiles( |
2253 | 0 | cmStrCat(cmSystemTools::GetFilenamePath(filePath), '/', |
2254 | 0 | cmSystemTools::GetFilenameWithoutExtension(filePath), |
2255 | 0 | "@*.[Cc][Pp][Ss]"_s))) { |
2256 | | |
2257 | | // Try to read supplemental data from each file found. |
2258 | 0 | for (std::string const& extra : glob.GetFiles()) { |
2259 | 0 | cmMakefile::CallRAII cs{ this->Makefile, extra, this->Status }; |
2260 | |
|
2261 | 0 | std::unique_ptr<cmPackageInfoReader> configReader = |
2262 | 0 | cmPackageInfoReader::Read(this->Makefile, extra, &reader); |
2263 | 0 | if (configReader && configReader->GetName() == this->Name) { |
2264 | 0 | if (!configReader->ImportTargetConfigurations(this->Makefile, |
2265 | 0 | this->Status)) { |
2266 | 0 | return false; |
2267 | 0 | } |
2268 | 0 | } |
2269 | 0 | } |
2270 | 0 | } |
2271 | | |
2272 | 0 | packageState.ImportedFiles.emplace(std::move(fileName)); |
2273 | 0 | return true; |
2274 | 0 | } |
2275 | | |
2276 | | void cmFindPackageCommand::AppendToFoundProperty(bool const found) |
2277 | 0 | { |
2278 | 0 | cmList foundContents; |
2279 | 0 | cmValue foundProp = |
2280 | 0 | this->Makefile->GetState()->GetGlobalProperty("PACKAGES_FOUND"); |
2281 | 0 | if (!foundProp.IsEmpty()) { |
2282 | 0 | foundContents.assign(*foundProp); |
2283 | 0 | foundContents.remove_items({ this->Name }); |
2284 | 0 | } |
2285 | |
|
2286 | 0 | cmList notFoundContents; |
2287 | 0 | cmValue notFoundProp = |
2288 | 0 | this->Makefile->GetState()->GetGlobalProperty("PACKAGES_NOT_FOUND"); |
2289 | 0 | if (!notFoundProp.IsEmpty()) { |
2290 | 0 | notFoundContents.assign(*notFoundProp); |
2291 | 0 | notFoundContents.remove_items({ this->Name }); |
2292 | 0 | } |
2293 | |
|
2294 | 0 | if (found) { |
2295 | 0 | foundContents.push_back(this->Name); |
2296 | 0 | } else { |
2297 | 0 | notFoundContents.push_back(this->Name); |
2298 | 0 | } |
2299 | |
|
2300 | 0 | this->Makefile->GetState()->SetGlobalProperty("PACKAGES_FOUND", |
2301 | 0 | foundContents.to_string()); |
2302 | |
|
2303 | 0 | this->Makefile->GetState()->SetGlobalProperty("PACKAGES_NOT_FOUND", |
2304 | 0 | notFoundContents.to_string()); |
2305 | 0 | } |
2306 | | |
2307 | | void cmFindPackageCommand::AppendSuccessInformation() |
2308 | 0 | { |
2309 | 0 | { |
2310 | 0 | std::string const transitivePropName = |
2311 | 0 | cmStrCat("_CMAKE_", this->Name, "_TRANSITIVE_DEPENDENCY"); |
2312 | 0 | this->Makefile->GetState()->SetGlobalProperty(transitivePropName, "False"); |
2313 | 0 | } |
2314 | 0 | std::string const found = cmStrCat(this->Name, "_FOUND"); |
2315 | 0 | std::string const upperFound = cmSystemTools::UpperCase(found); |
2316 | |
|
2317 | 0 | bool const upperResult = this->Makefile->IsOn(upperFound); |
2318 | 0 | bool const result = this->Makefile->IsOn(found); |
2319 | 0 | bool const packageFound = (result || upperResult); |
2320 | |
|
2321 | 0 | this->AppendToFoundProperty(packageFound); |
2322 | | |
2323 | | // Record whether the find was quiet or not, so this can be used |
2324 | | // e.g. in FeatureSummary.cmake |
2325 | 0 | std::string const quietInfoPropName = |
2326 | 0 | cmStrCat("_CMAKE_", this->Name, "_QUIET"); |
2327 | 0 | this->Makefile->GetState()->SetGlobalProperty( |
2328 | 0 | quietInfoPropName, this->Quiet ? "TRUE" : "FALSE"); |
2329 | | |
2330 | | // set a global property to record the required version of this package |
2331 | 0 | std::string const versionInfoPropName = |
2332 | 0 | cmStrCat("_CMAKE_", this->Name, "_REQUIRED_VERSION"); |
2333 | 0 | std::string versionInfo; |
2334 | 0 | if (!this->VersionRange.empty()) { |
2335 | 0 | versionInfo = this->VersionRange; |
2336 | 0 | } else if (!this->Version.empty()) { |
2337 | 0 | versionInfo = |
2338 | 0 | cmStrCat(this->VersionExact ? "==" : ">=", ' ', this->Version); |
2339 | 0 | } |
2340 | 0 | this->Makefile->GetState()->SetGlobalProperty(versionInfoPropName, |
2341 | 0 | versionInfo); |
2342 | 0 | if (this->IsRequired()) { |
2343 | 0 | std::string const requiredInfoPropName = |
2344 | 0 | cmStrCat("_CMAKE_", this->Name, "_TYPE"); |
2345 | 0 | this->Makefile->GetState()->SetGlobalProperty(requiredInfoPropName, |
2346 | 0 | "REQUIRED"); |
2347 | 0 | } |
2348 | 0 | } |
2349 | | |
2350 | | void cmFindPackageCommand::PushFindPackageRootPathStack() |
2351 | 0 | { |
2352 | | // Allocate a PACKAGE_ROOT_PATH for the current find_package call. |
2353 | 0 | this->Makefile->FindPackageRootPathStack.emplace_back(); |
2354 | 0 | std::vector<std::string>& rootPaths = |
2355 | 0 | this->Makefile->FindPackageRootPathStack.back(); |
2356 | | |
2357 | | // Add root paths from <PackageName>_ROOT CMake and environment variables, |
2358 | | // subject to CMP0074. |
2359 | 0 | std::string const rootVar = this->Name + "_ROOT"; |
2360 | 0 | cmValue rootDef = this->Makefile->GetDefinition(rootVar); |
2361 | 0 | if (rootDef && rootDef.IsEmpty()) { |
2362 | 0 | rootDef = nullptr; |
2363 | 0 | } |
2364 | 0 | cm::optional<std::string> rootEnv = cmSystemTools::GetEnvVar(rootVar); |
2365 | 0 | if (rootEnv && rootEnv->empty()) { |
2366 | 0 | rootEnv = cm::nullopt; |
2367 | 0 | } |
2368 | 0 | switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0074)) { |
2369 | 0 | case cmPolicies::WARN: |
2370 | 0 | this->Makefile->MaybeWarnCMP0074(rootVar, rootDef, rootEnv); |
2371 | 0 | CM_FALLTHROUGH; |
2372 | 0 | case cmPolicies::OLD: |
2373 | | // OLD behavior is to ignore the <PackageName>_ROOT variables. |
2374 | 0 | return; |
2375 | 0 | case cmPolicies::NEW: { |
2376 | | // NEW behavior is to honor the <PackageName>_ROOT variables. |
2377 | 0 | } break; |
2378 | 0 | } |
2379 | | |
2380 | | // Add root paths from <PACKAGENAME>_ROOT CMake and environment variables, |
2381 | | // if they are different than <PackageName>_ROOT, and subject to CMP0144. |
2382 | 0 | std::string const rootVAR = cmSystemTools::UpperCase(rootVar); |
2383 | 0 | cmValue rootDEF; |
2384 | 0 | cm::optional<std::string> rootENV; |
2385 | 0 | if (rootVAR != rootVar) { |
2386 | 0 | rootDEF = this->Makefile->GetDefinition(rootVAR); |
2387 | 0 | if (rootDEF && (rootDEF.IsEmpty() || rootDEF == rootDef)) { |
2388 | 0 | rootDEF = nullptr; |
2389 | 0 | } |
2390 | 0 | rootENV = cmSystemTools::GetEnvVar(rootVAR); |
2391 | 0 | if (rootENV && (rootENV->empty() || rootENV == rootEnv)) { |
2392 | 0 | rootENV = cm::nullopt; |
2393 | 0 | } |
2394 | 0 | } |
2395 | |
|
2396 | 0 | switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0144)) { |
2397 | 0 | case cmPolicies::WARN: |
2398 | 0 | this->Makefile->MaybeWarnCMP0144(rootVAR, rootDEF, rootENV); |
2399 | 0 | CM_FALLTHROUGH; |
2400 | 0 | case cmPolicies::OLD: |
2401 | | // OLD behavior is to ignore the <PACKAGENAME>_ROOT variables. |
2402 | 0 | rootDEF = nullptr; |
2403 | 0 | rootENV = cm::nullopt; |
2404 | 0 | break; |
2405 | 0 | case cmPolicies::NEW: { |
2406 | | // NEW behavior is to honor the <PACKAGENAME>_ROOT variables. |
2407 | 0 | } break; |
2408 | 0 | } |
2409 | | |
2410 | 0 | if (rootDef) { |
2411 | 0 | cmExpandList(*rootDef, rootPaths); |
2412 | 0 | } |
2413 | 0 | if (rootDEF) { |
2414 | 0 | cmExpandList(*rootDEF, rootPaths); |
2415 | 0 | } |
2416 | 0 | if (rootEnv) { |
2417 | 0 | std::vector<std::string> p = |
2418 | 0 | cmSystemTools::SplitEnvPathNormalized(*rootEnv); |
2419 | 0 | std::move(p.begin(), p.end(), std::back_inserter(rootPaths)); |
2420 | 0 | } |
2421 | 0 | if (rootENV) { |
2422 | 0 | std::vector<std::string> p = |
2423 | 0 | cmSystemTools::SplitEnvPathNormalized(*rootENV); |
2424 | 0 | std::move(p.begin(), p.end(), std::back_inserter(rootPaths)); |
2425 | 0 | } |
2426 | 0 | } |
2427 | | |
2428 | | void cmFindPackageCommand::PopFindPackageRootPathStack() |
2429 | 0 | { |
2430 | 0 | this->Makefile->FindPackageRootPathStack.pop_back(); |
2431 | 0 | } |
2432 | | |
2433 | | void cmFindPackageCommand::ComputePrefixes() |
2434 | 0 | { |
2435 | 0 | this->FillPrefixesPackageRedirect(); |
2436 | |
|
2437 | 0 | if (!this->NoDefaultPath) { |
2438 | 0 | if (!this->NoPackageRootPath) { |
2439 | 0 | this->FillPrefixesPackageRoot(); |
2440 | 0 | } |
2441 | 0 | if (!this->NoCMakePath) { |
2442 | 0 | this->FillPrefixesCMakeVariable(); |
2443 | 0 | } |
2444 | 0 | if (!this->NoCMakeEnvironmentPath) { |
2445 | 0 | this->FillPrefixesCMakeEnvironment(); |
2446 | 0 | } |
2447 | 0 | } |
2448 | |
|
2449 | 0 | this->FillPrefixesUserHints(); |
2450 | |
|
2451 | 0 | if (!this->NoDefaultPath) { |
2452 | 0 | if (!this->NoSystemEnvironmentPath) { |
2453 | 0 | this->FillPrefixesSystemEnvironment(); |
2454 | 0 | } |
2455 | 0 | if (!this->NoUserRegistry) { |
2456 | 0 | this->FillPrefixesUserRegistry(); |
2457 | 0 | } |
2458 | 0 | if (!this->NoCMakeSystemPath) { |
2459 | 0 | this->FillPrefixesCMakeSystemVariable(); |
2460 | 0 | } |
2461 | 0 | if (!this->NoSystemRegistry) { |
2462 | 0 | this->FillPrefixesSystemRegistry(); |
2463 | 0 | } |
2464 | 0 | } |
2465 | 0 | this->FillPrefixesUserGuess(); |
2466 | |
|
2467 | 0 | this->ComputeFinalPaths(IgnorePaths::No, &this->DebugBuffer); |
2468 | 0 | } |
2469 | | |
2470 | | void cmFindPackageCommand::FillPrefixesPackageRedirect() |
2471 | 0 | { |
2472 | 0 | cmSearchPath& paths = this->LabeledPaths[PathLabel::PackageRedirect]; |
2473 | |
|
2474 | 0 | auto const redirectDir = |
2475 | 0 | this->Makefile->GetDefinition("CMAKE_FIND_PACKAGE_REDIRECTS_DIR"); |
2476 | 0 | if (redirectDir && !redirectDir->empty()) { |
2477 | 0 | paths.AddPath(*redirectDir); |
2478 | 0 | } |
2479 | 0 | if (this->DebugModeEnabled()) { |
2480 | 0 | std::string debugBuffer = |
2481 | 0 | "The internally managed CMAKE_FIND_PACKAGE_REDIRECTS_DIR.\n"; |
2482 | 0 | collectPathsForDebug(debugBuffer, paths); |
2483 | 0 | this->DebugBuffer = cmStrCat(this->DebugBuffer, debugBuffer); |
2484 | 0 | } |
2485 | 0 | } |
2486 | | |
2487 | | void cmFindPackageCommand::FillPrefixesPackageRoot() |
2488 | 0 | { |
2489 | 0 | cmSearchPath& paths = this->LabeledPaths[PathLabel::PackageRoot]; |
2490 | | |
2491 | | // Add the PACKAGE_ROOT_PATH from each enclosing find_package call. |
2492 | 0 | for (auto pkgPaths = this->Makefile->FindPackageRootPathStack.rbegin(); |
2493 | 0 | pkgPaths != this->Makefile->FindPackageRootPathStack.rend(); |
2494 | 0 | ++pkgPaths) { |
2495 | 0 | for (std::string const& path : *pkgPaths) { |
2496 | 0 | paths.AddPath(path); |
2497 | 0 | } |
2498 | 0 | } |
2499 | 0 | if (this->DebugModeEnabled()) { |
2500 | 0 | std::string debugBuffer = "<PackageName>_ROOT CMake variable " |
2501 | 0 | "[CMAKE_FIND_USE_PACKAGE_ROOT_PATH].\n"; |
2502 | 0 | collectPathsForDebug(debugBuffer, paths); |
2503 | 0 | this->DebugBuffer = cmStrCat(this->DebugBuffer, debugBuffer); |
2504 | 0 | } |
2505 | 0 | } |
2506 | | |
2507 | | void cmFindPackageCommand::FillPrefixesCMakeEnvironment() |
2508 | 0 | { |
2509 | 0 | cmSearchPath& paths = this->LabeledPaths[PathLabel::CMakeEnvironment]; |
2510 | 0 | std::string debugBuffer; |
2511 | 0 | std::size_t debugOffset = 0; |
2512 | | |
2513 | | // Check the environment variable with the same name as the cache |
2514 | | // entry. |
2515 | 0 | paths.AddEnvPath(this->Variable); |
2516 | 0 | if (this->DebugModeEnabled()) { |
2517 | 0 | debugBuffer = cmStrCat("Env variable ", this->Variable, |
2518 | 0 | " [CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH].\n"); |
2519 | 0 | debugOffset = collectPathsForDebug(debugBuffer, paths); |
2520 | 0 | } |
2521 | | |
2522 | | // And now the general CMake environment variables |
2523 | 0 | paths.AddEnvPath("CMAKE_PREFIX_PATH"); |
2524 | 0 | if (this->DebugModeEnabled()) { |
2525 | 0 | debugBuffer = cmStrCat(debugBuffer, |
2526 | 0 | "CMAKE_PREFIX_PATH env variable " |
2527 | 0 | "[CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH].\n"); |
2528 | 0 | debugOffset = collectPathsForDebug(debugBuffer, paths, debugOffset); |
2529 | 0 | } |
2530 | |
|
2531 | 0 | paths.AddEnvPath("CMAKE_FRAMEWORK_PATH"); |
2532 | 0 | paths.AddEnvPath("CMAKE_APPBUNDLE_PATH"); |
2533 | 0 | if (this->DebugModeEnabled()) { |
2534 | 0 | debugBuffer = |
2535 | 0 | cmStrCat(debugBuffer, |
2536 | 0 | "CMAKE_FRAMEWORK_PATH and CMAKE_APPBUNDLE_PATH env " |
2537 | 0 | "variables [CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH].\n"); |
2538 | 0 | collectPathsForDebug(debugBuffer, paths, debugOffset); |
2539 | 0 | this->DebugBuffer = cmStrCat(this->DebugBuffer, debugBuffer); |
2540 | 0 | } |
2541 | 0 | } |
2542 | | |
2543 | | void cmFindPackageCommand::FillPrefixesCMakeVariable() |
2544 | 0 | { |
2545 | 0 | cmSearchPath& paths = this->LabeledPaths[PathLabel::CMake]; |
2546 | 0 | std::string debugBuffer; |
2547 | 0 | std::size_t debugOffset = 0; |
2548 | |
|
2549 | 0 | paths.AddCMakePath("CMAKE_PREFIX_PATH"); |
2550 | 0 | if (this->DebugModeEnabled()) { |
2551 | 0 | debugBuffer = "CMAKE_PREFIX_PATH variable [CMAKE_FIND_USE_CMAKE_PATH].\n"; |
2552 | 0 | debugOffset = collectPathsForDebug(debugBuffer, paths); |
2553 | 0 | } |
2554 | |
|
2555 | 0 | paths.AddCMakePath("CMAKE_FRAMEWORK_PATH"); |
2556 | 0 | paths.AddCMakePath("CMAKE_APPBUNDLE_PATH"); |
2557 | 0 | if (this->DebugModeEnabled()) { |
2558 | 0 | debugBuffer = |
2559 | 0 | cmStrCat(debugBuffer, |
2560 | 0 | "CMAKE_FRAMEWORK_PATH and CMAKE_APPBUNDLE_PATH variables " |
2561 | 0 | "[CMAKE_FIND_USE_CMAKE_PATH].\n"); |
2562 | 0 | collectPathsForDebug(debugBuffer, paths, debugOffset); |
2563 | 0 | this->DebugBuffer = cmStrCat(this->DebugBuffer, debugBuffer); |
2564 | 0 | } |
2565 | 0 | } |
2566 | | |
2567 | | void cmFindPackageCommand::FillPrefixesSystemEnvironment() |
2568 | 0 | { |
2569 | 0 | cmSearchPath& paths = this->LabeledPaths[PathLabel::SystemEnvironment]; |
2570 | | |
2571 | | // Use the system search path to generate prefixes. |
2572 | | // Relative paths are interpreted with respect to the current |
2573 | | // working directory. |
2574 | 0 | std::vector<std::string> envPATH = |
2575 | 0 | cmSystemTools::GetEnvPathNormalized("PATH"); |
2576 | 0 | for (std::string const& i : envPATH) { |
2577 | | // If the path is a PREFIX/bin case then add its parent instead. |
2578 | 0 | if ((cmHasLiteralSuffix(i, "/bin")) || (cmHasLiteralSuffix(i, "/sbin"))) { |
2579 | 0 | paths.AddPath(cmSystemTools::GetFilenamePath(i)); |
2580 | 0 | } else { |
2581 | 0 | paths.AddPath(i); |
2582 | 0 | } |
2583 | 0 | } |
2584 | 0 | if (this->DebugModeEnabled()) { |
2585 | 0 | std::string debugBuffer = "Standard system environment variables " |
2586 | 0 | "[CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH].\n"; |
2587 | 0 | collectPathsForDebug(debugBuffer, paths); |
2588 | 0 | this->DebugBuffer = cmStrCat(this->DebugBuffer, debugBuffer); |
2589 | 0 | } |
2590 | 0 | } |
2591 | | |
2592 | | void cmFindPackageCommand::FillPrefixesUserRegistry() |
2593 | 0 | { |
2594 | | #if defined(_WIN32) && !defined(__CYGWIN__) |
2595 | | this->LoadPackageRegistryWinUser(); |
2596 | | #elif defined(__HAIKU__) |
2597 | | char dir[B_PATH_NAME_LENGTH]; |
2598 | | if (find_directory(B_USER_SETTINGS_DIRECTORY, -1, false, dir, sizeof(dir)) == |
2599 | | B_OK) { |
2600 | | std::string fname = cmStrCat(dir, "/cmake/packages/", Name); |
2601 | | this->LoadPackageRegistryDir(fname, |
2602 | | this->LabeledPaths[PathLabel::UserRegistry]); |
2603 | | } |
2604 | | #else |
2605 | 0 | std::string dir; |
2606 | 0 | if (cmSystemTools::GetEnv("HOME", dir)) { |
2607 | 0 | dir += "/.cmake/packages/"; |
2608 | 0 | dir += this->Name; |
2609 | 0 | this->LoadPackageRegistryDir(dir, |
2610 | 0 | this->LabeledPaths[PathLabel::UserRegistry]); |
2611 | 0 | } |
2612 | 0 | #endif |
2613 | 0 | if (this->DebugModeEnabled()) { |
2614 | 0 | std::string debugBuffer = |
2615 | 0 | "CMake User Package Registry [CMAKE_FIND_USE_PACKAGE_REGISTRY].\n"; |
2616 | 0 | collectPathsForDebug(debugBuffer, |
2617 | 0 | this->LabeledPaths[PathLabel::UserRegistry]); |
2618 | 0 | this->DebugBuffer = cmStrCat(this->DebugBuffer, debugBuffer); |
2619 | 0 | } |
2620 | 0 | } |
2621 | | |
2622 | | void cmFindPackageCommand::FillPrefixesSystemRegistry() |
2623 | 0 | { |
2624 | 0 | if (this->NoSystemRegistry || this->NoDefaultPath) { |
2625 | 0 | return; |
2626 | 0 | } |
2627 | | |
2628 | | #if defined(_WIN32) && !defined(__CYGWIN__) |
2629 | | this->LoadPackageRegistryWinSystem(); |
2630 | | #endif |
2631 | | |
2632 | 0 | if (this->DebugModeEnabled()) { |
2633 | 0 | std::string debugBuffer = |
2634 | 0 | "CMake System Package Registry " |
2635 | 0 | "[CMAKE_FIND_PACKAGE_NO_SYSTEM_PACKAGE_REGISTRY].\n"; |
2636 | 0 | collectPathsForDebug(debugBuffer, |
2637 | 0 | this->LabeledPaths[PathLabel::SystemRegistry]); |
2638 | 0 | this->DebugBuffer = cmStrCat(this->DebugBuffer, debugBuffer); |
2639 | 0 | } |
2640 | 0 | } |
2641 | | |
2642 | | #if defined(_WIN32) && !defined(__CYGWIN__) |
2643 | | void cmFindPackageCommand::LoadPackageRegistryWinUser() |
2644 | | { |
2645 | | // HKEY_CURRENT_USER\\Software shares 32-bit and 64-bit views. |
2646 | | this->LoadPackageRegistryWin(true, 0, |
2647 | | this->LabeledPaths[PathLabel::UserRegistry]); |
2648 | | } |
2649 | | |
2650 | | void cmFindPackageCommand::LoadPackageRegistryWinSystem() |
2651 | | { |
2652 | | cmSearchPath& paths = this->LabeledPaths[PathLabel::SystemRegistry]; |
2653 | | |
2654 | | // HKEY_LOCAL_MACHINE\\SOFTWARE has separate 32-bit and 64-bit views. |
2655 | | // Prefer the target platform view first. |
2656 | | if (this->Makefile->PlatformIs64Bit()) { |
2657 | | this->LoadPackageRegistryWin(false, KEY_WOW64_64KEY, paths); |
2658 | | this->LoadPackageRegistryWin(false, KEY_WOW64_32KEY, paths); |
2659 | | } else { |
2660 | | this->LoadPackageRegistryWin(false, KEY_WOW64_32KEY, paths); |
2661 | | this->LoadPackageRegistryWin(false, KEY_WOW64_64KEY, paths); |
2662 | | } |
2663 | | } |
2664 | | |
2665 | | void cmFindPackageCommand::LoadPackageRegistryWin(bool const user, |
2666 | | unsigned int const view, |
2667 | | cmSearchPath& outPaths) |
2668 | | { |
2669 | | std::wstring key = L"Software\\Kitware\\CMake\\Packages\\"; |
2670 | | key += cmsys::Encoding::ToWide(this->Name); |
2671 | | std::set<std::wstring> bad; |
2672 | | HKEY hKey; |
2673 | | if (RegOpenKeyExW(user ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE, key.c_str(), |
2674 | | 0, KEY_QUERY_VALUE | view, &hKey) == ERROR_SUCCESS) { |
2675 | | DWORD valueType = REG_NONE; |
2676 | | wchar_t name[16383]; // RegEnumValue docs limit name to 32767 _bytes_ |
2677 | | std::vector<wchar_t> data(512); |
2678 | | bool done = false; |
2679 | | DWORD index = 0; |
2680 | | while (!done) { |
2681 | | DWORD nameSize = static_cast<DWORD>(sizeof(name)); |
2682 | | DWORD dataSize = static_cast<DWORD>(data.size() * sizeof(data[0])); |
2683 | | switch (RegEnumValueW(hKey, index, name, &nameSize, 0, &valueType, |
2684 | | (BYTE*)&data[0], &dataSize)) { |
2685 | | case ERROR_SUCCESS: |
2686 | | ++index; |
2687 | | if (valueType == REG_SZ) { |
2688 | | data[dataSize] = 0; |
2689 | | if (!this->CheckPackageRegistryEntry( |
2690 | | cmsys::Encoding::ToNarrow(&data[0]), outPaths)) { |
2691 | | // The entry is invalid. |
2692 | | bad.insert(name); |
2693 | | } |
2694 | | } |
2695 | | break; |
2696 | | case ERROR_MORE_DATA: |
2697 | | data.resize((dataSize + sizeof(data[0]) - 1) / sizeof(data[0])); |
2698 | | break; |
2699 | | case ERROR_NO_MORE_ITEMS: |
2700 | | default: |
2701 | | done = true; |
2702 | | break; |
2703 | | } |
2704 | | } |
2705 | | RegCloseKey(hKey); |
2706 | | } |
2707 | | |
2708 | | // Remove bad values if possible. |
2709 | | if (user && !bad.empty() && |
2710 | | RegOpenKeyExW(HKEY_CURRENT_USER, key.c_str(), 0, KEY_SET_VALUE | view, |
2711 | | &hKey) == ERROR_SUCCESS) { |
2712 | | for (std::wstring const& v : bad) { |
2713 | | RegDeleteValueW(hKey, v.c_str()); |
2714 | | } |
2715 | | RegCloseKey(hKey); |
2716 | | } |
2717 | | } |
2718 | | |
2719 | | #else |
2720 | | void cmFindPackageCommand::LoadPackageRegistryDir(std::string const& dir, |
2721 | | cmSearchPath& outPaths) |
2722 | 0 | { |
2723 | 0 | cmsys::Directory files; |
2724 | 0 | if (!files.Load(dir)) { |
2725 | 0 | return; |
2726 | 0 | } |
2727 | | |
2728 | 0 | std::string fname; |
2729 | 0 | for (unsigned long i = 0; i < files.GetNumberOfFiles(); ++i) { |
2730 | 0 | fname = cmStrCat(dir, '/', files.GetFile(i)); |
2731 | |
|
2732 | 0 | if (!cmSystemTools::FileIsDirectory(fname)) { |
2733 | | // Hold this file hostage until it behaves. |
2734 | 0 | cmFindPackageCommandHoldFile holdFile(fname.c_str()); |
2735 | | |
2736 | | // Load the file. |
2737 | 0 | cmsys::ifstream fin(fname.c_str(), std::ios::in | std::ios::binary); |
2738 | 0 | std::string fentry; |
2739 | 0 | if (fin && cmSystemTools::GetLineFromStream(fin, fentry) && |
2740 | 0 | this->CheckPackageRegistryEntry(fentry, outPaths)) { |
2741 | | // The file references an existing package, so release it. |
2742 | 0 | holdFile.Release(); |
2743 | 0 | } |
2744 | 0 | } |
2745 | 0 | } |
2746 | | |
2747 | | // TODO: Wipe out the directory if it is empty. |
2748 | 0 | } |
2749 | | #endif |
2750 | | |
2751 | | bool cmFindPackageCommand::CheckPackageRegistryEntry(std::string const& fname, |
2752 | | cmSearchPath& outPaths) |
2753 | 0 | { |
2754 | | // Parse the content of one package registry entry. |
2755 | 0 | if (cmSystemTools::FileIsFullPath(fname)) { |
2756 | | // The first line in the stream is the full path to a file or |
2757 | | // directory containing the package. |
2758 | 0 | if (cmSystemTools::FileExists(fname)) { |
2759 | | // The path exists. Look for the package here. |
2760 | 0 | if (!cmSystemTools::FileIsDirectory(fname)) { |
2761 | 0 | outPaths.AddPath(cmSystemTools::GetFilenamePath(fname)); |
2762 | 0 | } else { |
2763 | 0 | outPaths.AddPath(fname); |
2764 | 0 | } |
2765 | 0 | return true; |
2766 | 0 | } |
2767 | | // The path does not exist. Assume the stream content is |
2768 | | // associated with an old package that no longer exists, and |
2769 | | // delete it to keep the package registry clean. |
2770 | 0 | return false; |
2771 | 0 | } |
2772 | | // The first line in the stream is not the full path to a file or |
2773 | | // directory. Assume the stream content was created by a future |
2774 | | // version of CMake that uses a different format, and leave it. |
2775 | 0 | return true; |
2776 | 0 | } |
2777 | | |
2778 | | void cmFindPackageCommand::FillPrefixesCMakeSystemVariable() |
2779 | 0 | { |
2780 | 0 | cmSearchPath& paths = this->LabeledPaths[PathLabel::CMakeSystem]; |
2781 | |
|
2782 | 0 | bool const install_prefix_in_list = |
2783 | 0 | !this->Makefile->IsOn("CMAKE_FIND_NO_INSTALL_PREFIX"); |
2784 | 0 | bool const remove_install_prefix = this->NoCMakeInstallPath; |
2785 | 0 | bool const add_install_prefix = !this->NoCMakeInstallPath && |
2786 | 0 | this->Makefile->IsDefinitionSet("CMAKE_FIND_USE_INSTALL_PREFIX"); |
2787 | | |
2788 | | // We have 3 possible states for `CMAKE_SYSTEM_PREFIX_PATH` and |
2789 | | // `CMAKE_INSTALL_PREFIX`. |
2790 | | // Either we need to remove `CMAKE_INSTALL_PREFIX`, add |
2791 | | // `CMAKE_INSTALL_PREFIX`, or do nothing. |
2792 | | // |
2793 | | // When we need to remove `CMAKE_INSTALL_PREFIX` we remove the Nth occurrence |
2794 | | // of `CMAKE_INSTALL_PREFIX` from `CMAKE_SYSTEM_PREFIX_PATH`, where `N` is |
2795 | | // computed by `CMakeSystemSpecificInformation.cmake` while constructing |
2796 | | // `CMAKE_SYSTEM_PREFIX_PATH`. This ensures that if projects / toolchains |
2797 | | // have removed `CMAKE_INSTALL_PREFIX` from the list, we don't remove |
2798 | | // some other entry by mistake |
2799 | 0 | long install_prefix_count = -1; |
2800 | 0 | std::string install_path_to_remove; |
2801 | 0 | if (cmValue to_skip = this->Makefile->GetDefinition( |
2802 | 0 | "_CMAKE_SYSTEM_PREFIX_PATH_INSTALL_PREFIX_COUNT")) { |
2803 | 0 | cmStrToLong(*to_skip, &install_prefix_count); |
2804 | 0 | } |
2805 | 0 | if (cmValue install_value = this->Makefile->GetDefinition( |
2806 | 0 | "_CMAKE_SYSTEM_PREFIX_PATH_INSTALL_PREFIX_VALUE")) { |
2807 | 0 | install_path_to_remove = *install_value; |
2808 | 0 | } |
2809 | |
|
2810 | 0 | if (remove_install_prefix && install_prefix_in_list && |
2811 | 0 | install_prefix_count > 0 && !install_path_to_remove.empty()) { |
2812 | |
|
2813 | 0 | cmValue prefix_paths = |
2814 | 0 | this->Makefile->GetDefinition("CMAKE_SYSTEM_PREFIX_PATH"); |
2815 | | // remove entry from CMAKE_SYSTEM_PREFIX_PATH |
2816 | 0 | cmList expanded{ *prefix_paths }; |
2817 | 0 | long count = 0; |
2818 | 0 | for (auto const& path : expanded) { |
2819 | 0 | bool const to_add = |
2820 | 0 | !(path == install_path_to_remove && ++count == install_prefix_count); |
2821 | 0 | if (to_add) { |
2822 | 0 | paths.AddPath(path); |
2823 | 0 | } |
2824 | 0 | } |
2825 | 0 | } else if (add_install_prefix && !install_prefix_in_list) { |
2826 | 0 | paths.AddCMakePath("CMAKE_INSTALL_PREFIX"); |
2827 | 0 | paths.AddCMakePath("CMAKE_SYSTEM_PREFIX_PATH"); |
2828 | 0 | } else { |
2829 | | // Otherwise the current setup of `CMAKE_SYSTEM_PREFIX_PATH` is correct |
2830 | 0 | paths.AddCMakePath("CMAKE_SYSTEM_PREFIX_PATH"); |
2831 | 0 | } |
2832 | |
|
2833 | 0 | paths.AddCMakePath("CMAKE_SYSTEM_FRAMEWORK_PATH"); |
2834 | 0 | paths.AddCMakePath("CMAKE_SYSTEM_APPBUNDLE_PATH"); |
2835 | |
|
2836 | 0 | if (this->DebugModeEnabled()) { |
2837 | 0 | std::string debugBuffer = "CMake variables defined in the Platform file " |
2838 | 0 | "[CMAKE_FIND_USE_CMAKE_SYSTEM_PATH].\n"; |
2839 | 0 | collectPathsForDebug(debugBuffer, paths); |
2840 | 0 | this->DebugBuffer = cmStrCat(this->DebugBuffer, debugBuffer); |
2841 | 0 | } |
2842 | 0 | } |
2843 | | |
2844 | | void cmFindPackageCommand::FillPrefixesUserGuess() |
2845 | 0 | { |
2846 | 0 | cmSearchPath& paths = this->LabeledPaths[PathLabel::Guess]; |
2847 | |
|
2848 | 0 | for (std::string const& p : this->UserGuessArgs) { |
2849 | 0 | paths.AddUserPath(p); |
2850 | 0 | } |
2851 | 0 | if (this->DebugModeEnabled()) { |
2852 | 0 | std::string debugBuffer = |
2853 | 0 | "Paths specified by the find_package PATHS option.\n"; |
2854 | 0 | collectPathsForDebug(debugBuffer, paths); |
2855 | 0 | this->DebugBuffer = cmStrCat(this->DebugBuffer, debugBuffer); |
2856 | 0 | } |
2857 | 0 | } |
2858 | | |
2859 | | void cmFindPackageCommand::FillPrefixesUserHints() |
2860 | 0 | { |
2861 | 0 | cmSearchPath& paths = this->LabeledPaths[PathLabel::Hints]; |
2862 | |
|
2863 | 0 | for (std::string const& p : this->UserHintsArgs) { |
2864 | 0 | paths.AddUserPath(p); |
2865 | 0 | } |
2866 | 0 | if (this->DebugModeEnabled()) { |
2867 | 0 | std::string debugBuffer = |
2868 | 0 | "Paths specified by the find_package HINTS option.\n"; |
2869 | 0 | collectPathsForDebug(debugBuffer, paths); |
2870 | 0 | this->DebugBuffer = cmStrCat(this->DebugBuffer, debugBuffer); |
2871 | 0 | } |
2872 | 0 | } |
2873 | | |
2874 | | bool cmFindPackageCommand::SearchDirectory(std::string const& dir, |
2875 | | PackageDescriptionType type) |
2876 | 0 | { |
2877 | 0 | assert(!dir.empty() && dir.back() == '/'); |
2878 | | |
2879 | | // Check each path suffix on this directory. |
2880 | 0 | for (std::string const& s : this->SearchPathSuffixes) { |
2881 | 0 | std::string d = dir; |
2882 | 0 | if (!s.empty()) { |
2883 | 0 | d += s; |
2884 | 0 | d += '/'; |
2885 | 0 | } |
2886 | 0 | if (this->CheckDirectory(d, type)) { |
2887 | 0 | return true; |
2888 | 0 | } |
2889 | 0 | } |
2890 | 0 | return false; |
2891 | 0 | } |
2892 | | |
2893 | | bool cmFindPackageCommand::CheckDirectory(std::string const& dir, |
2894 | | PackageDescriptionType type) |
2895 | 0 | { |
2896 | 0 | assert(!dir.empty() && dir.back() == '/'); |
2897 | |
|
2898 | 0 | std::string const d = dir.substr(0, dir.size() - 1); |
2899 | 0 | if (cm::contains(this->IgnoredPaths, d)) { |
2900 | 0 | this->ConsideredPaths.emplace_back( |
2901 | 0 | dir, cmFindPackageCommand::FoundMode(type), SearchResult::Ignored); |
2902 | 0 | return false; |
2903 | 0 | } |
2904 | | |
2905 | | // Look for the file in this directory. |
2906 | 0 | std::string file; |
2907 | 0 | FoundPackageMode foundMode = FoundPackageMode::None; |
2908 | 0 | if (this->FindConfigFile(d, type, file, foundMode)) { |
2909 | 0 | this->FileFound = std::move(file); |
2910 | 0 | this->FileFoundMode = foundMode; |
2911 | 0 | return true; |
2912 | 0 | } |
2913 | 0 | return false; |
2914 | 0 | } |
2915 | | |
2916 | | bool cmFindPackageCommand::FindConfigFile(std::string const& dir, |
2917 | | PackageDescriptionType type, |
2918 | | std::string& file, |
2919 | | FoundPackageMode& foundMode) |
2920 | 0 | { |
2921 | 0 | for (auto const& config : this->Configs) { |
2922 | 0 | if (type != pdt::Any && config.Type != type) { |
2923 | 0 | continue; |
2924 | 0 | } |
2925 | 0 | file = cmStrCat(dir, '/', config.Name); |
2926 | 0 | if (this->DebugModeEnabled()) { |
2927 | 0 | this->DebugBuffer = cmStrCat(this->DebugBuffer, " ", file, '\n'); |
2928 | 0 | } |
2929 | 0 | if (cmSystemTools::FileExists(file, true)) { |
2930 | | // Allow resolving symlinks when the config file is found through a link |
2931 | 0 | if (this->UseRealPath) { |
2932 | 0 | file = cmSystemTools::GetRealPath(file); |
2933 | 0 | } else { |
2934 | 0 | file = cmSystemTools::ToNormalizedPathOnDisk(file); |
2935 | 0 | } |
2936 | 0 | if (this->CheckVersion(file)) { |
2937 | 0 | foundMode = cmFindPackageCommand::FoundMode(config.Type); |
2938 | 0 | return true; |
2939 | 0 | } |
2940 | 0 | this->ConsideredPaths.emplace_back( |
2941 | 0 | file, cmFindPackageCommand::FoundMode(type), |
2942 | 0 | this->ConsideredConfigs.back().result, |
2943 | 0 | this->ConsideredConfigs.back().message); |
2944 | 0 | } else { |
2945 | 0 | this->ConsideredPaths.emplace_back( |
2946 | 0 | file, cmFindPackageCommand::FoundMode(type), SearchResult::NoExist); |
2947 | 0 | } |
2948 | 0 | } |
2949 | 0 | return false; |
2950 | 0 | } |
2951 | | |
2952 | | bool cmFindPackageCommand::CheckVersion(std::string const& config_file) |
2953 | 0 | { |
2954 | 0 | bool result = false; // by default, assume the version is not ok. |
2955 | 0 | bool haveResult = false; |
2956 | 0 | std::string version = "unknown"; |
2957 | 0 | std::string message; |
2958 | 0 | SearchResult reason = SearchResult::InsufficientVersion; |
2959 | | |
2960 | | // Get the file extension. |
2961 | 0 | std::string::size_type pos = config_file.rfind('.'); |
2962 | 0 | std::string ext = cmSystemTools::LowerCase(config_file.substr(pos)); |
2963 | |
|
2964 | 0 | if (ext == ".cps"_s) { |
2965 | 0 | cmMakefile::CallRAII cs{ this->Makefile, config_file, this->Status }; |
2966 | |
|
2967 | 0 | std::unique_ptr<cmPackageInfoReader> reader = |
2968 | 0 | cmPackageInfoReader::Read(this->Makefile, config_file); |
2969 | |
|
2970 | 0 | if (reader && reader->GetName() == this->Name) { |
2971 | | // Read version information. |
2972 | 0 | cm::optional<std::string> cpsVersion = reader->GetVersion(); |
2973 | 0 | cm::optional<ParsedVersion> const& parsedVersion = |
2974 | 0 | reader->ParseVersion(cpsVersion); |
2975 | 0 | bool const hasVersion = cpsVersion.has_value(); |
2976 | | |
2977 | | // Test for version compatibility. |
2978 | 0 | result = this->Version.empty(); |
2979 | 0 | if (hasVersion) { |
2980 | 0 | version = std::move(*cpsVersion); |
2981 | |
|
2982 | 0 | if (!this->Version.empty()) { |
2983 | 0 | if (!parsedVersion) { |
2984 | | // If we don't understand the version, compare the exact versions |
2985 | | // using full string comparison. This is the correct behavior for |
2986 | | // the "custom" schema, and the best we can do otherwise. |
2987 | 0 | result = (this->Version == version); |
2988 | 0 | } else if (this->VersionExact) { |
2989 | | // If EXACT is specified, the version must be exactly the requested |
2990 | | // version. |
2991 | 0 | result = |
2992 | 0 | cmSystemTools::VersionCompareEqual(this->Version, version); |
2993 | 0 | } else { |
2994 | | // Do we have a compat_version? |
2995 | 0 | cm::optional<std::string> const& compatVersion = |
2996 | 0 | reader->GetCompatVersion(); |
2997 | 0 | if (reader->ParseVersion(compatVersion)) { |
2998 | | // If yes, the initial result is whether the requested version is |
2999 | | // between the actual version and the compat version, inclusive. |
3000 | 0 | result = cmSystemTools::VersionCompareGreaterEq(version, |
3001 | 0 | this->Version) && |
3002 | 0 | cmSystemTools::VersionCompareGreaterEq(this->Version, |
3003 | 0 | *compatVersion); |
3004 | |
|
3005 | 0 | if (result && !this->VersionMax.empty()) { |
3006 | | // We must also check that the version is less than the version |
3007 | | // limit. |
3008 | 0 | if (this->VersionRangeMax == VERSION_ENDPOINT_EXCLUDED) { |
3009 | 0 | result = cmSystemTools::VersionCompareGreater( |
3010 | 0 | this->VersionMax, version); |
3011 | 0 | } else { |
3012 | 0 | result = cmSystemTools::VersionCompareGreaterEq( |
3013 | 0 | this->VersionMax, version); |
3014 | 0 | } |
3015 | 0 | } |
3016 | |
|
3017 | 0 | if (!result) { |
3018 | 0 | message = |
3019 | 0 | cmStrCat("Version \""_s, version, |
3020 | 0 | "\" (compatibility version \""_s, *compatVersion, |
3021 | 0 | "\") is not compatible " |
3022 | 0 | "with the version requested."_s); |
3023 | 0 | } |
3024 | 0 | } else { |
3025 | | // If no, compat_version is assumed to be exactly the actual |
3026 | | // version, so the result is whether the requested version is |
3027 | | // exactly the actual version, and we can ignore the version |
3028 | | // limit. |
3029 | 0 | result = |
3030 | 0 | cmSystemTools::VersionCompareEqual(this->Version, version); |
3031 | 0 | } |
3032 | 0 | } |
3033 | 0 | } |
3034 | |
|
3035 | 0 | if (!result && message.empty()) { |
3036 | 0 | message = |
3037 | 0 | cmStrCat("Version \""_s, version, |
3038 | 0 | "\" is not compatible with the version requested."_s); |
3039 | 0 | } |
3040 | 0 | } |
3041 | |
|
3042 | 0 | if (result) { |
3043 | | // Locate appendices. |
3044 | 0 | cmFindPackageCommand::AppendixMap appendices = |
3045 | 0 | this->FindAppendices(config_file, *reader); |
3046 | | |
3047 | | // Collect available components. |
3048 | 0 | std::set<std::string> allComponents; |
3049 | |
|
3050 | 0 | std::vector<std::string> const& rootComponents = |
3051 | 0 | reader->GetComponentNames(); |
3052 | 0 | allComponents.insert(rootComponents.begin(), rootComponents.end()); |
3053 | |
|
3054 | 0 | for (auto const& appendix : appendices) { |
3055 | 0 | allComponents.insert(appendix.second.Components.begin(), |
3056 | 0 | appendix.second.Components.end()); |
3057 | 0 | } |
3058 | | |
3059 | | // Verify that all required components are available. |
3060 | 0 | std::set<std::string> requiredComponents = this->RequiredComponents; |
3061 | 0 | requiredComponents.insert(this->RequiredTargets.begin(), |
3062 | 0 | this->RequiredTargets.end()); |
3063 | |
|
3064 | 0 | std::vector<std::string> missingComponents; |
3065 | 0 | std::set_difference(requiredComponents.begin(), |
3066 | 0 | requiredComponents.end(), allComponents.begin(), |
3067 | 0 | allComponents.end(), |
3068 | 0 | std::back_inserter(missingComponents)); |
3069 | 0 | if (!missingComponents.empty()) { |
3070 | 0 | bool const single = (missingComponents.size() == 1); |
3071 | 0 | result = false; |
3072 | 0 | message = |
3073 | 0 | cmStrCat((single ? "Required component was not found: "_s |
3074 | 0 | : "Required components were not found: "_s), |
3075 | 0 | cmJoin(missingComponents, ", "_s), '.'); |
3076 | 0 | reason = SearchResult::InsufficientComponents; |
3077 | 0 | } |
3078 | |
|
3079 | 0 | if (result && hasVersion) { |
3080 | 0 | this->VersionFound = version; |
3081 | |
|
3082 | 0 | if (parsedVersion) { |
3083 | 0 | std::vector<unsigned> const& versionParts = |
3084 | 0 | parsedVersion->ReleaseComponents; |
3085 | |
|
3086 | 0 | this->VersionFoundCount = |
3087 | 0 | static_cast<unsigned>(versionParts.size()); |
3088 | 0 | switch (std::min(this->VersionFoundCount, 4u)) { |
3089 | 0 | case 4: |
3090 | 0 | this->VersionFoundTweak = versionParts[3]; |
3091 | 0 | CM_FALLTHROUGH; |
3092 | 0 | case 3: |
3093 | 0 | this->VersionFoundPatch = versionParts[2]; |
3094 | 0 | CM_FALLTHROUGH; |
3095 | 0 | case 2: |
3096 | 0 | this->VersionFoundMinor = versionParts[1]; |
3097 | 0 | CM_FALLTHROUGH; |
3098 | 0 | case 1: |
3099 | 0 | this->VersionFoundMajor = versionParts[0]; |
3100 | 0 | CM_FALLTHROUGH; |
3101 | 0 | default: |
3102 | 0 | break; |
3103 | 0 | } |
3104 | 0 | } else { |
3105 | 0 | this->VersionFoundCount = 0; |
3106 | 0 | } |
3107 | 0 | } |
3108 | 0 | this->CpsReader = std::move(reader); |
3109 | 0 | this->CpsAppendices = std::move(appendices); |
3110 | 0 | this->RequiredComponents = std::move(requiredComponents); |
3111 | 0 | } |
3112 | 0 | } else if (reader) { |
3113 | 0 | message = |
3114 | 0 | cmStrCat("The file describes the package \""_s, reader->GetName(), |
3115 | 0 | "\", which is not the requested package."_s); |
3116 | 0 | reason = SearchResult::Ignored; |
3117 | 0 | } else { |
3118 | 0 | message = "The package description file could not be read."; |
3119 | 0 | reason = SearchResult::Error; |
3120 | 0 | } |
3121 | 0 | } else { |
3122 | | // Get the filename without the .cmake extension. |
3123 | 0 | std::string version_file_base = config_file.substr(0, pos); |
3124 | | |
3125 | | // Look for foo-config-version.cmake |
3126 | 0 | std::string version_file = cmStrCat(version_file_base, "-version.cmake"); |
3127 | 0 | if (!haveResult && cmSystemTools::FileExists(version_file, true)) { |
3128 | 0 | result = this->CheckVersionFile(version_file, version); |
3129 | 0 | haveResult = true; |
3130 | 0 | } |
3131 | | |
3132 | | // Look for fooConfigVersion.cmake |
3133 | 0 | version_file = cmStrCat(version_file_base, "Version.cmake"); |
3134 | 0 | if (!haveResult && cmSystemTools::FileExists(version_file, true)) { |
3135 | 0 | result = this->CheckVersionFile(version_file, version); |
3136 | 0 | haveResult = true; |
3137 | 0 | } |
3138 | |
|
3139 | 0 | if (haveResult && !result) { |
3140 | 0 | message = |
3141 | 0 | "The version found is not compatible with the version requested."; |
3142 | 0 | } |
3143 | | |
3144 | | // If no version was requested a versionless package is acceptable. |
3145 | 0 | if (!haveResult && this->Version.empty()) { |
3146 | 0 | result = true; |
3147 | 0 | } |
3148 | 0 | } |
3149 | | |
3150 | 0 | if (result) { |
3151 | 0 | reason = SearchResult::Acceptable; |
3152 | 0 | } |
3153 | |
|
3154 | 0 | ConfigFileInfo configFileInfo; |
3155 | 0 | configFileInfo.filename = config_file; |
3156 | 0 | configFileInfo.version = version; |
3157 | 0 | configFileInfo.message = message; |
3158 | 0 | configFileInfo.result = reason; |
3159 | 0 | this->ConsideredConfigs.push_back(std::move(configFileInfo)); |
3160 | |
|
3161 | 0 | return result; |
3162 | 0 | } |
3163 | | |
3164 | | bool cmFindPackageCommand::CheckVersionFile(std::string const& version_file, |
3165 | | std::string& result_version) |
3166 | 0 | { |
3167 | | // The version file will be loaded in an isolated scope. |
3168 | 0 | cmMakefile::ScopePushPop const varScope(this->Makefile); |
3169 | 0 | cmMakefile::PolicyPushPop const polScope(this->Makefile); |
3170 | 0 | static_cast<void>(varScope); |
3171 | 0 | static_cast<void>(polScope); |
3172 | | |
3173 | | // Clear the output variables. |
3174 | 0 | this->Makefile->RemoveDefinition("PACKAGE_VERSION"); |
3175 | 0 | this->Makefile->RemoveDefinition("PACKAGE_VERSION_UNSUITABLE"); |
3176 | 0 | this->Makefile->RemoveDefinition("PACKAGE_VERSION_COMPATIBLE"); |
3177 | 0 | this->Makefile->RemoveDefinition("PACKAGE_VERSION_EXACT"); |
3178 | | |
3179 | | // Set the input variables. |
3180 | 0 | this->Makefile->AddDefinition("PACKAGE_FIND_NAME", this->Name); |
3181 | 0 | this->Makefile->AddDefinition("PACKAGE_FIND_VERSION_COMPLETE", |
3182 | 0 | this->VersionComplete); |
3183 | |
|
3184 | 0 | auto addDefinition = [this](std::string const& variable, |
3185 | 0 | cm::string_view value) { |
3186 | 0 | this->Makefile->AddDefinition(variable, value); |
3187 | 0 | }; |
3188 | 0 | this->SetVersionVariables(addDefinition, "PACKAGE_FIND_VERSION", |
3189 | 0 | this->Version, this->VersionCount, |
3190 | 0 | this->VersionMajor, this->VersionMinor, |
3191 | 0 | this->VersionPatch, this->VersionTweak); |
3192 | 0 | if (!this->VersionRange.empty()) { |
3193 | 0 | this->SetVersionVariables(addDefinition, "PACKAGE_FIND_VERSION_MIN", |
3194 | 0 | this->Version, this->VersionCount, |
3195 | 0 | this->VersionMajor, this->VersionMinor, |
3196 | 0 | this->VersionPatch, this->VersionTweak); |
3197 | 0 | this->SetVersionVariables(addDefinition, "PACKAGE_FIND_VERSION_MAX", |
3198 | 0 | this->VersionMax, this->VersionMaxCount, |
3199 | 0 | this->VersionMaxMajor, this->VersionMaxMinor, |
3200 | 0 | this->VersionMaxPatch, this->VersionMaxTweak); |
3201 | |
|
3202 | 0 | this->Makefile->AddDefinition("PACKAGE_FIND_VERSION_RANGE", |
3203 | 0 | this->VersionComplete); |
3204 | 0 | this->Makefile->AddDefinition("PACKAGE_FIND_VERSION_RANGE_MIN", |
3205 | 0 | this->VersionRangeMin); |
3206 | 0 | this->Makefile->AddDefinition("PACKAGE_FIND_VERSION_RANGE_MAX", |
3207 | 0 | this->VersionRangeMax); |
3208 | 0 | } |
3209 | | |
3210 | | // Load the version check file. |
3211 | | // Pass NoPolicyScope because we do our own policy push/pop. |
3212 | 0 | bool suitable = false; |
3213 | 0 | if (this->ReadListFile(version_file, NoPolicyScope)) { |
3214 | | // Check the output variables. |
3215 | 0 | bool okay = this->Makefile->IsOn("PACKAGE_VERSION_EXACT"); |
3216 | 0 | bool const unsuitable = this->Makefile->IsOn("PACKAGE_VERSION_UNSUITABLE"); |
3217 | 0 | if (!okay && !this->VersionExact) { |
3218 | 0 | okay = this->Makefile->IsOn("PACKAGE_VERSION_COMPATIBLE"); |
3219 | 0 | } |
3220 | | |
3221 | | // The package is suitable if the version is okay and not |
3222 | | // explicitly unsuitable. |
3223 | 0 | suitable = !unsuitable && (okay || this->Version.empty()); |
3224 | 0 | if (suitable) { |
3225 | | // Get the version found. |
3226 | 0 | this->VersionFound = |
3227 | 0 | this->Makefile->GetSafeDefinition("PACKAGE_VERSION"); |
3228 | | |
3229 | | // Try to parse the version number and store the results that were |
3230 | | // successfully parsed. |
3231 | 0 | unsigned int parsed_major; |
3232 | 0 | unsigned int parsed_minor; |
3233 | 0 | unsigned int parsed_patch; |
3234 | 0 | unsigned int parsed_tweak; |
3235 | 0 | this->VersionFoundCount = |
3236 | 0 | parseVersion(this->VersionFound, parsed_major, parsed_minor, |
3237 | 0 | parsed_patch, parsed_tweak); |
3238 | 0 | switch (this->VersionFoundCount) { |
3239 | 0 | case 4: |
3240 | 0 | this->VersionFoundTweak = parsed_tweak; |
3241 | 0 | CM_FALLTHROUGH; |
3242 | 0 | case 3: |
3243 | 0 | this->VersionFoundPatch = parsed_patch; |
3244 | 0 | CM_FALLTHROUGH; |
3245 | 0 | case 2: |
3246 | 0 | this->VersionFoundMinor = parsed_minor; |
3247 | 0 | CM_FALLTHROUGH; |
3248 | 0 | case 1: |
3249 | 0 | this->VersionFoundMajor = parsed_major; |
3250 | 0 | CM_FALLTHROUGH; |
3251 | 0 | default: |
3252 | 0 | break; |
3253 | 0 | } |
3254 | 0 | } |
3255 | 0 | } |
3256 | | |
3257 | 0 | result_version = this->Makefile->GetSafeDefinition("PACKAGE_VERSION"); |
3258 | 0 | if (result_version.empty()) { |
3259 | 0 | result_version = "unknown"; |
3260 | 0 | } |
3261 | | |
3262 | | // Succeed if the version is suitable. |
3263 | 0 | return suitable; |
3264 | 0 | } |
3265 | | |
3266 | | void cmFindPackageCommand::StoreVersionFound() |
3267 | 0 | { |
3268 | | // Store the whole version string. |
3269 | 0 | std::string const ver = cmStrCat(this->Name, "_VERSION"); |
3270 | 0 | auto addDefinition = [this](std::string const& variable, |
3271 | 0 | cm::string_view value) { |
3272 | 0 | this->Makefile->AddDefinition(variable, value); |
3273 | 0 | }; |
3274 | |
|
3275 | 0 | this->SetVersionVariables(addDefinition, ver, this->VersionFound, |
3276 | 0 | this->VersionFoundCount, this->VersionFoundMajor, |
3277 | 0 | this->VersionFoundMinor, this->VersionFoundPatch, |
3278 | 0 | this->VersionFoundTweak); |
3279 | |
|
3280 | 0 | if (this->VersionFound.empty()) { |
3281 | 0 | this->Makefile->RemoveDefinition(ver); |
3282 | 0 | } |
3283 | 0 | } |
3284 | | |
3285 | | bool cmFindPackageCommand::SearchPrefix(std::string const& prefix) |
3286 | 0 | { |
3287 | 0 | assert(!prefix.empty() && prefix.back() == '/'); |
3288 | | |
3289 | | // Skip this if the prefix does not exist. |
3290 | 0 | if (!cmSystemTools::FileIsDirectory(prefix)) { |
3291 | 0 | return false; |
3292 | 0 | } |
3293 | | |
3294 | | // Skip this if it's in ignored paths. |
3295 | 0 | std::string prefixWithoutSlash = prefix; |
3296 | 0 | if (prefixWithoutSlash != "/" && prefixWithoutSlash.back() == '/') { |
3297 | 0 | prefixWithoutSlash.erase(prefixWithoutSlash.length() - 1); |
3298 | 0 | } |
3299 | 0 | if (this->IgnoredPaths.count(prefixWithoutSlash) || |
3300 | 0 | this->IgnoredPrefixPaths.count(prefixWithoutSlash)) { |
3301 | 0 | return false; |
3302 | 0 | } |
3303 | | |
3304 | 0 | auto searchFn = [this](std::string const& fullPath, |
3305 | 0 | PackageDescriptionType type) -> bool { |
3306 | 0 | return this->SearchDirectory(fullPath, type); |
3307 | 0 | }; |
3308 | |
|
3309 | 0 | auto iCpsGen = cmCaseInsensitiveDirectoryListGenerator{ "cps"_s }; |
3310 | 0 | auto iCMakeGen = cmCaseInsensitiveDirectoryListGenerator{ "cmake"_s }; |
3311 | 0 | auto anyDirGen = |
3312 | 0 | cmAnyDirectoryListGenerator{ this->SortOrder, this->SortDirection }; |
3313 | 0 | auto cpsPkgDirGen = |
3314 | 0 | cmProjectDirectoryListGenerator{ &this->Names, this->SortOrder, |
3315 | 0 | this->SortDirection, true }; |
3316 | 0 | auto cmakePkgDirGen = |
3317 | 0 | cmProjectDirectoryListGenerator{ &this->Names, this->SortOrder, |
3318 | 0 | this->SortDirection, false }; |
3319 | | |
3320 | | // PREFIX/(Foo|foo|FOO)/(cps|CPS)/ |
3321 | 0 | if (TryGeneratedPaths(searchFn, pdt::Cps, prefix, cpsPkgDirGen, iCpsGen)) { |
3322 | 0 | return true; |
3323 | 0 | } |
3324 | | |
3325 | | // PREFIX/(Foo|foo|FOO)/*/(cps|CPS)/ |
3326 | 0 | if (TryGeneratedPaths(searchFn, pdt::Cps, prefix, cpsPkgDirGen, iCpsGen, |
3327 | 0 | anyDirGen)) { |
3328 | 0 | return true; |
3329 | 0 | } |
3330 | | |
3331 | | // PREFIX/(cps|CPS)/(Foo|foo|FOO)/ |
3332 | 0 | if (TryGeneratedPaths(searchFn, pdt::Cps, prefix, iCpsGen, cpsPkgDirGen)) { |
3333 | 0 | return true; |
3334 | 0 | } |
3335 | | |
3336 | | // PREFIX/(cps|CPS)/(Foo|foo|FOO)/*/ |
3337 | 0 | if (TryGeneratedPaths(searchFn, pdt::Cps, prefix, iCpsGen, cpsPkgDirGen, |
3338 | 0 | anyDirGen)) { |
3339 | 0 | return true; |
3340 | 0 | } |
3341 | | |
3342 | | // PREFIX/(cps|CPS)/ (useful on windows or in build trees) |
3343 | 0 | if (TryGeneratedPaths(searchFn, pdt::Cps, prefix, iCpsGen)) { |
3344 | 0 | return true; |
3345 | 0 | } |
3346 | | |
3347 | | // PREFIX/ (useful on windows or in build trees) |
3348 | 0 | if (this->SearchDirectory(prefix, pdt::CMake)) { |
3349 | 0 | return true; |
3350 | 0 | } |
3351 | | |
3352 | | // PREFIX/(cmake|CMake)/ (useful on windows or in build trees) |
3353 | 0 | if (TryGeneratedPaths(searchFn, pdt::CMake, prefix, iCMakeGen)) { |
3354 | 0 | return true; |
3355 | 0 | } |
3356 | | |
3357 | | // PREFIX/(Foo|foo|FOO).*/ |
3358 | 0 | if (TryGeneratedPaths(searchFn, pdt::CMake, prefix, cmakePkgDirGen)) { |
3359 | 0 | return true; |
3360 | 0 | } |
3361 | | |
3362 | | // PREFIX/(Foo|foo|FOO).*/(cmake|CMake)/ |
3363 | 0 | if (TryGeneratedPaths(searchFn, pdt::CMake, prefix, cmakePkgDirGen, |
3364 | 0 | iCMakeGen)) { |
3365 | 0 | return true; |
3366 | 0 | } |
3367 | | |
3368 | 0 | auto secondPkgDirGen = |
3369 | 0 | cmProjectDirectoryListGenerator{ &this->Names, this->SortOrder, |
3370 | 0 | this->SortDirection, false }; |
3371 | | |
3372 | | // PREFIX/(Foo|foo|FOO).*/(cmake|CMake)/(Foo|foo|FOO).*/ |
3373 | 0 | if (TryGeneratedPaths(searchFn, pdt::CMake, prefix, cmakePkgDirGen, |
3374 | 0 | iCMakeGen, secondPkgDirGen)) { |
3375 | 0 | return true; |
3376 | 0 | } |
3377 | | |
3378 | | // Construct list of common install locations (lib and share). |
3379 | 0 | std::vector<cm::string_view> common; |
3380 | 0 | std::string libArch; |
3381 | 0 | if (!this->LibraryArchitecture.empty()) { |
3382 | 0 | libArch = "lib/" + this->LibraryArchitecture; |
3383 | 0 | common.emplace_back(libArch); |
3384 | 0 | } |
3385 | 0 | if (this->UseLib32Paths) { |
3386 | 0 | common.emplace_back("lib32"_s); |
3387 | 0 | } |
3388 | 0 | if (this->UseLib64Paths) { |
3389 | 0 | common.emplace_back("lib64"_s); |
3390 | 0 | } |
3391 | 0 | if (this->UseLibx32Paths) { |
3392 | 0 | common.emplace_back("libx32"_s); |
3393 | 0 | } |
3394 | 0 | common.emplace_back("lib"_s); |
3395 | 0 | common.emplace_back("share"_s); |
3396 | |
|
3397 | 0 | auto commonGen = cmEnumPathSegmentsGenerator{ common }; |
3398 | 0 | auto cmakeGen = cmAppendPathSegmentGenerator{ "cmake"_s }; |
3399 | 0 | auto cpsGen = cmAppendPathSegmentGenerator{ "cps"_s }; |
3400 | | |
3401 | | // PREFIX/(lib/ARCH|lib*|share)/cps/(Foo|foo|FOO)/ |
3402 | 0 | if (TryGeneratedPaths(searchFn, pdt::Cps, prefix, commonGen, cpsGen, |
3403 | 0 | cpsPkgDirGen)) { |
3404 | 0 | return true; |
3405 | 0 | } |
3406 | | |
3407 | | // PREFIX/(lib/ARCH|lib*|share)/cps/(Foo|foo|FOO)/*/ |
3408 | 0 | if (TryGeneratedPaths(searchFn, pdt::Cps, prefix, commonGen, cpsGen, |
3409 | 0 | cpsPkgDirGen, anyDirGen)) { |
3410 | 0 | return true; |
3411 | 0 | } |
3412 | | |
3413 | | // PREFIX/(lib/ARCH|lib*|share)/cps/ |
3414 | 0 | if (TryGeneratedPaths(searchFn, pdt::Cps, prefix, commonGen, cpsGen)) { |
3415 | 0 | return true; |
3416 | 0 | } |
3417 | | |
3418 | | // PREFIX/(lib/ARCH|lib*|share)/cmake/(Foo|foo|FOO).*/ |
3419 | 0 | if (TryGeneratedPaths(searchFn, pdt::CMake, prefix, commonGen, cmakeGen, |
3420 | 0 | cmakePkgDirGen)) { |
3421 | 0 | return true; |
3422 | 0 | } |
3423 | | |
3424 | | // PREFIX/(lib/ARCH|lib*|share)/(Foo|foo|FOO).*/ |
3425 | 0 | if (TryGeneratedPaths(searchFn, pdt::CMake, prefix, commonGen, |
3426 | 0 | cmakePkgDirGen)) { |
3427 | 0 | return true; |
3428 | 0 | } |
3429 | | |
3430 | | // PREFIX/(lib/ARCH|lib*|share)/(Foo|foo|FOO).*/(cmake|CMake)/ |
3431 | 0 | if (TryGeneratedPaths(searchFn, pdt::CMake, prefix, commonGen, |
3432 | 0 | cmakePkgDirGen, iCMakeGen)) { |
3433 | 0 | return true; |
3434 | 0 | } |
3435 | | |
3436 | | // PREFIX/(Foo|foo|FOO).*/(lib/ARCH|lib*|share)/cmake/(Foo|foo|FOO).*/ |
3437 | 0 | if (TryGeneratedPaths(searchFn, pdt::CMake, prefix, cmakePkgDirGen, |
3438 | 0 | commonGen, cmakeGen, secondPkgDirGen)) { |
3439 | 0 | return true; |
3440 | 0 | } |
3441 | | |
3442 | | // PREFIX/(Foo|foo|FOO).*/(lib/ARCH|lib*|share)/(Foo|foo|FOO).*/ |
3443 | 0 | if (TryGeneratedPaths(searchFn, pdt::CMake, prefix, cmakePkgDirGen, |
3444 | 0 | commonGen, secondPkgDirGen)) { |
3445 | 0 | return true; |
3446 | 0 | } |
3447 | | |
3448 | | // PREFIX/(Foo|foo|FOO).*/(lib/ARCH|lib*|share)/(Foo|foo|FOO).*/(cmake|CMake)/ |
3449 | 0 | return TryGeneratedPaths(searchFn, pdt::CMake, prefix, cmakePkgDirGen, |
3450 | 0 | commonGen, secondPkgDirGen, iCMakeGen); |
3451 | 0 | } |
3452 | | |
3453 | | bool cmFindPackageCommand::SearchFrameworkPrefix(std::string const& prefix) |
3454 | 0 | { |
3455 | 0 | assert(!prefix.empty() && prefix.back() == '/'); |
3456 | |
|
3457 | 0 | auto searchFn = [this](std::string const& fullPath, |
3458 | 0 | PackageDescriptionType type) -> bool { |
3459 | 0 | return this->SearchDirectory(fullPath, type); |
3460 | 0 | }; |
3461 | |
|
3462 | 0 | auto iCMakeGen = cmCaseInsensitiveDirectoryListGenerator{ "cmake"_s }; |
3463 | 0 | auto iCpsGen = cmCaseInsensitiveDirectoryListGenerator{ "cps"_s }; |
3464 | 0 | auto fwGen = |
3465 | 0 | cmMacProjectDirectoryListGenerator{ &this->Names, ".framework"_s }; |
3466 | 0 | auto rGen = cmAppendPathSegmentGenerator{ "Resources"_s }; |
3467 | 0 | auto vGen = cmAppendPathSegmentGenerator{ "Versions"_s }; |
3468 | 0 | auto anyGen = |
3469 | 0 | cmAnyDirectoryListGenerator{ this->SortOrder, this->SortDirection }; |
3470 | | |
3471 | | // <prefix>/Foo.framework/Versions/*/Resources/CPS/ |
3472 | 0 | if (TryGeneratedPaths(searchFn, pdt::Cps, prefix, fwGen, vGen, anyGen, rGen, |
3473 | 0 | iCpsGen)) { |
3474 | 0 | return true; |
3475 | 0 | } |
3476 | | |
3477 | | // <prefix>/Foo.framework/Resources/CPS/ |
3478 | 0 | if (TryGeneratedPaths(searchFn, pdt::Cps, prefix, fwGen, rGen, iCpsGen)) { |
3479 | 0 | return true; |
3480 | 0 | } |
3481 | | |
3482 | | // <prefix>/Foo.framework/Resources/ |
3483 | 0 | if (TryGeneratedPaths(searchFn, pdt::CMake, prefix, fwGen, rGen)) { |
3484 | 0 | return true; |
3485 | 0 | } |
3486 | | |
3487 | | // <prefix>/Foo.framework/Resources/CMake/ |
3488 | 0 | if (TryGeneratedPaths(searchFn, pdt::CMake, prefix, fwGen, rGen, |
3489 | 0 | iCMakeGen)) { |
3490 | 0 | return true; |
3491 | 0 | } |
3492 | | |
3493 | | // <prefix>/Foo.framework/Versions/*/Resources/ |
3494 | 0 | if (TryGeneratedPaths(searchFn, pdt::CMake, prefix, fwGen, vGen, anyGen, |
3495 | 0 | rGen)) { |
3496 | 0 | return true; |
3497 | 0 | } |
3498 | | |
3499 | | // <prefix>/Foo.framework/Versions/*/Resources/CMake/ |
3500 | 0 | return TryGeneratedPaths(searchFn, pdt::CMake, prefix, fwGen, vGen, anyGen, |
3501 | 0 | rGen, iCMakeGen); |
3502 | 0 | } |
3503 | | |
3504 | | bool cmFindPackageCommand::SearchAppBundlePrefix(std::string const& prefix) |
3505 | 0 | { |
3506 | 0 | assert(!prefix.empty() && prefix.back() == '/'); |
3507 | |
|
3508 | 0 | auto searchFn = [this](std::string const& fullPath, |
3509 | 0 | PackageDescriptionType type) -> bool { |
3510 | 0 | return this->SearchDirectory(fullPath, type); |
3511 | 0 | }; |
3512 | |
|
3513 | 0 | auto appGen = cmMacProjectDirectoryListGenerator{ &this->Names, ".app"_s }; |
3514 | 0 | auto crGen = cmAppendPathSegmentGenerator{ "Contents/Resources"_s }; |
3515 | | |
3516 | | // <prefix>/Foo.app/Contents/Resources/CPS/ |
3517 | 0 | if (TryGeneratedPaths(searchFn, pdt::Cps, prefix, appGen, crGen, |
3518 | 0 | cmCaseInsensitiveDirectoryListGenerator{ "cps"_s })) { |
3519 | 0 | return true; |
3520 | 0 | } |
3521 | | |
3522 | | // <prefix>/Foo.app/Contents/Resources/ |
3523 | 0 | if (TryGeneratedPaths(searchFn, pdt::CMake, prefix, appGen, crGen)) { |
3524 | 0 | return true; |
3525 | 0 | } |
3526 | | |
3527 | | // <prefix>/Foo.app/Contents/Resources/CMake/ |
3528 | 0 | return TryGeneratedPaths( |
3529 | 0 | searchFn, pdt::CMake, prefix, appGen, crGen, |
3530 | 0 | cmCaseInsensitiveDirectoryListGenerator{ "cmake"_s }); |
3531 | 0 | } |
3532 | | |
3533 | | bool cmFindPackageCommand::SearchEnvironmentPrefix(std::string const& prefix) |
3534 | 0 | { |
3535 | 0 | assert(!prefix.empty() && prefix.back() == '/'); |
3536 | | |
3537 | | // Skip this if the prefix does not exist. |
3538 | 0 | if (!cmSystemTools::FileIsDirectory(prefix)) { |
3539 | 0 | return false; |
3540 | 0 | } |
3541 | | |
3542 | 0 | auto searchFn = [this](std::string const& fullPath, |
3543 | 0 | PackageDescriptionType type) -> bool { |
3544 | 0 | return this->SearchDirectory(fullPath, type); |
3545 | 0 | }; |
3546 | |
|
3547 | 0 | auto pkgDirGen = |
3548 | 0 | cmProjectDirectoryListGenerator{ &this->Names, this->SortOrder, |
3549 | 0 | this->SortDirection, true }; |
3550 | | |
3551 | | // <environment-path>/(Foo|foo|FOO)/cps/ |
3552 | 0 | if (TryGeneratedPaths(searchFn, pdt::Cps, prefix, pkgDirGen, |
3553 | 0 | cmAppendPathSegmentGenerator{ "cps"_s })) { |
3554 | 0 | return true; |
3555 | 0 | } |
3556 | | |
3557 | | // <environment-path>/(Foo|foo|FOO)/ |
3558 | 0 | return TryGeneratedPaths(searchFn, pdt::Cps, prefix, pkgDirGen); |
3559 | 0 | } |
3560 | | |
3561 | | bool cmFindPackageCommand::IsRequired() const |
3562 | 0 | { |
3563 | 0 | return this->Required == RequiredStatus::RequiredExplicit || |
3564 | 0 | this->Required == RequiredStatus::RequiredFromPackageVar || |
3565 | 0 | this->Required == RequiredStatus::RequiredFromFindVar; |
3566 | 0 | } |
3567 | | |
3568 | | cmFindPackageCommand::FoundPackageMode cmFindPackageCommand::FoundMode( |
3569 | | PackageDescriptionType type) |
3570 | 0 | { |
3571 | 0 | switch (type) { |
3572 | 0 | case PackageDescriptionType::Any: |
3573 | 0 | return FoundPackageMode::None; |
3574 | 0 | case PackageDescriptionType::CMake: |
3575 | 0 | return FoundPackageMode::Config; |
3576 | 0 | case PackageDescriptionType::Cps: |
3577 | 0 | return FoundPackageMode::Cps; |
3578 | 0 | } |
3579 | 0 | return FoundPackageMode::None; |
3580 | 0 | } |
3581 | | |
3582 | | // TODO: Debug cmsys::Glob double slash problem. |
3583 | | |
3584 | | bool cmFindPackage(std::vector<std::string> const& args, |
3585 | | cmExecutionStatus& status) |
3586 | 0 | { |
3587 | 0 | return cmFindPackageCommand(status).InitialPass(args); |
3588 | 0 | } |
3589 | | |
3590 | | cmFindPackageDebugState::cmFindPackageDebugState( |
3591 | | cmFindPackageCommand const* findPackage) |
3592 | 0 | : cmFindCommonDebugState("find_package", findPackage) |
3593 | 0 | , FindPackageCommand(findPackage) |
3594 | 0 | { |
3595 | 0 | } |
3596 | | |
3597 | 0 | cmFindPackageDebugState::~cmFindPackageDebugState() = default; |
3598 | | |
3599 | | void cmFindPackageDebugState::FoundAtImpl(std::string const& path, |
3600 | | std::string regexName) |
3601 | 0 | { |
3602 | 0 | (void)path; |
3603 | 0 | (void)regexName; |
3604 | 0 | } |
3605 | | |
3606 | | void cmFindPackageDebugState::FailedAtImpl(std::string const& path, |
3607 | | std::string regexName) |
3608 | 0 | { |
3609 | 0 | (void)path; |
3610 | 0 | (void)regexName; |
3611 | 0 | } |
3612 | | |
3613 | | bool cmFindPackageDebugState::ShouldImplicitlyLogEvents() const |
3614 | 0 | { |
3615 | 0 | auto const* fpc = this->FindPackageCommand; |
3616 | 0 | bool const canUsePackage = fpc->UseConfigFiles || fpc->UseCpsFiles; |
3617 | 0 | return canUsePackage && |
3618 | 0 | fpc->FileFoundMode != cmFindPackageCommand::FoundPackageMode::Module && |
3619 | 0 | std::any_of(fpc->ConsideredPaths.begin(), fpc->ConsideredPaths.end(), |
3620 | 0 | [](cmFindPackageCommand::ConsideredPath const& cp) { |
3621 | 0 | return cp.Mode > |
3622 | 0 | cmFindPackageCommand::FoundPackageMode::Module; |
3623 | 0 | }); |
3624 | 0 | } |
3625 | | |
3626 | | void cmFindPackageDebugState::WriteDebug() const |
3627 | 0 | { |
3628 | 0 | } |
3629 | | |
3630 | | #ifndef CMAKE_BOOTSTRAP |
3631 | | void cmFindPackageDebugState::WriteEvent(cmConfigureLog& log, |
3632 | | cmMakefile const& mf) const |
3633 | 0 | { |
3634 | 0 | (void)log; |
3635 | 0 | (void)mf; |
3636 | |
|
3637 | 0 | log.BeginEvent("find_package-v1", mf); |
3638 | |
|
3639 | 0 | auto const* fpc = this->FindPackageCommand; |
3640 | |
|
3641 | 0 | log.WriteValue("name"_s, fpc->Name); |
3642 | 0 | if (!fpc->Components.empty()) { |
3643 | 0 | log.BeginObject("components"_s); |
3644 | 0 | log.BeginArray(); |
3645 | 0 | for (auto const& component : cmList{ fpc->Components }) { |
3646 | 0 | log.NextArrayElement(); |
3647 | 0 | log.WriteValue("name"_s, component); |
3648 | 0 | log.WriteValue("required"_s, |
3649 | 0 | fpc->RequiredComponents.find(component) != |
3650 | 0 | fpc->RequiredComponents.end()); |
3651 | 0 | log.WriteValue("found"_s, |
3652 | 0 | mf.IsOn(cmStrCat(fpc->Name, '_', component, "_FOUND"))); |
3653 | 0 | } |
3654 | 0 | log.EndArray(); |
3655 | 0 | log.EndObject(); |
3656 | 0 | } |
3657 | 0 | if (!fpc->Configs.empty()) { |
3658 | 0 | auto pdt_name = |
3659 | 0 | [](cmFindPackageCommand::PackageDescriptionType type) -> std::string { |
3660 | 0 | switch (type) { |
3661 | 0 | case pdt::Any: |
3662 | 0 | return "any"; |
3663 | 0 | case pdt::CMake: |
3664 | 0 | return "cmake"; |
3665 | 0 | case pdt::Cps: |
3666 | 0 | return "cps"; |
3667 | 0 | } |
3668 | 0 | assert(false); |
3669 | 0 | return "<UNKNOWN>"; |
3670 | 0 | }; |
3671 | |
|
3672 | 0 | log.BeginObject("configs"_s); |
3673 | 0 | log.BeginArray(); |
3674 | 0 | for (auto const& config : fpc->Configs) { |
3675 | 0 | log.NextArrayElement(); |
3676 | 0 | log.WriteValue("filename"_s, config.Name); |
3677 | 0 | log.WriteValue("kind"_s, pdt_name(config.Type)); |
3678 | 0 | } |
3679 | 0 | log.EndArray(); |
3680 | 0 | log.EndObject(); |
3681 | 0 | } |
3682 | 0 | { |
3683 | 0 | log.BeginObject("version_request"_s); |
3684 | 0 | if (!fpc->Version.empty()) { |
3685 | 0 | log.WriteValue("version"_s, fpc->Version); |
3686 | 0 | } |
3687 | 0 | if (!fpc->VersionComplete.empty()) { |
3688 | 0 | log.WriteValue("version_complete"_s, fpc->VersionComplete); |
3689 | 0 | } |
3690 | 0 | if (!fpc->VersionRange.empty()) { |
3691 | 0 | log.WriteValue("min"_s, std::string(fpc->VersionRangeMin)); |
3692 | 0 | log.WriteValue("max"_s, std::string(fpc->VersionRangeMax)); |
3693 | 0 | } |
3694 | 0 | log.WriteValue("exact"_s, fpc->VersionExact); |
3695 | 0 | log.EndObject(); |
3696 | 0 | } |
3697 | 0 | { |
3698 | 0 | auto required_str = |
3699 | 0 | [](cmFindPackageCommand::RequiredStatus status) -> std::string { |
3700 | 0 | switch (status) { |
3701 | 0 | case cmFindPackageCommand::RequiredStatus::Optional: |
3702 | 0 | return "optional"; |
3703 | 0 | case cmFindPackageCommand::RequiredStatus::OptionalExplicit: |
3704 | 0 | return "optional_explicit"; |
3705 | 0 | case cmFindPackageCommand::RequiredStatus::RequiredExplicit: |
3706 | 0 | return "required_explicit"; |
3707 | 0 | case cmFindPackageCommand::RequiredStatus::RequiredFromPackageVar: |
3708 | 0 | return "required_from_package_variable"; |
3709 | 0 | case cmFindPackageCommand::RequiredStatus::RequiredFromFindVar: |
3710 | 0 | return "required_from_find_variable"; |
3711 | 0 | } |
3712 | 0 | assert(false); |
3713 | 0 | return "<UNKNOWN>"; |
3714 | 0 | }; |
3715 | 0 | log.BeginObject("settings"_s); |
3716 | 0 | log.WriteValue("required"_s, required_str(fpc->Required)); |
3717 | 0 | log.WriteValue("quiet"_s, fpc->Quiet); |
3718 | 0 | log.WriteValue("global"_s, fpc->GlobalScope); |
3719 | 0 | log.WriteValue("policy_scope"_s, fpc->PolicyScope); |
3720 | 0 | log.WriteValue("bypass_provider"_s, fpc->BypassProvider); |
3721 | 0 | if (!fpc->UserHintsArgs.empty()) { |
3722 | 0 | log.WriteValue("hints"_s, fpc->UserHintsArgs); |
3723 | 0 | } |
3724 | 0 | if (!fpc->Names.empty()) { |
3725 | 0 | log.WriteValue("names"_s, fpc->Names); |
3726 | 0 | } |
3727 | 0 | if (!fpc->UserGuessArgs.empty()) { |
3728 | 0 | log.WriteValue("search_paths"_s, fpc->UserGuessArgs); |
3729 | 0 | } |
3730 | 0 | if (!fpc->SearchPathSuffixes.empty()) { |
3731 | 0 | log.WriteValue("path_suffixes"_s, fpc->SearchPathSuffixes); |
3732 | 0 | } |
3733 | 0 | if (fpc->RegistryViewDefined) { |
3734 | 0 | log.WriteValue( |
3735 | 0 | "registry_view"_s, |
3736 | 0 | std::string(cmWindowsRegistry::FromView(fpc->RegistryView))); |
3737 | 0 | } |
3738 | 0 | { |
3739 | 0 | auto find_root_path_mode = |
3740 | 0 | [](cmFindCommon::RootPathMode mode) -> std::string { |
3741 | 0 | switch (mode) { |
3742 | 0 | case cmFindCommon::RootPathModeNever: |
3743 | 0 | return "NEVER"; |
3744 | 0 | case cmFindCommon::RootPathModeOnly: |
3745 | 0 | return "ONLY"; |
3746 | 0 | case cmFindCommon::RootPathModeBoth: |
3747 | 0 | return "BOTH"; |
3748 | 0 | } |
3749 | 0 | assert(false); |
3750 | 0 | return "<UNKNOWN>"; |
3751 | 0 | }; |
3752 | 0 | log.BeginObject("paths"_s); |
3753 | 0 | log.WriteValue("CMAKE_FIND_USE_CMAKE_PATH"_s, !fpc->NoDefaultPath); |
3754 | 0 | log.WriteValue("CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH"_s, |
3755 | 0 | !fpc->NoCMakeEnvironmentPath); |
3756 | 0 | log.WriteValue("CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH"_s, |
3757 | 0 | !fpc->NoSystemEnvironmentPath); |
3758 | 0 | log.WriteValue("CMAKE_FIND_USE_CMAKE_SYSTEM_PATH"_s, |
3759 | 0 | !fpc->NoCMakeSystemPath); |
3760 | 0 | log.WriteValue("CMAKE_FIND_USE_INSTALL_PREFIX"_s, |
3761 | 0 | !fpc->NoCMakeInstallPath); |
3762 | 0 | log.WriteValue("CMAKE_FIND_USE_PACKAGE_ROOT_PATH"_s, |
3763 | 0 | !fpc->NoPackageRootPath); |
3764 | 0 | log.WriteValue("CMAKE_FIND_USE_CMAKE_PACKAGE_REGISTRY"_s, |
3765 | 0 | !fpc->NoUserRegistry); |
3766 | 0 | log.WriteValue("CMAKE_FIND_USE_SYSTEM_PACKAGE_REGISTRY"_s, |
3767 | 0 | !fpc->NoSystemRegistry); |
3768 | 0 | log.WriteValue("CMAKE_FIND_ROOT_PATH_MODE"_s, |
3769 | 0 | find_root_path_mode(fpc->FindRootPathMode)); |
3770 | 0 | log.EndObject(); |
3771 | 0 | } |
3772 | 0 | log.EndObject(); |
3773 | 0 | } |
3774 | |
|
3775 | 0 | auto found_mode = |
3776 | 0 | [](cmFindPackageCommand::FoundPackageMode status) -> std::string { |
3777 | 0 | switch (status) { |
3778 | 0 | case cmFindPackageCommand::FoundPackageMode::None: |
3779 | 0 | return "none?"; |
3780 | 0 | case cmFindPackageCommand::FoundPackageMode::Module: |
3781 | 0 | return "module"; |
3782 | 0 | case cmFindPackageCommand::FoundPackageMode::Config: |
3783 | 0 | return "config"; |
3784 | 0 | case cmFindPackageCommand::FoundPackageMode::Cps: |
3785 | 0 | return "cps"; |
3786 | 0 | case cmFindPackageCommand::FoundPackageMode::Provider: |
3787 | 0 | return "provider"; |
3788 | 0 | } |
3789 | 0 | assert(false); |
3790 | 0 | return "<UNKNOWN>"; |
3791 | 0 | }; |
3792 | 0 | if (!fpc->ConsideredPaths.empty()) { |
3793 | 0 | auto search_result = |
3794 | 0 | [](cmFindPackageCommand::SearchResult type) -> std::string { |
3795 | 0 | switch (type) { |
3796 | 0 | case cmFindPackageCommand::SearchResult::Acceptable: |
3797 | 0 | return "acceptable"; |
3798 | 0 | case cmFindPackageCommand::SearchResult::InsufficientVersion: |
3799 | 0 | return "insufficient_version"; |
3800 | 0 | case cmFindPackageCommand::SearchResult::InsufficientComponents: |
3801 | 0 | return "insufficient_components"; |
3802 | 0 | case cmFindPackageCommand::SearchResult::Error: |
3803 | 0 | return "error"; |
3804 | 0 | case cmFindPackageCommand::SearchResult::NoExist: |
3805 | 0 | return "no_exist"; |
3806 | 0 | case cmFindPackageCommand::SearchResult::Ignored: |
3807 | 0 | return "ignored"; |
3808 | 0 | case cmFindPackageCommand::SearchResult::NoConfigFile: |
3809 | 0 | return "no_config_file"; |
3810 | 0 | case cmFindPackageCommand::SearchResult::NotFound: |
3811 | 0 | return "not_found"; |
3812 | 0 | } |
3813 | 0 | assert(false); |
3814 | 0 | return "<UNKNOWN>"; |
3815 | 0 | }; |
3816 | |
|
3817 | 0 | log.BeginObject("candidates"_s); |
3818 | 0 | log.BeginArray(); |
3819 | 0 | for (auto const& considered : fpc->ConsideredPaths) { |
3820 | 0 | log.NextArrayElement(); |
3821 | 0 | log.WriteValue("path"_s, considered.Path); |
3822 | 0 | log.WriteValue("mode"_s, found_mode(considered.Mode)); |
3823 | 0 | log.WriteValue("reason"_s, search_result(considered.Reason)); |
3824 | 0 | if (!considered.Message.empty()) { |
3825 | 0 | log.WriteValue("message"_s, considered.Message); |
3826 | 0 | } |
3827 | 0 | } |
3828 | 0 | log.EndArray(); |
3829 | 0 | log.EndObject(); |
3830 | 0 | } |
3831 | | // TODO: Add provider information (see #26925) |
3832 | 0 | if (!fpc->FileFound.empty()) { |
3833 | 0 | log.BeginObject("found"_s); |
3834 | 0 | log.WriteValue("path"_s, fpc->FileFound); |
3835 | 0 | log.WriteValue("mode"_s, found_mode(fpc->FileFoundMode)); |
3836 | 0 | log.WriteValue("version"_s, fpc->VersionFound); |
3837 | 0 | log.EndObject(); |
3838 | 0 | } else { |
3839 | 0 | log.WriteValue("found"_s, nullptr); |
3840 | 0 | } |
3841 | |
|
3842 | 0 | this->WriteSearchVariables(log, mf); |
3843 | |
|
3844 | 0 | log.EndEvent(); |
3845 | 0 | } |
3846 | | |
3847 | | std::vector<std::pair<cmFindCommonDebugState::VariableSource, std::string>> |
3848 | | cmFindPackageDebugState::ExtraSearchVariables() const |
3849 | 0 | { |
3850 | 0 | std::vector<std::pair<cmFindCommonDebugState::VariableSource, std::string>> |
3851 | 0 | extraSearches; |
3852 | 0 | if (this->FindPackageCommand->UseFindModules) { |
3853 | 0 | extraSearches.emplace_back(VariableSource::PathList, "CMAKE_MODULE_PATH"); |
3854 | 0 | } |
3855 | 0 | return extraSearches; |
3856 | 0 | } |
3857 | | #endif |