Coverage Report

Created: 2026-02-09 06:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/CMake/Source/cmFindCommon.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 "cmFindCommon.h"
4
5
#include <algorithm>
6
#include <array>
7
#include <utility>
8
9
#include <cmext/algorithm>
10
11
#include "cmExecutionStatus.h"
12
#include "cmList.h"
13
#include "cmMakefile.h"
14
#include "cmMessageType.h"
15
#include "cmPolicies.h"
16
#include "cmStringAlgorithms.h"
17
#include "cmSystemTools.h"
18
#include "cmValue.h"
19
#include "cmake.h"
20
21
#ifndef CMAKE_BOOTSTRAP
22
#  include <deque>
23
#  include <iterator>
24
25
#  include <cm/optional>
26
#  include <cm/string_view>
27
#  include <cmext/string_view>
28
29
#  include "cmConfigureLog.h"
30
#  include "cmRange.h"
31
#endif
32
33
cmFindCommon::PathGroup cmFindCommon::PathGroup::All("ALL");
34
cmFindCommon::PathLabel cmFindCommon::PathLabel::PackageRoot(
35
  "PackageName_ROOT");
36
cmFindCommon::PathLabel cmFindCommon::PathLabel::CMake("CMAKE");
37
cmFindCommon::PathLabel cmFindCommon::PathLabel::CMakeEnvironment(
38
  "CMAKE_ENVIRONMENT");
39
cmFindCommon::PathLabel cmFindCommon::PathLabel::Hints("HINTS");
40
cmFindCommon::PathLabel cmFindCommon::PathLabel::SystemEnvironment(
41
  "SYSTEM_ENVIRONMENT");
42
cmFindCommon::PathLabel cmFindCommon::PathLabel::CMakeSystem("CMAKE_SYSTEM");
43
cmFindCommon::PathLabel cmFindCommon::PathLabel::Guess("GUESS");
44
45
cmFindCommon::cmFindCommon(cmExecutionStatus& status)
46
0
  : Makefile(&status.GetMakefile())
47
0
  , Status(status)
