Coverage Report

Created: 2026-04-29 07:01

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