Coverage Report

Created: 2026-02-09 06:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/CMake/Source/cmFindPackageCommand.h
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
#pragma once
4
5
#include "cmConfigure.h" // IWYU pragma: keep
6
7
#include <cstddef>
8
#include <functional>
9
#include <map>
10
#include <memory>
11
#include <set>
12
#include <string>
13
#include <utility>
14
#include <vector>
15
16
#include <cm/string_view>
17
18
#include <cm3p/kwiml/int.h>
19
20
#include "cmFindCommon.h"
21
#include "cmPackageInfoReader.h"
22
#include "cmPolicies.h"
23
24
// IWYU insists we should forward-declare instead of including <functional>,
25
// but we cannot forward-declare reliably because some C++ standard libraries
26
// put the template in an inline namespace.
27
#ifdef CMAKE_IWYU_FORWARD_STD_HASH
28
/* clang-format off */
29
namespace std {
30
  template <class T> struct hash;
31
}
32
/* clang-format on */
33
#endif
34
35
class cmExecutionStatus;
36
class cmPackageState;
37
class cmSearchPath;
38
class cmPackageInformation;
39
40
/** \class cmFindPackageCommand
41
 * \brief Load settings from an external project.
42
 *
43
 * cmFindPackageCommand
44
 */
45
class cmFindPackageCommand : public cmFindCommon
46
{
47
public:
48
  /*! A sorting order strategy to be applied to recovered package folders (see
49
   * FIND_PACKAGE_SORT_ORDER)*/
50
  enum /*class*/ SortOrderType
51
  {
52
    None,
53
    Name_order,
54
    Natural
55
  };
56
  /*! A sorting direction to be applied to recovered package folders (see
57
   * FIND_PACKAGE_SORT_DIRECTION)*/
58
  enum /*class*/ SortDirectionType
59
  {
60
    Asc,
61
    Dec
62
  };
63
64
  enum class PackageDescriptionType
65
  {
66
    Any,
67
    CMake,
68
    Cps,
69
  };
70
71
  /*! sorts a given list of string based on the input sort parameters */
72
  static void Sort(std::vector<std::string>::iterator begin,
73
                   std::vector<std::string>::iterator end, SortOrderType order,
74
                   SortDirectionType dir);
75
76
  cmFindPackageCommand(cmExecutionStatus& status);
77
  ~cmFindPackageCommand() override;
78
79
  bool InitialPass(std::vector<std::string> const& args);
80
81
private:
82
  class PathLabel : public cmFindCommon::PathLabel
83
  {
84
  protected:
85
    PathLabel();
86
87
  public:
88
    PathLabel(std::string const& label)
89
16
      : cmFindCommon::PathLabel(label)
90
16
    {
91
16
    }
92
    static PathLabel PackageRedirect;
93
    static PathLabel UserRegistry;
94
    static PathLabel Builds;
95
    static PathLabel SystemRegistry;
96
  };
97
98
  void InheritOptions(cmFindPackageCommand* other);
99
100
  bool IsFound() const override;
101
  bool IsDefined() const override;
102
103
  // Try to find a package, assuming most state has already been set up. This
104
  // is used for recursive dependency solving, particularly when importing
105
  // packages via CPS. Bypasses providers if argsForProvider is empty.
106
  bool FindPackage(std::vector<std::string> const& argsForProvider = {});
107
108
  bool FindPackageUsingModuleMode();
109
  bool FindPackageUsingConfigMode();
110
111
  // Add additional search path labels and groups not present in the
112
  // parent class
113
  void AppendSearchPathGroups();
114
115
  void AppendSuccessInformation();
116
  void AppendToFoundProperty(bool found);
117
  void SetVersionVariables(
118
    std::function<void(std::string const&, cm::string_view)> const&
119
      addDefinition,
120
    std::string const& prefix, std::string const& version, unsigned int count,
121
    unsigned int major, unsigned int minor, unsigned int patch,
122
    unsigned int tweak);
123
  void SetModuleVariables();
124
  bool FindModule(bool& found);
125
  void AddFindDefinition(std::string const& var, cm::string_view value);
126
  void RestoreFindDefinitions();
127
128
  class SetRestoreFindDefinitions;
129
130
  enum /*class*/ HandlePackageModeType
131
  {
132
    Module,
133
    Config
134
  };
135
  bool HandlePackageMode(HandlePackageModeType type);
136
137
  bool FindConfig();
138
  bool FindPrefixedConfig();
139
  bool FindFrameworkConfig();
140
  bool FindAppBundleConfig();
141
  bool FindEnvironmentConfig();
142
  enum PolicyScopeRule
143
  {
144
    NoPolicyScope,
145
    DoPolicyScope
146
  };
147
  bool ReadListFile(std::string const& f, PolicyScopeRule psr);
148
  bool ReadPackage();
149
150
  struct Appendix
151
  {
152
    std::unique_ptr<cmPackageInfoReader> Reader;
153
    std::vector<std::string> Components;
154
155
0
    operator cmPackageInfoReader&() const { return *this->Reader; }
156
  };
157
  using AppendixMap = std::map<std::string, Appendix>;
158
  AppendixMap FindAppendices(std::string const& base,
159
                             cmPackageInfoReader const& baseReader) const;
160
  enum RequiredStatus
161
  {
162
    Optional,
163
    OptionalExplicit,
164
    RequiredExplicit,
165
    RequiredFromPackageVar,
166
    RequiredFromFindVar
167
  };
168
  bool FindPackageDependencies(std::string const& filePath,
169
                               cmPackageInfoReader const& reader,
170
                               RequiredStatus required);
171
172
  bool ImportPackageTargets(cmPackageState& packageState,
173
                            std::string const& filePath,
174
                            cmPackageInfoReader& reader);
175
  void StoreVersionFound();
176
  void SetConfigDirCacheVariable(std::string const& value);
177
178
  void PushFindPackageRootPathStack();
179
  void PopFindPackageRootPathStack();
180
  class PushPopRootPathStack;
181
182
  enum class FoundPackageMode
183
  {
184
    None,
185
    Module,
186
    // Do not implicitly log for prior package types.
187
    Config,
188
    Cps,
189
    Provider,
190
  };
191
  void ComputePrefixes();
192
  void FillPrefixesPackageRedirect();
193
  void FillPrefixesPackageRoot();
194
  void FillPrefixesCMakeEnvironment();
195
  void FillPrefixesCMakeVariable();
196
  void FillPrefixesSystemEnvironment();
197
  void FillPrefixesUserRegistry();
198
  void FillPrefixesSystemRegistry();
199
  void FillPrefixesCMakeSystemVariable();
200
  void FillPrefixesUserGuess();
201
  void FillPrefixesUserHints();
202
  void LoadPackageRegistryDir(std::string const& dir, cmSearchPath& outPaths);
203
  void LoadPackageRegistryWinUser();
204
  void LoadPackageRegistryWinSystem();
205
  void LoadPackageRegistryWin(bool user, unsigned int view,
206
                              cmSearchPath& outPaths);
207
  bool CheckPackageRegistryEntry(std::string const& fname,
208
                                 cmSearchPath& outPaths);
209
  bool SearchDirectory(std::string const& dir, PackageDescriptionType type);
210
  bool CheckDirectory(std::string const& dir, PackageDescriptionType type);
211
  bool FindConfigFile(std::string const& dir, PackageDescriptionType type,
212
                      std::string& file, FoundPackageMode& foundMode);
213
  bool CheckVersion(std::string const& config_file);
214
  bool CheckVersionFile(std::string const& version_file,
215
                        std::string& result_version);
216
  bool SearchPrefix(std::string const& prefix);
217
  bool SearchFrameworkPrefix(std::string const& prefix);
218
  bool SearchAppBundlePrefix(std::string const& prefix);
219
  bool SearchEnvironmentPrefix(std::string const& prefix);
220
221
  bool IsRequired() const;
222
223
  struct OriginalDef
224
  {
225
    bool exists;
226
    std::string value;
227
  };
228
  std::map<std::string, OriginalDef> OriginalDefs;
229
230
  std::map<std::string, cmPolicies::PolicyID> DeprecatedFindModules;
231
232
  static cm::string_view const VERSION_ENDPOINT_INCLUDED;
233
  static cm::string_view const VERSION_ENDPOINT_EXCLUDED;
234
235
  std::string Name;
236
  std::string Variable;
237
  std::string VersionComplete;
238
  std::string VersionRange;
239
  cm::string_view VersionRangeMin;
240
  cm::string_view VersionRangeMax;
241
  std::string Version;
242
  unsigned int VersionMajor = 0;
243
  unsigned int VersionMinor = 0;
244
  unsigned int VersionPatch = 0;
245
  unsigned int VersionTweak = 0;
246
  unsigned int VersionCount = 0;
247
  std::string VersionMax;
248
  unsigned int VersionMaxMajor = 0;
249
  unsigned int VersionMaxMinor = 0;
250
  unsigned int VersionMaxPatch = 0;
251
  unsigned int VersionMaxTweak = 0;
252
  unsigned int VersionMaxCount = 0;
253
  bool VersionExact = false;
254
  std::string FileFound;
255
  FoundPackageMode FileFoundMode = FoundPackageMode::None;
256
  std::string VersionFound;
257
  unsigned int VersionFoundMajor = 0;
258
  unsigned int VersionFoundMinor = 0;
259
  unsigned int VersionFoundPatch = 0;
260
  unsigned int VersionFoundTweak = 0;
261
  unsigned int VersionFoundCount = 0;
262
  KWIML_INT_uint64_t RequiredCMakeVersion = 0;
263
  bool BypassProvider = false;
264
  bool Quiet = false;
265
  RequiredStatus Required = RequiredStatus::Optional;
266
  bool UseCpsFiles = false;
267
  bool UseConfigFiles = true;
268
  bool UseFindModules = true;
269
  bool NoUserRegistry = false;
270
  bool NoSystemRegistry = false;
271
  bool UseLib32Paths = false;
272
  bool UseLib64Paths = false;
273
  bool UseLibx32Paths = false;
274
  bool UseRealPath = false;
275
  bool PolicyScope = true;
276
  bool GlobalScope = false;
277
  bool RegistryViewDefined = false;
278
  bool ScopeUnwind = false;
279
  std::string LibraryArchitecture;
280
  std::vector<std::string> Names;
281
  std::set<std::string> IgnoredPaths;
282
  std::set<std::string> IgnoredPrefixPaths;
283
  std::string Components;
284
  std::set<std::string> RequiredComponents;
285
  std::set<std::string> OptionalComponents;
286
  std::set<std::string> RequiredTargets;
287
  std::string DebugBuffer;
288
  cmPackageInformation* CurrentPackageInfo;
289
290
  enum class SearchResult
291
  {
292
    Acceptable,
293
    InsufficientVersion,
294
    InsufficientComponents,
295
    Error,
296
    NoExist,
297
    Ignored,
298
    NoConfigFile,
299
    NotFound,
300
  };
301
  struct ConsideredPath
302
  {
303
    ConsideredPath(std::string path, FoundPackageMode mode,
304
                   SearchResult result, std::string message = {})
305
0
      : Path(std::move(path))
306
0
      , Mode(mode)
307
0
      , Reason(result)
308
0
      , Message(std::move(message))
309
0
    {
310
0
    }
311
312
    std::string Path;
313
    FoundPackageMode Mode;
314
    SearchResult Reason;
315
    std::string Message;
316
  };
317
  std::vector<ConsideredPath> ConsideredPaths;
318
319
  static FoundPackageMode FoundMode(PackageDescriptionType type);
320
321
  struct ConfigName
322
  {
323
    ConfigName(std::string const& name, PackageDescriptionType type)
324
0
      : Name{ name }
325
0
      , Type{ type }
326
0
    {
327
0
    }
328
    ConfigName(std::string&& name, PackageDescriptionType type)
329
0
      : Name{ std::move(name) }
330
0
      , Type{ type }
331
0
    {
332
0
    }
333
    ConfigName(ConfigName const&) = default;
334
0
    ConfigName(ConfigName&&) = default;
335
336
    std::string Name;
337
    PackageDescriptionType Type;
338
  };
339
  std::vector<ConfigName> Configs;
340
341
  class FlushDebugBufferOnExit;
342
343
  /*! the selected sortOrder (Natural by default)*/
344
  SortOrderType SortOrder = Natural;
345
  /*! the selected sortDirection (Dec by default)*/
346
  SortDirectionType SortDirection = Dec;
347
348
  struct ConfigFileInfo
349
  {
350
    std::string filename;
351
    std::string version;
352
    std::string message;
353
    SearchResult result;
354
355
    bool operator<(ConfigFileInfo const& rhs) const
356
0
    {
357
0
      return this->filename < rhs.filename;
358
0
    }
359
360
    bool operator==(ConfigFileInfo const& rhs) const
361
0
    {
362
0
      return this->filename == rhs.filename;
363
0
    }
364
365
    bool operator!=(ConfigFileInfo const& rhs) const
366
0
    {
367
0
      return !(*this == rhs);
368
0
    }
369
  };
370
  std::vector<ConfigFileInfo> ConsideredConfigs;
371
372
  std::unique_ptr<cmPackageInfoReader> CpsReader;
373
  AppendixMap CpsAppendices;
374
375
  friend struct std::hash<ConfigFileInfo>;
376
  friend class cmFindPackageDebugState;
377
378
  enum class FindState
379
  {
380
    Undefined,
381
    Irrelevant,
382
    Found,
383
    NotFound,
384
  };
385
  FindState InitialState = FindState::Undefined;
386
};
387
388
namespace std {
389
390
template <>
391
struct hash<cmFindPackageCommand::ConfigFileInfo>
392
{
393
  using argument_type = cmFindPackageCommand::ConfigFileInfo;
394
  using result_type = size_t;
395
396
  result_type operator()(argument_type const& s) const noexcept
397
0
  {
398
0
    result_type const h(std::hash<std::string>{}(s.filename));
399
0
    return h;
400
0
  }
401
};
402
}
403
404
bool cmFindPackage(std::vector<std::string> const& args,
405
                   cmExecutionStatus& status);
406
407
class cmFindPackageDebugState : public cmFindCommonDebugState
408
{
409
public:
410
  explicit cmFindPackageDebugState(cmFindPackageCommand const* findPackage);
411
  ~cmFindPackageDebugState() override;
412
413
private:
414
  void FoundAtImpl(std::string const& path, std::string regexName) override;
415
  void FailedAtImpl(std::string const& path, std::string regexName) override;
416
  bool ShouldImplicitlyLogEvents() const override;
417
418
  void WriteDebug() const override;
419
#ifndef CMAKE_BOOTSTRAP
420
  void WriteEvent(cmConfigureLog& log, cmMakefile const& mf) const override;
421
  std::vector<std::pair<VariableSource, std::string>> ExtraSearchVariables()
422
    const override;
423
#endif
424
425
  cmFindPackageCommand const* const FindPackageCommand;
426
};