48
0
{
49
0
  this->FindRootPathMode = RootPathModeBoth;
50
0
  this->FullDebugMode = false;
51
0
  this->NoDefaultPath = false;
52
0
  this->NoPackageRootPath = false;
53
0
  this->NoCMakePath = false;
54
0
  this->NoCMakeEnvironmentPath = false;
55
0
  this->NoSystemEnvironmentPath = false;
56
0
  this->NoCMakeSystemPath = false;
57
0
  this->NoCMakeInstallPath = false;
58
59
// OS X Bundle and Framework search policy.  The default is to
60
// search frameworks first on apple.
61
#if defined(__APPLE__)
62
  this->SearchFrameworkFirst = true;
63
  this->SearchAppBundleFirst = true;
64
#else
65
0
  this->SearchFrameworkFirst = false;
66
0
  this->SearchAppBundleFirst = false;
67
0
#endif
68
0
  this->SearchFrameworkOnly = false;
69
0
  this->SearchFrameworkLast = false;
70
0
  this->SearchAppBundleOnly = false;
71
0
  this->SearchAppBundleLast = false;
72
73
0
  this->InitializeSearchPathGroups();
74
75
  // Windows Registry views
76
  // When policy CMP0134 is not NEW, rely on previous behavior:
77
0
  if (this->Makefile->GetPolicyStatus(cmPolicies::CMP0134) !=
78
0
      cmPolicies::NEW) {
79
0
    if (this->Makefile->GetDefinition("CMAKE_SIZEOF_VOID_P") == "8") {
80
0
      this->RegistryView = cmWindowsRegistry::View::Reg64;
81
0
    } else {
82
0
      this->RegistryView = cmWindowsRegistry::View::Reg32;
83
0
    }
84
0
  }
85
0
}
86
87
0
cmFindCommon::~cmFindCommon() = default;
88
89
void cmFindCommon::SetError(std::string const& e)
90
0
{
91
0
  this->Status.SetError(e);
92
0
}
93
94
bool cmFindCommon::DebugModeEnabled() const
95
0
{
96
0
  return this->FullDebugMode;
97
0
}
98
99
void cmFindCommon::DebugMessage(std::string const& msg) const
100
0
{
101
0
  if (this->Makefile) {
102
0
    this->Makefile->IssueMessage(MessageType::LOG, msg);
103
0
  }
104
0
}
105
106
bool cmFindCommon::ComputeIfDebugModeWanted()
107
0
{
108
0
  return this->Makefile->GetDebugFindPkgMode() ||
109
0
    this->Makefile->IsOn("CMAKE_FIND_DEBUG_MODE") ||
110
0
    this->Makefile->GetCMakeInstance()->GetDebugFindOutput();
111
0
}
112
113
bool cmFindCommon::ComputeIfDebugModeWanted(std::string const& var)
114
0
{
115
0
  return this->ComputeIfDebugModeWanted() ||
116
0
    this->Makefile->GetCMakeInstance()->GetDebugFindOutput(var);
117
0
}
118
119
bool cmFindCommon::ComputeIfImplicitDebugModeSuppressed()
120
0
{
121
  // XXX(find-events): In the future, mirror the `ComputeIfDebugModeWanted`
122
  // methods if more control is desired.
123
0
  return this->Makefile->IsOn(
124
0
    "CMAKE_FIND_DEBUG_MODE_NO_IMPLICIT_CONFIGURE_LOG");
125
0
}
126
127
void cmFindCommon::InitializeSearchPathGroups()
128
0
{
129
0
  std::vector<PathLabel>* labels;
130
131
  // Define the various different groups of path types
132
133
  // All search paths
134
0
  labels = &this->PathGroupLabelMap[PathGroup::All];
135
0
  labels->push_back(PathLabel::PackageRoot);
136
0
  labels->push_back(PathLabel::CMake);
137
0
  labels->push_back(PathLabel::CMakeEnvironment);
138
0
  labels->push_back(PathLabel::Hints);
139
0
  labels->push_back(PathLabel::SystemEnvironment);
140
0
  labels->push_back(PathLabel::CMakeSystem);
141
0
  labels->push_back(PathLabel::Guess);
142
143
  // Define the search group order
144
0
  this->PathGroupOrder.push_back(PathGroup::All);
145
146
  // Create the individual labeled search paths
147
0
  this->LabeledPaths.emplace(PathLabel::PackageRoot, cmSearchPath(this));
148
0
  this->LabeledPaths.emplace(PathLabel::CMake, cmSearchPath(this));
149
0
  this->LabeledPaths.emplace(PathLabel::CMakeEnvironment, cmSearchPath(this));
150
0
  this->LabeledPaths.emplace(PathLabel::Hints, cmSearchPath(this));
151
0
  this->LabeledPaths.emplace(PathLabel::SystemEnvironment, cmSearchPath(this));
152
0
  this->LabeledPaths.emplace(PathLabel::CMakeSystem, cmSearchPath(this));
153
0
  this->LabeledPaths.emplace(PathLabel::Guess, cmSearchPath(this));
154
0
}
155
156
void cmFindCommon::SelectDefaultRootPathMode()
157
0
{
158
  // Check the policy variable for this find command type.
159
0
  std::string findRootPathVar =
160
0
    cmStrCat("CMAKE_FIND_ROOT_PATH_MODE_", this->CMakePathName);
161
0
  std::string rootPathMode =
162
0
    this->Makefile->GetSafeDefinition(findRootPathVar);
163
0
  if (rootPathMode == "NEVER") {
164
0
    this->FindRootPathMode = RootPathModeNever;
165
0
  } else if (rootPathMode == "ONLY") {
166
0
    this->FindRootPathMode = RootPathModeOnly;
167
0
  } else if (rootPathMode == "BOTH") {
168
0
    this->FindRootPathMode = RootPathModeBoth;
169
0
  }
170
0
}
171
172
void cmFindCommon::SelectDefaultMacMode()
173
0
{
174
0
  std::string ff = this->Makefile->GetSafeDefinition("CMAKE_FIND_FRAMEWORK");
175
0
  if (ff == "NEVER") {
176
0
    this->SearchFrameworkLast = false;
177
0
    this->SearchFrameworkFirst = false;
178
0
    this->SearchFrameworkOnly = false;
179
0
  } else if (ff == "ONLY") {
180
0
    this->SearchFrameworkLast = false;
181
0
    this->SearchFrameworkFirst = false;
182
0
    this->SearchFrameworkOnly = true;
183
0
  } else if (ff == "FIRST") {
184
0
    this->SearchFrameworkLast = false;
185
0
    this->SearchFrameworkFirst = true;
186
0
    this->SearchFrameworkOnly = false;
187
0
  } else if (ff == "LAST") {
188
0
    this->SearchFrameworkLast = true;
189
0
    this->SearchFrameworkFirst = false;
190
0
    this->SearchFrameworkOnly = false;
191
0
  }
192
193
0
  std::string fab = this->Makefile->GetSafeDefinition("CMAKE_FIND_APPBUNDLE");
194
0
  if (fab == "NEVER") {
195
0
    this->SearchAppBundleLast = false;
196
0
    this->SearchAppBundleFirst = false;
197
0
    this->SearchAppBundleOnly = false;
198
0
  } else if (fab == "ONLY") {
199
0
    this->SearchAppBundleLast = false;
200
0
    this->SearchAppBundleFirst = false;
201
0
    this->SearchAppBundleOnly = true;
202
0
  } else if (fab == "FIRST") {
203
0
    this->SearchAppBundleLast = false;
204
0
    this->SearchAppBundleFirst = true;
205
0
    this->SearchAppBundleOnly = false;
206
0
  } else if (fab == "LAST") {
207
0
    this->SearchAppBundleLast = true;
208
0
    this->SearchAppBundleFirst = false;
209
0
    this->SearchAppBundleOnly = false;
210
0
  }
211
0
}
212
213
void cmFindCommon::SelectDefaultSearchModes()
214
0
{
215
0
  std::array<std::pair<bool&, std::string>, 6> const search_paths = {
216
0
    { { this->NoPackageRootPath, "CMAKE_FIND_USE_PACKAGE_ROOT_PATH" },
217
0
      { this->NoCMakePath, "CMAKE_FIND_USE_CMAKE_PATH" },
218
0
      { this->NoCMakeEnvironmentPath,
219
0
        "CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH" },
220
0
      { this->NoSystemEnvironmentPath,
221
0
        "CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH" },
222
0
      { this->NoCMakeSystemPath, "CMAKE_FIND_USE_CMAKE_SYSTEM_PATH" },
223
0
      { this->NoCMakeInstallPath, "CMAKE_FIND_USE_INSTALL_PREFIX" } }
224
0
  };
225
226
0
  for (auto const& path : search_paths) {
227
0
    cmValue def = this->Makefile->GetDefinition(path.second);
228
0
    if (def) {
229
0
      path.first = !def.IsOn();
230
0
    }
231
0
  }
232
0
}
233
234
void cmFindCommon::RerootPaths(std::vector<std::string>& paths,
235
                               std::string* debugBuffer)
236
0
{
237
  // Short-circuit if there is nothing to do.
238
0
  if (this->FindRootPathMode == RootPathModeNever) {
239
0
    return;
240
0
  }
241
242
0
  cmValue sysroot = this->Makefile->GetDefinition("CMAKE_SYSROOT");
243
0
  cmValue sysrootCompile =
244
0
    this->Makefile->GetDefinition("CMAKE_SYSROOT_COMPILE");
245
0
  cmValue sysrootLink = this->Makefile->GetDefinition("CMAKE_SYSROOT_LINK");
246
0
  cmValue rootPath = this->Makefile->GetDefinition("CMAKE_FIND_ROOT_PATH");
247
0
  bool const noSysroot = !cmNonempty(sysroot);
248
0
  bool const noCompileSysroot = !cmNonempty(sysrootCompile);
249
0
  bool const noLinkSysroot = !cmNonempty(sysrootLink);
250
0
  bool const noRootPath = !cmNonempty(rootPath);
251
0
  if (noSysroot && noCompileSysroot && noLinkSysroot && noRootPath) {
252
0
    return;
253
0
  }
254
255
0
  if (this->DebugModeEnabled() && debugBuffer) {
256
0
    *debugBuffer = cmStrCat(
257
0
      *debugBuffer, "Prepending the following roots to each prefix:\n");
258
0
  }
259
260
0
  auto debugRoot = [this, debugBuffer](std::string const& name,
261
0
                                       cmValue value) {
262
0
    if (this->DebugModeEnabled() && debugBuffer) {
263
0
      *debugBuffer = cmStrCat(*debugBuffer, name, '\n');
264
0
      cmList roots{ value };
265
0
      if (roots.empty()) {
266
0
        *debugBuffer = cmStrCat(*debugBuffer, "  none\n");
267
0
      }
268
0
      for (auto const& root : roots) {
269
0
        *debugBuffer = cmStrCat(*debugBuffer, "  ", root, '\n');
270
0
      }
271
0
    }
272
0
  };
273
274
  // Construct the list of path roots with no trailing slashes.
275
0
  cmList roots;
276
0
  debugRoot("CMAKE_FIND_ROOT_PATH", rootPath);
277
0
  if (cmNonempty(rootPath)) {
278
0
    roots.assign(*rootPath);
279
0
  }
280
0
  debugRoot("CMAKE_SYSROOT_COMPILE", sysrootCompile);
281
0
  if (cmNonempty(sysrootCompile)) {
282
0
    roots.emplace_back(*sysrootCompile);
283
0
  }
284
0
  debugRoot("CMAKE_SYSROOT_LINK", sysrootLink);
285
0
  if (cmNonempty(sysrootLink)) {
286
0
    roots.emplace_back(*sysrootLink);
287
0
  }
288
0
  debugRoot("CMAKE_SYSROOT", sysroot);
289
0
  if (cmNonempty(sysroot)) {
290
0
    roots.emplace_back(*sysroot);
291
0
  }
292
0
  for (auto& r : roots) {
293
0
    cmSystemTools::ConvertToUnixSlashes(r);
294
0
  }
295
296
0
  cmValue stagePrefix = this->Makefile->GetDefinition("CMAKE_STAGING_PREFIX");
297
298
  // Copy the original set of unrooted paths.
299
0
  auto unrootedPaths = paths;
300
0
  paths.clear();
301
302
0
  auto isSameDirectoryOrSubDirectory = [](std::string const& l,
303
0
                                          std::string const& r) {
304
0
    std::string const lReal = cmSystemTools::GetRealPath(l);
305
0
    std::string const rReal = cmSystemTools::GetRealPath(r);
306
0
    return (lReal == rReal) || cmSystemTools::IsSubDirectory(lReal, rReal);
307
0
  };
308
309
0
  for (auto const& r : roots) {
310
0
    for (auto const& up : unrootedPaths) {
311
      // Place the unrooted path under the current root if it is not
312
      // already inside.  Skip the unrooted path if it is relative to
313
      // a user home directory or is empty.
314
0
      std::string rootedDir;
315
0
      if (isSameDirectoryOrSubDirectory(up, r) ||
316
0
          (stagePrefix && isSameDirectoryOrSubDirectory(up, *stagePrefix))) {
317
0
        rootedDir = up;
318
0
      } else if (!up.empty() && up[0] != '~') {
319
0
        auto const* split = cmSystemTools::SplitPathRootComponent(up);
320
0
        if (split && *split) {
321
          // Start with the new root.
322
0
          rootedDir = cmStrCat(r, '/', split);
323
0
        } else {
324
0
          rootedDir = r;
325
0
        }
326
0
      }
327
328
      // Store the new path.
329
0
      paths.push_back(rootedDir);
330
0
    }
331
0
  }
332
333
  // If searching both rooted and unrooted paths add the original
334
  // paths again.
335
0
  if (this->FindRootPathMode == RootPathModeBoth) {
336
0
    cm::append(paths, unrootedPaths);
337
0
  }
338
0
}
339
340
void cmFindCommon::GetIgnoredPaths(std::vector<std::string>& ignore)
341
0
{
342
0
  std::array<char const*, 2> const paths = { { "CMAKE_SYSTEM_IGNORE_PATH",
343
0
                                               "CMAKE_IGNORE_PATH" } };
344
345
  // Construct the list of path roots with no trailing slashes.
346
0
  for (char const* pathName : paths) {
347
    // Get the list of paths to ignore from the variable.
348
0
    cmList::append(ignore, this->Makefile->GetDefinition(pathName));
349
0
  }
350
351
0
  for (std::string& i : ignore) {
352
0
    cmSystemTools::ConvertToUnixSlashes(i);
353
0
  }
354
0
}
355
356
void cmFindCommon::GetIgnoredPaths(std::set<std::string>& ignore)
357
0
{
358
0
  std::vector<std::string> ignoreVec;
359
0
  this->GetIgnoredPaths(ignoreVec);
360
0
  ignore.insert(ignoreVec.begin(), ignoreVec.end());
361
0
}
362
363
void cmFindCommon::GetIgnoredPrefixPaths(std::vector<std::string>& ignore)
364
0
{
365
0
  std::array<char const*, 2> const paths = {
366
0
    { "CMAKE_SYSTEM_IGNORE_PREFIX_PATH", "CMAKE_IGNORE_PREFIX_PATH" }
367
0
  };
368
  // Construct the list of path roots with no trailing slashes.
369
0
  for (char const* pathName : paths) {
370
    // Get the list of paths to ignore from the variable.
371
0
    cmList::append(ignore, this->Makefile->GetDefinition(pathName));
372
0
  }
373
374
0
  for (std::string& i : ignore) {
375
0
    cmSystemTools::ConvertToUnixSlashes(i);
376
0
  }
377
0
}
378
379
void cmFindCommon::GetIgnoredPrefixPaths(std::set<std::string>& ignore)
380
0
{
381
0
  std::vector<std::string> ignoreVec;
382
0
  this->GetIgnoredPrefixPaths(ignoreVec);
383
0
  ignore.insert(ignoreVec.begin(), ignoreVec.end());
384
0
}
385
386
bool cmFindCommon::CheckCommonArgument(std::string const& arg)
387
0
{
388
0
  if (arg == "NO_DEFAULT_PATH") {
389
0
    this->NoDefaultPath = true;
390
0
    return true;
391
0
  }
392
0
  if (arg == "NO_PACKAGE_ROOT_PATH") {
393
0
    this->NoPackageRootPath = true;
394
0
    return true;
395
0
  }
396
0
  if (arg == "NO_CMAKE_PATH") {
397
0
    this->NoCMakePath = true;
398
0
    return true;
399
0
  }
400
0
  if (arg == "NO_CMAKE_ENVIRONMENT_PATH") {
401
0
    this->NoCMakeEnvironmentPath = true;
402
0
    return true;
403
0
  }
404
0
  if (arg == "NO_SYSTEM_ENVIRONMENT_PATH") {
405
0
    this->NoSystemEnvironmentPath = true;
406
0
    return true;
407
0
  }
408
0
  if (arg == "NO_CMAKE_SYSTEM_PATH") {
409
0
    this->NoCMakeSystemPath = true;
410
0
    return true;
411
0
  }
412
0
  if (arg == "NO_CMAKE_INSTALL_PREFIX") {
413
0
    this->NoCMakeInstallPath = true;
414
0
    return true;
415
0
  }
416
0
  if (arg == "NO_CMAKE_FIND_ROOT_PATH") {
417
0
    this->FindRootPathMode = RootPathModeNever;
418
0
    return true;
419
0
  }
420
0
  if (arg == "ONLY_CMAKE_FIND_ROOT_PATH") {
421
0
    this->FindRootPathMode = RootPathModeOnly;
422
0
    return true;
423
0
  }
424
0
  if (arg == "CMAKE_FIND_ROOT_PATH_BOTH") {
425
0
    this->FindRootPathMode = RootPathModeBoth;
426
0
    return true;
427
0
  }
428
  // The argument is not one of the above.
429
0
  return false;
430
0
}
431
432
void cmFindCommon::AddPathSuffix(std::string const& arg)
433
0
{
434
0
  std::string suffix = arg;
435
436
  // Strip leading and trailing slashes.
437
0
  if (suffix.empty()) {
438
0
    return;
439
0
  }
440
0
  if (suffix.front() == '/') {
441
0
    suffix = suffix.substr(1);
442
0
  }
443
0
  if (suffix.empty()) {
444
0
    return;
445
0
  }
446
0
  if (suffix.back() == '/') {
447
0
    suffix = suffix.substr(0, suffix.size() - 1);
448
0
  }
449
0
  if (suffix.empty()) {
450
0
    return;
451
0
  }
452
453
  // Store the suffix.
454
0
  this->SearchPathSuffixes.push_back(std::move(suffix));
455
0
}
456
457
void cmFindCommon::ComputeFinalPaths(IgnorePaths ignorePaths,
458
                                     std::string* debugBuffer)
459
0
{
460
  // Filter out ignored paths from the prefix list
461
0
  std::set<std::string> ignoredPaths;
462
0
  std::set<std::string> ignoredPrefixes;
463
0
  if (ignorePaths == IgnorePaths::Yes) {
464
0
    this->GetIgnoredPaths(ignoredPaths);
465
0
    this->GetIgnoredPrefixPaths(ignoredPrefixes);
466
0
  }
467
468
  // Combine the separate path types, filtering out ignores
469
0
  this->SearchPaths.clear();
470
0
  std::vector<PathLabel>& allLabels = this->PathGroupLabelMap[PathGroup::All];
471
0
  for (PathLabel const& l : allLabels) {
472
0
    this->LabeledPaths[l].ExtractWithout(ignoredPaths, ignoredPrefixes,
473
0
                                         this->SearchPaths);
474
0
  }
475
476
  // Expand list of paths inside all search roots.
477
0
  this->RerootPaths(this->SearchPaths, debugBuffer);
478
479
  // Add a trailing slash to all paths to aid the search process.
480
0
  std::for_each(this->SearchPaths.begin(), this->SearchPaths.end(),
481
0
                [](std::string& s) {
482
0
                  if (!s.empty() && s.back() != '/') {
483
0
                    s += '/';
484
0
                  }
485
0
                });
486
0
}
487
488
cmFindCommonDebugState::cmFindCommonDebugState(std::string name,
489
                                               cmFindCommon const* findCommand)
490
0
  : FindCommand(findCommand)
491
0
  , CommandName(std::move(name))
492
  // Strip the `find_` prefix.
493
0
  , Mode(this->CommandName.substr(5))
494
0
{
495
0
}
496
497
void cmFindCommonDebugState::FoundAt(std::string const& path,
498
                                     std::string regexName)
499
0
{
500
0
  this->IsFound = true;
501
502
0
  if (!this->TrackSearchProgress()) {
503
0
    return;
504
0
  }
505
506
0
  this->FoundAtImpl(path, regexName);
507
0
}
508
509
void cmFindCommonDebugState::FailedAt(std::string const& path,
510
                                      std::string regexName)
511
0
{
512
0
  if (!this->TrackSearchProgress()) {
513
0
    return;
514
0
  }
515
516
0
  this->FailedAtImpl(path, regexName);
517
0
}
518
519
bool cmFindCommonDebugState::ShouldImplicitlyLogEvents() const
520
0
{
521
0
  return true;
522
0
}
523
524
void cmFindCommonDebugState::Write()
525
0
{
526
0
  auto const* const fc = this->FindCommand;
527
528
0
#ifndef CMAKE_BOOTSTRAP
529
  // Write find event to the configure log if the log exists
530
0
  if (cmConfigureLog* log =
531
0
        fc->Makefile->GetCMakeInstance()->GetConfigureLog()) {
532
    // Write event if any of:
533
    //   - debug mode is enabled
534
    //   - implicit logging should happen and:
535
    //     - the variable was not defined (first run)
536
    //     - the variable found state does not match the new found state (state
537
    //       transition)
538
0
    if (fc->DebugModeEnabled() ||
539
0
        (this->ShouldImplicitlyLogEvents() &&
540
0
         (!fc->IsDefined() || fc->IsFound() != this->IsFound))) {
541
0
      this->WriteEvent(*log, *fc->Makefile);
542
0
    }
543
0
  }
544
0
#endif
545
546
0
  if (fc->DebugModeEnabled()) {
547
0
    this->WriteDebug();
548
0
  }
549
0
}
550
551
#ifndef CMAKE_BOOTSTRAP
552
void cmFindCommonDebugState::WriteSearchVariables(cmConfigureLog& log,
553
                                                  cmMakefile const& mf) const
554
0
{
555
0
  auto WriteString = [&log, &mf](std::string const& name) {
556
0
    if (cmValue value = mf.GetDefinition(name)) {
557
0
      log.WriteValue(name, *value);
558
0
    }
559
0
  };
560
0
  auto WriteCMakeList = [&log, &mf](std::string const& name) {
561
0
    if (cmValue value = mf.GetDefinition(name)) {
562
0
      cmList values{ *value };
563
0
      if (!values.empty()) {
564
0
        log.WriteValue(name, values);
565
0
      }
566
0
    }
567
0
  };
568
0
  auto WriteEnvList = [&log](std::string const& name) {
569
0
    if (auto value = cmSystemTools::GetEnvVar(name)) {
570
0
      auto values = cmSystemTools::SplitEnvPath(*value);
571
0
      if (!values.empty()) {
572
0
        log.WriteValue(cmStrCat("ENV{", name, '}'), values);
573
0
      }
574
0
    }
575
0
  };
576
577
0
  auto const* fc = this->FindCommand;
578
0
  log.BeginObject("search_context"_s);
579
0
  auto const& packageRootStack = mf.FindPackageRootPathStack;
580
0
  if (!packageRootStack.empty()) {
581
0
    bool havePaths =
582
0
      std::any_of(packageRootStack.begin(), packageRootStack.end(),
583
0
                  [](std::vector<std::string> const& entry) -> bool {
584
0
                    return !entry.empty();
585
0
                  });
586
0
    if (havePaths) {
587
0
      log.BeginObject("package_stack");
588
0
      log.BeginArray();
589
0
      for (auto const& pkgPaths : cmReverseRange(packageRootStack)) {
590
0
        if (!pkgPaths.empty()) {
591
0
          log.NextArrayElement();
592
0
          log.WriteValue("package_paths", pkgPaths);
593
0
        }
594
0
      }
595
0
      log.EndArray();
596
0
      log.EndObject();
597
0
    }
598
0
  }
599
0
  auto cmakePathVar = cmStrCat("CMAKE_", fc->CMakePathName, "_PATH");
600
0
  WriteCMakeList(cmakePathVar);
601
0
  WriteCMakeList("CMAKE_PREFIX_PATH");
602
0
  if (fc->CMakePathName == "PROGRAM"_s) {
603
0
    WriteCMakeList("CMAKE_APPBUNDLE_PATH");
604
0
  } else {
605
0
    WriteCMakeList("CMAKE_FRAMEWORK_PATH");
606
0
  }
607
  // Same as above, but ask the environment instead.
608
0
  WriteEnvList(cmakePathVar);
609
0
  WriteEnvList("CMAKE_PREFIX_PATH");
610
0
  if (fc->CMakePathName == "PROGRAM"_s) {
611
0
    WriteEnvList("CMAKE_APPBUNDLE_PATH");
612
0
  } else {
613
0
    WriteEnvList("CMAKE_FRAMEWORK_PATH");
614
0
  }
615
0
  WriteEnvList("PATH");
616
0
  WriteString("CMAKE_INSTALL_PREFIX");
617
0
  WriteString("CMAKE_STAGING_PREFIX");
618
0
  WriteCMakeList("CMAKE_SYSTEM_PREFIX_PATH");
619
0
  auto systemPathVar = cmStrCat("CMAKE_SYSTEM_", fc->CMakePathName, "_PATH");
620
0
  WriteCMakeList(systemPathVar);
621
  // Sysroot paths.
622
0
  WriteString("CMAKE_SYSROOT");
623
0
  WriteString("CMAKE_SYSROOT_COMPILE");
624
0
  WriteString("CMAKE_SYSROOT_LINK");
625
0
  WriteString("CMAKE_FIND_ROOT_PATH");
626
  // Write out paths which are ignored.
627
0
  WriteCMakeList("CMAKE_IGNORE_PATH");
628
0
  WriteCMakeList("CMAKE_IGNORE_PREFIX_PATH");
629
0
  WriteCMakeList("CMAKE_SYSTEM_IGNORE_PATH");
630
0
  WriteCMakeList("CMAKE_SYSTEM_IGNORE_PREFIX_PATH");
631
0
  if (fc->CMakePathName == "PROGRAM"_s) {
632
0
    WriteCMakeList("CMAKE_SYSTEM_APPBUNDLE_PATH");
633
0
  } else {
634
0
    WriteCMakeList("CMAKE_SYSTEM_FRAMEWORK_PATH");
635
0
  }
636
0
  for (auto const& extraVar : this->ExtraSearchVariables()) {
637
0
    switch (extraVar.first) {
638
0
      case VariableSource::String:
639
0
        WriteString(extraVar.second);
640
0
        break;
641
0
      case VariableSource::PathList:
642
0
        WriteCMakeList(extraVar.second);
643
0
        break;
644
0
      case VariableSource::EnvironmentList:
645
0
        WriteEnvList(extraVar.second);
646
0
        break;
647
0
    }
648
0
  }
649
0
  log.EndObject();
650
0
}
651
652
std::vector<std::pair<cmFindCommonDebugState::VariableSource, std::string>>
653
cmFindCommonDebugState::ExtraSearchVariables() const
654
0
{
655
0
  return {};
656
0
}
657
#endif
658
659
bool cmFindCommonDebugState::TrackSearchProgress() const
660
0
{
661
  // Track search progress if debugging or logging the configure.
662
0
  return this->FindCommand->DebugModeEnabled()
663
0
#ifndef CMAKE_BOOTSTRAP
664
0
    || this->FindCommand->Makefile->GetCMakeInstance()->GetConfigureLog()
665
0
#endif
666
0
    ;
667
0
}