/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file Copyright.txt or https://cmake.org/licensing for details.  */
#include "cmFindPackageCommand.h"

#include <algorithm>
#include <cassert>
#include <cstdio>
#include <deque>
#include <functional>
#include <iterator>
#include <sstream>
#include <utility>

#include <cm/optional>
#include <cmext/algorithm>
#include <cmext/string_view>

#include "cmsys/Directory.hxx"
#include "cmsys/FStream.hxx"
#include "cmsys/Glob.hxx"
#include "cmsys/RegularExpression.hxx"
#include "cmsys/String.h"

#include "cmAlgorithms.h"
#include "cmDependencyProvider.h"
#include "cmExecutionStatus.h"
#include "cmExperimental.h"
#include "cmList.h"
#include "cmListFileCache.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmPolicies.h"
#include "cmRange.h"
#include "cmSearchPath.h"
#include "cmState.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmValue.h"
#include "cmVersion.h"
#include "cmWindowsRegistry.h"

#if defined(__HAIKU__)
#  include <FindDirectory.h>
#  include <StorageDefs.h>
#endif

#if defined(_WIN32) && !defined(__CYGWIN__)
#  include <windows.h>
// http://msdn.microsoft.com/en-us/library/aa384253%28v=vs.85%29.aspx
#  if !defined(KEY_WOW64_32KEY)
#    define KEY_WOW64_32KEY 0x0200
#  endif
#  if !defined(KEY_WOW64_64KEY)
#    define KEY_WOW64_64KEY 0x0100
#  endif
#endif

namespace {

using pdt = cmFindPackageCommand::PackageDescriptionType;

template <template <typename> class Op>
struct StrverscmpOp
{
  bool operator()(const std::string& lhs, const std::string& rhs) const
  {
    return Op<int>()(cmSystemTools::strverscmp(lhs, rhs), 0);
  }
};

std::size_t collectPathsForDebug(std::string& buffer,
                                 cmSearchPath const& searchPath,
                                 std::size_t const startIndex = 0)
{
  const auto& paths = searchPath.GetPaths();
  if (paths.empty()) {
    buffer += "  none\n";
    return 0;
  }
  for (auto i = startIndex; i < paths.size(); i++) {
    buffer += "  " + paths[i].Path + "\n";
  }
  return paths.size();
}

#if !(defined(_WIN32) && !defined(__CYGWIN__))
class cmFindPackageCommandHoldFile
{
  const char* File;

public:
  cmFindPackageCommandHoldFile(const char* const f)
    : File(f)
  {
  }
  ~cmFindPackageCommandHoldFile()
  {
    if (this->File) {
      cmSystemTools::RemoveFile(this->File);
    }
  }
  cmFindPackageCommandHoldFile(const cmFindPackageCommandHoldFile&) = delete;
  cmFindPackageCommandHoldFile& operator=(
    const cmFindPackageCommandHoldFile&) = delete;
  void Release() { this->File = nullptr; }
};
#endif

bool isDirentryToIgnore(const char* const fname)
{
  assert(fname);
  assert(fname[0] != 0);
  return fname[0] == '.' &&
    (fname[1] == 0 || (fname[1] == '.' && fname[2] == 0));
}

class cmAppendPathSegmentGenerator
{
public:
  cmAppendPathSegmentGenerator(cm::string_view dirName)
    : DirName{ dirName }
  {
  }

  std::string GetNextCandidate(const std::string& parent)
  {
    if (this->NeedReset) {
      return {};
    }
    this->NeedReset = true;
    return cmStrCat(parent, this->DirName, '/');
  }

  void Reset() { this->NeedReset = false; }

private:
  const cm::string_view DirName;
  bool NeedReset = false;
};

class cmEnumPathSegmentsGenerator
{
public:
  cmEnumPathSegmentsGenerator(const std::vector<cm::string_view>& init)
    : Names{ init }
    , Current{ this->Names.get().cbegin() }
  {
  }

  std::string GetNextCandidate(const std::string& parent)
  {
    if (this->Current != this->Names.get().cend()) {
      return cmStrCat(parent, *this->Current++, '/');
    }
    return {};
  }

  void Reset() { this->Current = this->Names.get().cbegin(); }

private:
  std::reference_wrapper<const std::vector<cm::string_view>> Names;
  std::vector<cm::string_view>::const_iterator Current;
};

class cmCaseInsensitiveDirectoryListGenerator
{
public:
  cmCaseInsensitiveDirectoryListGenerator(cm::string_view name)
    : DirName{ name }
  {
  }

  std::string GetNextCandidate(const std::string& parent)
  {
    if (!this->Loaded) {
      this->CurrentIdx = 0ul;
      this->Loaded = true;
      if (!this->DirectoryLister.Load(parent)) {
        return {};
      }
    }

    while (this->CurrentIdx < this->DirectoryLister.GetNumberOfFiles()) {
      const char* const fname =
        this->DirectoryLister.GetFile(this->CurrentIdx++);
      if (isDirentryToIgnore(fname)) {
        continue;
      }
      if (cmsysString_strcasecmp(fname, this->DirName.data()) == 0) {
        auto candidate = cmStrCat(parent, fname, '/');
        if (cmSystemTools::FileIsDirectory(candidate)) {
          return candidate;
        }
      }
    }
    return {};
  }

  void Reset() { this->Loaded = false; }

private:
  cmsys::Directory DirectoryLister;
  const cm::string_view DirName;
  unsigned long CurrentIdx = 0ul;
  bool Loaded = false;
};

class cmDirectoryListGenerator
{
public:
  cmDirectoryListGenerator(std::vector<std::string> const* names,
                           bool exactMatch)
    : Names{ names }
    , ExactMatch{ exactMatch }
    , Current{ this->Matches.cbegin() }
  {
    assert(names || !exactMatch);
    assert(!names || !names->empty());
  }
  virtual ~cmDirectoryListGenerator() = default;

  std::string GetNextCandidate(const std::string& parent)
  {
    // Construct a list of matches if not yet
    if (this->Matches.empty()) {
      cmsys::Directory directoryLister;
      // ALERT `Directory::Load()` keeps only names
      // internally and LOST entry type from `dirent`.
      // So, `Directory::FileIsDirectory` gonna use
      // `SystemTools::FileIsDirectory()` and waste a syscall.
      // TODO Need to enhance the `Directory` class.
      directoryLister.Load(parent);

      // ATTENTION Is it guaranteed that first two entries are
      // `.` and `..`?
      // TODO If so, just start with index 2 and drop the
      // `isDirentryToIgnore(i)` condition to check.
      for (auto i = 0ul; i < directoryLister.GetNumberOfFiles(); ++i) {
        const char* const fname = directoryLister.GetFile(i);
        // Skip entries to ignore or that aren't directories.
        if (isDirentryToIgnore(fname) || !directoryLister.FileIsDirectory(i)) {
          continue;
        }

        if (!this->Names) {
          this->Matches.emplace_back(fname);
        } else {
          for (const auto& n : *this->Names) {
            // NOTE Customization point for
            // `cmMacProjectDirectoryListGenerator`
            const auto name = this->TransformNameBeforeCmp(n);
            // Skip entries that don't match.
            const auto equal =
              ((this->ExactMatch
                  ? cmsysString_strcasecmp(fname, name.c_str())
                  : cmsysString_strncasecmp(fname, name.c_str(),
                                            name.length())) == 0);
            if (equal) {
              this->Matches.emplace_back(fname);
              break;
            }
          }
        }
      }
      // NOTE Customization point for `cmProjectDirectoryListGenerator`
      this->OnMatchesLoaded();

      this->Current = this->Matches.cbegin();
    }

    if (this->Current != this->Matches.cend()) {
      auto candidate = cmStrCat(parent, *this->Current++, '/');
      return candidate;
    }

    return {};
  }

  void Reset()
  {
    this->Matches.clear();
    this->Current = this->Matches.cbegin();
  }

protected:
  virtual void OnMatchesLoaded() {}
  virtual std::string TransformNameBeforeCmp(std::string same) { return same; }

  std::vector<std::string> const* Names;
  bool const ExactMatch;
  std::vector<std::string> Matches;
  std::vector<std::string>::const_iterator Current;
};

class cmProjectDirectoryListGenerator : public cmDirectoryListGenerator
{
public:
  cmProjectDirectoryListGenerator(std::vector<std::string> const* names,
                                  cmFindPackageCommand::SortOrderType so,
                                  cmFindPackageCommand::SortDirectionType sd,
                                  bool exactMatch)
    : cmDirectoryListGenerator{ names, exactMatch }
    , SortOrder{ so }
    , SortDirection{ sd }
  {
  }

protected:
  void OnMatchesLoaded() override
  {
    // check if there is a specific sorting order to perform
    if (this->SortOrder != cmFindPackageCommand::None) {
      cmFindPackageCommand::Sort(this->Matches.begin(), this->Matches.end(),
                                 this->SortOrder, this->SortDirection);
    }
  }

private:
  // sort parameters
  const cmFindPackageCommand::SortOrderType SortOrder;
  const cmFindPackageCommand::SortDirectionType SortDirection;
};

class cmMacProjectDirectoryListGenerator : public cmDirectoryListGenerator
{
public:
  cmMacProjectDirectoryListGenerator(std::vector<std::string> const* names,
                                     cm::string_view ext)
    : cmDirectoryListGenerator{ names, true }
    , Extension{ ext }
  {
  }

protected:
  std::string TransformNameBeforeCmp(std::string name) override
  {
    return cmStrCat(name, this->Extension);
  }

private:
  const cm::string_view Extension;
};

class cmAnyDirectoryListGenerator : public cmProjectDirectoryListGenerator
{
public:
  cmAnyDirectoryListGenerator(cmFindPackageCommand::SortOrderType so,
                              cmFindPackageCommand::SortDirectionType sd)
    : cmProjectDirectoryListGenerator(nullptr, so, sd, false)
  {
  }
};

#if defined(__LCC__)
#  define CM_LCC_DIAG_SUPPRESS_1222
#  pragma diag_suppress 1222 // invalid error number (3288, but works anyway)
#  define CM_LCC_DIAG_SUPPRESS_3288
#  pragma diag_suppress 3288 // parameter was declared but never referenced
#  define CM_LCC_DIAG_SUPPRESS_3301
#  pragma diag_suppress 3301 // parameter was declared but never referenced
#  define CM_LCC_DIAG_SUPPRESS_3308
#  pragma diag_suppress 3308 // parameter was declared but never referenced
#endif

void ResetGenerator()
{
}

template <typename Generator>
void ResetGenerator(Generator&& generator)
{
  std::forward<Generator&&>(generator).Reset();
}

template <typename Generator, typename... Generators>
void ResetGenerator(Generator&& generator, Generators&&... generators)
{
  ResetGenerator(std::forward<Generator&&>(generator));
  ResetGenerator(std::forward<Generators&&>(generators)...);
}

template <typename CallbackFn>
bool TryGeneratedPaths(CallbackFn&& filesCollector,
                       cmFindPackageCommand::PackageDescriptionType type,
                       const std::string& fullPath)
{
  assert(!fullPath.empty() && fullPath.back() == '/');
  return std::forward<CallbackFn&&>(filesCollector)(fullPath, type);
}

template <typename CallbackFn, typename Generator, typename... Rest>
bool TryGeneratedPaths(CallbackFn&& filesCollector,
                       cmFindPackageCommand::PackageDescriptionType type,
                       const std::string& startPath, Generator&& gen,
                       Rest&&... tail)
{
  ResetGenerator(std::forward<Generator&&>(gen));
  for (auto path = gen.GetNextCandidate(startPath); !path.empty();
       path = gen.GetNextCandidate(startPath)) {
    ResetGenerator(std::forward<Rest&&>(tail)...);
    if (TryGeneratedPaths(std::forward<CallbackFn&&>(filesCollector), type,
                          path, std::forward<Rest&&>(tail)...)) {
      return true;
    }
  }
  return false;
}

#ifdef CM_LCC_DIAG_SUPPRESS_3308
#  undef CM_LCC_DIAG_SUPPRESS_3308
#  pragma diag_default 3308
#endif

#ifdef CM_LCC_DIAG_SUPPRESS_3301
#  undef CM_LCC_DIAG_SUPPRESS_3301
#  pragma diag_default 3301
#endif

#ifdef CM_LCC_DIAG_SUPPRESS_3288
#  undef CM_LCC_DIAG_SUPPRESS_3288
#  pragma diag_default 3288
#endif

#ifdef CM_LCC_DIAG_SUPPRESS_1222
#  undef CM_LCC_DIAG_SUPPRESS_1222
#  pragma diag_default 1222
#endif

// Parse the version number and store the results that were
// successfully parsed.
unsigned int parseVersion(std::string const& version, unsigned int& major,
                          unsigned int& minor, unsigned int& patch,
                          unsigned int& tweak)
{
  return static_cast<unsigned int>(std::sscanf(
    version.c_str(), "%u.%u.%u.%u", &major, &minor, &patch, &tweak));
}

} // anonymous namespace

class cmFindPackageCommand::FlushDebugBufferOnExit
{
  cmFindPackageCommand& Command;

public:
  FlushDebugBufferOnExit(cmFindPackageCommand& command)
    : Command(command)
  {
  }
  ~FlushDebugBufferOnExit()
  {
    if (!Command.DebugBuffer.empty()) {
      Command.DebugMessage(Command.DebugBuffer);
    }
  }
};

class cmFindPackageCommand::PushPopRootPathStack
{
  cmFindPackageCommand& Command;

public:
  PushPopRootPathStack(cmFindPackageCommand& command)
    : Command(command)
  {
    Command.PushFindPackageRootPathStack();
  }
  ~PushPopRootPathStack() { Command.PopFindPackageRootPathStack(); }
};

class cmFindPackageCommand::SetRestoreFindDefinitions
{
  cmFindPackageCommand& Command;

public:
  SetRestoreFindDefinitions(cmFindPackageCommand& command)
    : Command(command)
  {
    Command.SetModuleVariables();
  }
  ~SetRestoreFindDefinitions() { Command.RestoreFindDefinitions(); }
};

cmFindPackageCommand::PathLabel
  cmFindPackageCommand::PathLabel::PackageRedirect("PACKAGE_REDIRECT");
cmFindPackageCommand::PathLabel cmFindPackageCommand::PathLabel::UserRegistry(
  "PACKAGE_REGISTRY");
cmFindPackageCommand::PathLabel cmFindPackageCommand::PathLabel::Builds(
  "BUILDS");
cmFindPackageCommand::PathLabel
  cmFindPackageCommand::PathLabel::SystemRegistry("SYSTEM_PACKAGE_REGISTRY");

const cm::string_view cmFindPackageCommand::VERSION_ENDPOINT_INCLUDED(
  "INCLUDE");
const cm::string_view cmFindPackageCommand::VERSION_ENDPOINT_EXCLUDED(
  "EXCLUDE");

void cmFindPackageCommand::Sort(std::vector<std::string>::iterator begin,
                                std::vector<std::string>::iterator end,
                                SortOrderType const order,
                                SortDirectionType const dir)
{
  if (order == Name_order) {
    if (dir == Dec) {
      std::sort(begin, end, std::greater<std::string>());
    } else {
      std::sort(begin, end);
    }
  } else if (order == Natural) {
    // natural order uses letters and numbers (contiguous numbers digit are
    // compared such that e.g. 000  00 < 01 < 010 < 09 < 0 < 1 < 9 < 10
    if (dir == Dec) {
      std::sort(begin, end, StrverscmpOp<std::greater>());
    } else {
      std::sort(begin, end, StrverscmpOp<std::less>());
    }
  }
  // else do not sort
}

cmFindPackageCommand::cmFindPackageCommand(cmExecutionStatus& status)
  : cmFindCommon(status)
  , VersionRangeMin(VERSION_ENDPOINT_INCLUDED)
  , VersionRangeMax(VERSION_ENDPOINT_INCLUDED)
{
  this->CMakePathName = "PACKAGE";
  this->DebugMode = false;
  this->AppendSearchPathGroups();

  this->DeprecatedFindModules["Boost"] = cmPolicies::CMP0167;
  this->DeprecatedFindModules["CUDA"] = cmPolicies::CMP0146;
  this->DeprecatedFindModules["Dart"] = cmPolicies::CMP0145;
  this->DeprecatedFindModules["PythonInterp"] = cmPolicies::CMP0148;
  this->DeprecatedFindModules["PythonLibs"] = cmPolicies::CMP0148;
  this->DeprecatedFindModules["Qt"] = cmPolicies::CMP0084;
}

void cmFindPackageCommand::AppendSearchPathGroups()
{
  // Update the All group with new paths. Note that package redirection must
  // take precedence over everything else, so it has to be first in the array.
  std::vector<cmFindCommon::PathLabel>* const labels =
    &this->PathGroupLabelMap[PathGroup::All];
  labels->insert(labels->begin(), PathLabel::PackageRedirect);
  labels->insert(
    std::find(labels->begin(), labels->end(), PathLabel::CMakeSystem),
    PathLabel::UserRegistry);
  labels->insert(
    std::find(labels->begin(), labels->end(), PathLabel::CMakeSystem),
    PathLabel::Builds);
  labels->insert(std::find(labels->begin(), labels->end(), PathLabel::Guess),
                 PathLabel::SystemRegistry);

  // Create the new path objects
  this->LabeledPaths.emplace(PathLabel::PackageRedirect, cmSearchPath{ this });
  this->LabeledPaths.emplace(PathLabel::UserRegistry, cmSearchPath{ this });
  this->LabeledPaths.emplace(PathLabel::Builds, cmSearchPath{ this });
  this->LabeledPaths.emplace(PathLabel::SystemRegistry, cmSearchPath{ this });
}

void cmFindPackageCommand::InheritOptions(cmFindPackageCommand* other)
{
  this->RequiredCMakeVersion = other->RequiredCMakeVersion;
  this->LibraryArchitecture = other->LibraryArchitecture;
  this->UseLib32Paths = other->UseLib32Paths;
  this->UseLib64Paths = other->UseLib64Paths;
  this->UseLibx32Paths = other->UseLibx32Paths;
  this->NoUserRegistry = other->NoUserRegistry;
  this->NoSystemRegistry = other->NoSystemRegistry;
  this->UseRealPath = other->UseRealPath;
  this->SortOrder = other->SortOrder;
  this->SortDirection = other->SortDirection;

  this->GlobalScope = other->GlobalScope;
  this->RegistryView = other->RegistryView;
  this->NoDefaultPath = other->NoDefaultPath;
  this->NoPackageRootPath = other->NoPackageRootPath;
  this->NoCMakePath = other->NoCMakePath;
  this->NoCMakeEnvironmentPath = other->NoCMakeEnvironmentPath;
  this->NoSystemEnvironmentPath = other->NoSystemEnvironmentPath;
  this->NoCMakeSystemPath = other->NoCMakeSystemPath;
  this->NoCMakeInstallPath = other->NoCMakeInstallPath;
  this->FindRootPathMode = other->FindRootPathMode;

  this->SearchFrameworkLast = other->SearchFrameworkLast;
  this->SearchFrameworkFirst = other->SearchFrameworkFirst;
  this->SearchFrameworkOnly = other->SearchFrameworkOnly;
  this->SearchAppBundleLast = other->SearchAppBundleLast;
  this->SearchAppBundleFirst = other->SearchAppBundleFirst;
  this->SearchAppBundleOnly = other->SearchAppBundleOnly;
  this->SearchPathSuffixes = other->SearchPathSuffixes;

  this->Quiet = other->Quiet;
}

bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args)
{
  if (args.empty()) {
    this->SetError("called with incorrect number of arguments");
    return false;
  }

  // Lookup required version of CMake.
  if (cmValue const rv =
        this->Makefile->GetDefinition("CMAKE_MINIMUM_REQUIRED_VERSION")) {
    unsigned int v[3] = { 0, 0, 0 };
    std::sscanf(rv->c_str(), "%u.%u.%u", &v[0], &v[1], &v[2]);
    this->RequiredCMakeVersion = CMake_VERSION_ENCODE(v[0], v[1], v[2]);
  }

  // Lookup target architecture, if any.
  if (cmValue const arch =
        this->Makefile->GetDefinition("CMAKE_LIBRARY_ARCHITECTURE")) {
    this->LibraryArchitecture = *arch;
  }

  // Lookup whether lib32 paths should be used.
  if (this->Makefile->PlatformIs32Bit() &&
      this->Makefile->GetState()->GetGlobalPropertyAsBool(
        "FIND_LIBRARY_USE_LIB32_PATHS")) {
    this->UseLib32Paths = true;
  }

  // Lookup whether lib64 paths should be used.
  if (this->Makefile->PlatformIs64Bit() &&
      this->Makefile->GetState()->GetGlobalPropertyAsBool(
        "FIND_LIBRARY_USE_LIB64_PATHS")) {
    this->UseLib64Paths = true;
  }

  // Lookup whether libx32 paths should be used.
  if (this->Makefile->PlatformIsx32() &&
      this->Makefile->GetState()->GetGlobalPropertyAsBool(
        "FIND_LIBRARY_USE_LIBX32_PATHS")) {
    this->UseLibx32Paths = true;
  }

  // Check if User Package Registry should be disabled
  // The `CMAKE_FIND_USE_PACKAGE_REGISTRY` has
  // priority over the deprecated CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY
  if (cmValue const def =
        this->Makefile->GetDefinition("CMAKE_FIND_USE_PACKAGE_REGISTRY")) {
    this->NoUserRegistry = !def.IsOn();
  } else if (this->Makefile->IsOn("CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY")) {
    this->NoUserRegistry = true;
  }

  // Check if System Package Registry should be disabled
  // The `CMAKE_FIND_USE_SYSTEM_PACKAGE_REGISTRY` has
  // priority over the deprecated CMAKE_FIND_PACKAGE_NO_SYSTEM_PACKAGE_REGISTRY
  if (cmValue const def = this->Makefile->GetDefinition(
        "CMAKE_FIND_USE_SYSTEM_PACKAGE_REGISTRY")) {
    this->NoSystemRegistry = !def.IsOn();
  } else if (this->Makefile->IsOn(
               "CMAKE_FIND_PACKAGE_NO_SYSTEM_PACKAGE_REGISTRY")) {
    this->NoSystemRegistry = true;
  }

  // Check whether we should resolve symlinks when finding packages
  if (this->Makefile->IsOn("CMAKE_FIND_PACKAGE_RESOLVE_SYMLINKS")) {
    this->UseRealPath = true;
  }

  // Check if Sorting should be enabled
  if (cmValue const so =
        this->Makefile->GetDefinition("CMAKE_FIND_PACKAGE_SORT_ORDER")) {

    if (*so == "NAME") {
      this->SortOrder = Name_order;
    } else if (*so == "NATURAL") {
      this->SortOrder = Natural;
    } else {
      this->SortOrder = None;
    }
  }
  if (cmValue const sd =
        this->Makefile->GetDefinition("CMAKE_FIND_PACKAGE_SORT_DIRECTION")) {
    this->SortDirection = (*sd == "ASC") ? Asc : Dec;
  }

  // Find what search path locations have been enabled/disable.
  this->SelectDefaultSearchModes();

  // Find the current root path mode.
  this->SelectDefaultRootPathMode();

  // Find the current bundle/framework search policy.
  this->SelectDefaultMacMode();

  // Record options.
  this->Name = args[0];
  cm::string_view componentsSep = ""_s;
  bool bypassProvider = false;

  // Always search directly in a generated path.
  this->SearchPathSuffixes.emplace_back();

  // Process debug mode
  cmMakefile::DebugFindPkgRAII debugFindPkgRAII(this->Makefile, this->Name);
  this->DebugMode = this->ComputeIfDebugModeWanted();

  // Parse the arguments.
  enum Doing
  {
    DoingNone,
    DoingComponents,
    DoingOptionalComponents,
    DoingNames,
    DoingPaths,
    DoingPathSuffixes,
    DoingConfigs,
    DoingHints
  };
  Doing doing = DoingNone;
  cmsys::RegularExpression versionRegex(
    R"V(^([0-9]+(\.[0-9]+)*)(\.\.\.(<?)([0-9]+(\.[0-9]+)*))?$)V");
  bool haveVersion = false;
  std::vector<std::size_t> configArgs;
  std::vector<std::size_t> moduleArgs;
  for (std::size_t i = 1u; i < args.size(); ++i) {
    if (args[i] == "QUIET") {
      this->Quiet = true;
      doing = DoingNone;
    } else if (args[i] == "BYPASS_PROVIDER") {
      bypassProvider = true;
      doing = DoingNone;
    } else if (args[i] == "EXACT") {
      this->VersionExact = true;
      doing = DoingNone;
    } else if (args[i] == "GLOBAL") {
      this->GlobalScope = true;
      doing = DoingNone;
    } else if (args[i] == "MODULE") {
      moduleArgs.push_back(i);
      doing = DoingNone;
      // XXX(clang-tidy): https://bugs.llvm.org/show_bug.cgi?id=44165
      // NOLINTNEXTLINE(bugprone-branch-clone)
    } else if (args[i] == "CONFIG") {
      configArgs.push_back(i);
      doing = DoingNone;
      // XXX(clang-tidy): https://bugs.llvm.org/show_bug.cgi?id=44165
      // NOLINTNEXTLINE(bugprone-branch-clone)
    } else if (args[i] == "NO_MODULE") {
      configArgs.push_back(i);
      doing = DoingNone;
    } else if (args[i] == "REQUIRED") {
      this->Required = true;
      doing = DoingComponents;
    } else if (args[i] == "COMPONENTS") {
      doing = DoingComponents;
    } else if (args[i] == "OPTIONAL_COMPONENTS") {
      doing = DoingOptionalComponents;
    } else if (args[i] == "NAMES") {
      configArgs.push_back(i);
      doing = DoingNames;
    } else if (args[i] == "PATHS") {
      configArgs.push_back(i);
      doing = DoingPaths;
    } else if (args[i] == "HINTS") {
      configArgs.push_back(i);
      doing = DoingHints;
    } else if (args[i] == "PATH_SUFFIXES") {
      configArgs.push_back(i);
      doing = DoingPathSuffixes;
    } else if (args[i] == "CONFIGS") {
      configArgs.push_back(i);
      doing = DoingConfigs;
    } else if (args[i] == "NO_POLICY_SCOPE") {
      this->PolicyScope = false;
      doing = DoingNone;
    } else if (args[i] == "NO_CMAKE_PACKAGE_REGISTRY") {
      this->NoUserRegistry = true;
      configArgs.push_back(i);
      doing = DoingNone;
    } else if (args[i] == "NO_CMAKE_SYSTEM_PACKAGE_REGISTRY") {
      this->NoSystemRegistry = true;
      configArgs.push_back(i);
      doing = DoingNone;
      // XXX(clang-tidy): https://bugs.llvm.org/show_bug.cgi?id=44165
      // NOLINTNEXTLINE(bugprone-branch-clone)
    } else if (args[i] == "NO_CMAKE_BUILDS_PATH") {
      // Ignore legacy option.
      configArgs.push_back(i);
      doing = DoingNone;
    } else if (args[i] == "REGISTRY_VIEW") {
      if (++i == args.size()) {
        this->SetError("missing required argument for REGISTRY_VIEW");
        return false;
      }
      auto view = cmWindowsRegistry::ToView(args[i]);
      if (view) {
        this->RegistryView = *view;
        this->RegistryViewDefined = true;
      } else {
        this->SetError(
          cmStrCat("given invalid value for REGISTRY_VIEW: ", args[i]));
        return false;
      }
    } else if (this->CheckCommonArgument(args[i])) {
      configArgs.push_back(i);
      doing = DoingNone;
    } else if ((doing == DoingComponents) ||
               (doing == DoingOptionalComponents)) {
      // Set a variable telling the find script whether this component
      // is required.
      if (doing == DoingOptionalComponents) {
        this->OptionalComponents.insert(args[i]);
      } else {
        this->RequiredComponents.insert(args[i]);
      }

      // Append to the list of required components.
      this->Components += componentsSep;
      this->Components += args[i];
      componentsSep = ";"_s;
    } else if (doing == DoingNames) {
      this->Names.push_back(args[i]);
    } else if (doing == DoingPaths) {
      this->UserGuessArgs.push_back(args[i]);
    } else if (doing == DoingHints) {
      this->UserHintsArgs.push_back(args[i]);
    } else if (doing == DoingPathSuffixes) {
      this->AddPathSuffix(args[i]);
    } else if (doing == DoingConfigs) {
      if (args[i].find_first_of(":/\\") != std::string::npos ||
          cmSystemTools::GetFilenameLastExtension(args[i]) != ".cmake") {
        this->SetError(cmStrCat(
          "given CONFIGS option followed by invalid file name \"", args[i],
          "\".  The names given must be file names without "
          "a path and with a \".cmake\" extension."));
        return false;
      }
      this->Configs.emplace_back(args[i], pdt::CMake);
    } else if (!haveVersion && versionRegex.find(args[i])) {
      haveVersion = true;
      this->VersionComplete = args[i];
    } else {
      this->SetError(
        cmStrCat("called with invalid argument \"", args[i], "\""));
      return false;
    }
  }

  if (!this->GlobalScope) {
    cmValue value(
      this->Makefile->GetDefinition("CMAKE_FIND_PACKAGE_TARGETS_GLOBAL"));
    this->GlobalScope = value.IsOn();
  }

  std::vector<std::string> doubledComponents;
  std::set_intersection(
    this->RequiredComponents.begin(), this->RequiredComponents.end(),
    this->OptionalComponents.begin(), this->OptionalComponents.end(),
    std::back_inserter(doubledComponents));
  if (!doubledComponents.empty()) {
    this->SetError(
      cmStrCat("called with components that are both required and "
               "optional:\n",
               cmWrap("  ", doubledComponents, "", "\n"), '\n'));
    return false;
  }

  // Check and eliminate search modes not allowed by the args provided
  this->UseFindModules = configArgs.empty();
  this->UseConfigFiles = moduleArgs.empty();
  if (this->UseConfigFiles &&
      cmExperimental::HasSupportEnabled(
        *this->Makefile, cmExperimental::Feature::ImportPackageInfo)) {
    this->UseCpsFiles = this->Configs.empty();
  } else {
    this->UseCpsFiles = false;
  }
  if (!this->UseFindModules && !this->UseConfigFiles) {
    std::ostringstream e;
    e << "given options exclusive to Module mode:\n";
    for (auto si : moduleArgs) {
      e << "  " << args[si] << "\n";
    }
    e << "and options exclusive to Config mode:\n";
    for (auto si : configArgs) {
      e << "  " << args[si] << "\n";
    }
    e << "The options are incompatible.";
    this->SetError(e.str());
    return false;
  }

  // Ignore EXACT with no version.
  if (this->VersionComplete.empty() && this->VersionExact) {
    this->VersionExact = false;
    this->Makefile->IssueMessage(
      MessageType::AUTHOR_WARNING,
      "Ignoring EXACT since no version is requested.");
  }

  if (this->VersionComplete.empty() || this->Components.empty()) {
    // Check whether we are recursing inside "Find<name>.cmake" within
    // another find_package(<name>) call.
    std::string const mod = cmStrCat(this->Name, "_FIND_MODULE");
    if (this->Makefile->IsOn(mod)) {
      if (this->VersionComplete.empty()) {
        // Get version information from the outer call if necessary.
        // Requested version string.
        std::string const ver = cmStrCat(this->Name, "_FIND_VERSION_COMPLETE");
        this->VersionComplete = this->Makefile->GetSafeDefinition(ver);

        // Whether an exact version is required.
        std::string const exact = cmStrCat(this->Name, "_FIND_VERSION_EXACT");
        this->VersionExact = this->Makefile->IsOn(exact);
      }
      if (this->Components.empty()) {
        std::string const components_var = this->Name + "_FIND_COMPONENTS";
        this->Components = this->Makefile->GetSafeDefinition(components_var);
        for (auto const& component : cmList{ this->Components }) {
          this->RequiredComponents.insert(component);
        }
      }
    }
  }

  // fill various parts of version specification
  if (!this->VersionComplete.empty()) {
    if (!versionRegex.find(this->VersionComplete)) {
      this->SetError("called with invalid version specification.");
      return false;
    }

    this->Version = versionRegex.match(1);
    this->VersionMax = versionRegex.match(5);
    if (versionRegex.match(4) == "<"_s) {
      this->VersionRangeMax = VERSION_ENDPOINT_EXCLUDED;
    }
    if (!this->VersionMax.empty()) {
      this->VersionRange = this->VersionComplete;
    }
  }

  if (!this->VersionRange.empty()) {
    // version range must not be empty
    if ((this->VersionRangeMax == VERSION_ENDPOINT_INCLUDED &&
         cmSystemTools::VersionCompareGreater(this->Version,
                                              this->VersionMax)) ||
        (this->VersionRangeMax == VERSION_ENDPOINT_EXCLUDED &&
         cmSystemTools::VersionCompareGreaterEq(this->Version,
                                                this->VersionMax))) {
      this->SetError("specified version range is empty.");
      return false;
    }
  }

  if (this->VersionExact && !this->VersionRange.empty()) {
    this->SetError("EXACT cannot be specified with a version range.");
    return false;
  }

  if (!this->Version.empty()) {
    this->VersionCount =
      parseVersion(this->Version, this->VersionMajor, this->VersionMinor,
                   this->VersionPatch, this->VersionTweak);
  }
  if (!this->VersionMax.empty()) {
    this->VersionMaxCount = parseVersion(
      this->VersionMax, this->VersionMaxMajor, this->VersionMaxMinor,
      this->VersionMaxPatch, this->VersionMaxTweak);
  }

  return this->FindPackage(bypassProvider ? std::vector<std::string>{} : args);
}

bool cmFindPackageCommand::FindPackage(
  std::vector<std::string> const& argsForProvider)
{
  const std::string makePackageRequiredVar =
    cmStrCat("CMAKE_REQUIRE_FIND_PACKAGE_", this->Name);
  const bool makePackageRequiredSet =
    this->Makefile->IsOn(makePackageRequiredVar);
  if (makePackageRequiredSet) {
    if (this->Required) {
      this->Makefile->IssueMessage(
        MessageType::WARNING,
        cmStrCat("for module ", this->Name,
                 " already called with REQUIRED, thus ",
                 makePackageRequiredVar, " has no effect."));
    } else {
      this->Required = true;
    }
  }

  std::string const disableFindPackageVar =
    cmStrCat("CMAKE_DISABLE_FIND_PACKAGE_", this->Name);
  if (this->Makefile->IsOn(disableFindPackageVar)) {
    if (this->Required) {
      this->SetError(
        cmStrCat("for module ", this->Name,
                 (makePackageRequiredSet
                    ? " was made REQUIRED with " + makePackageRequiredVar
                    : " called with REQUIRED, "),
                 " but ", disableFindPackageVar,
                 " is enabled. A REQUIRED package cannot be disabled."));
      return false;
    }
    return true;
  }

  // Restore PACKAGE_PREFIX_DIR to its pre-call value when we return. If our
  // caller is a file generated by configure_package_config_file(), and if
  // the package we are about to load also has a config file created by that
  // command, it will overwrite PACKAGE_PREFIX_DIR. We need to restore it in
  // case something still refers to it in our caller's scope after we return.
  class RestoreVariableOnLeavingScope
  {
    cmMakefile* makefile_;
    cm::optional<std::string> value_;

  public:
    RestoreVariableOnLeavingScope(cmMakefile* makefile)
      : makefile_(makefile)
    {
      cmValue v = makefile->GetDefinition("PACKAGE_PREFIX_DIR");
      if (v) {
        value_ = *v;
      }
    }
    ~RestoreVariableOnLeavingScope()
    {
      if (this->value_) {
        makefile_->AddDefinition("PACKAGE_PREFIX_DIR", *value_);
      } else {
        makefile_->RemoveDefinition("PACKAGE_PREFIX_DIR");
      }
    }
  };
  RestoreVariableOnLeavingScope restorePackagePrefixDir(this->Makefile);

  // Now choose what method(s) we will use to satisfy the request. Note that
  // we still want all the above checking of arguments, etc. regardless of the
  // method used. This will ensure ill-formed arguments are caught earlier,
  // before things like dependency providers need to deal with them.

  // A dependency provider (if set) gets first look before other methods.
  // We do this before modifying the package root path stack because a
  // provider might use methods that ignore that.
  cmState* const state = this->Makefile->GetState();
  cmState::Command const providerCommand = state->GetDependencyProviderCommand(
    cmDependencyProvider::Method::FindPackage);
  if (argsForProvider.empty()) {
    if (this->DebugMode && providerCommand) {
      this->DebugMessage(
        "BYPASS_PROVIDER given, skipping dependency provider");
    }
  } else if (providerCommand) {
    if (this->DebugMode) {
      this->DebugMessage(cmStrCat("Trying dependency provider command: ",
                                  state->GetDependencyProvider()->GetCommand(),
                                  "()"));
    }
    std::vector<cmListFileArgument> listFileArgs(argsForProvider.size() + 1);
    listFileArgs[0] =
      cmListFileArgument("FIND_PACKAGE", cmListFileArgument::Unquoted, 0);
    std::transform(argsForProvider.begin(), argsForProvider.end(),
                   listFileArgs.begin() + 1, [](const std::string& arg) {
                     return cmListFileArgument(arg,
                                               cmListFileArgument::Bracket, 0);
                   });
    if (!providerCommand(listFileArgs, this->Status)) {
      return false;
    }
    if (this->Makefile->IsOn(cmStrCat(this->Name, "_FOUND"))) {
      if (this->DebugMode) {
        this->DebugMessage("Package was found by the dependency provider");
      }
      this->AppendSuccessInformation();
      return true;
    }
  }

  // Limit package nesting depth well below the recursion depth limit because
  // find_package nesting uses more stack space than normal recursion.
  {
    static std::size_t const findPackageDepthMinMax = 100;
    std::size_t const findPackageDepthMax = std::max(
      this->Makefile->GetRecursionDepthLimit() / 2, findPackageDepthMinMax);
    std::size_t const findPackageDepth =
      this->Makefile->FindPackageRootPathStack.size() + 1;
    if (findPackageDepth > findPackageDepthMax) {
      this->SetError(cmStrCat("maximum nesting depth of ", findPackageDepthMax,
                              " exceeded."));
      return false;
    }
  }

  // RAII objects to ensure we leave this function with consistent state.
  FlushDebugBufferOnExit flushDebugBufferOnExit(*this);
  PushPopRootPathStack pushPopRootPathStack(*this);
  SetRestoreFindDefinitions setRestoreFindDefinitions(*this);
  cmMakefile::FindPackageStackRAII findPackageStackRAII(this->Makefile,
                                                        this->Name);

  // See if we have been told to delegate to FetchContent or some other
  // redirected config package first. We have to check all names that
  // find_package() may look for, but only need to invoke the override for the
  // first one that matches.
  auto overrideNames = this->Names;
  if (overrideNames.empty()) {
    overrideNames.push_back(this->Name);
  }
  bool forceConfigMode = false;
  const auto redirectsDir =
    this->Makefile->GetSafeDefinition("CMAKE_FIND_PACKAGE_REDIRECTS_DIR");
  for (const auto& overrideName : overrideNames) {
    const auto nameLower = cmSystemTools::LowerCase(overrideName);
    const auto delegatePropName =
      cmStrCat("_FetchContent_", nameLower, "_override_find_package");
    const cmValue delegateToFetchContentProp =
      this->Makefile->GetState()->GetGlobalProperty(delegatePropName);
    if (delegateToFetchContentProp.IsOn()) {
      // When this property is set, the FetchContent module has already been
      // included at least once, so we know the FetchContent_MakeAvailable()
      // command will be defined. Any future find_package() calls after this
      // one for this package will by-pass this once-only delegation.
      // The following call will typically create a <name>-config.cmake file
      // in the redirectsDir, which we still want to process like any other
      // config file to ensure we follow normal find_package() processing.
      cmListFileFunction func(
        "FetchContent_MakeAvailable", 0, 0,
        { cmListFileArgument(overrideName, cmListFileArgument::Unquoted, 0) });
      if (!this->Makefile->ExecuteCommand(func, this->Status)) {
        return false;
      }
    }

    if (cmSystemTools::FileExists(
          cmStrCat(redirectsDir, '/', nameLower, "-config.cmake")) ||
        cmSystemTools::FileExists(
          cmStrCat(redirectsDir, '/', overrideName, "Config.cmake"))) {
      // Force the use of this redirected config package file, regardless of
      // the type of find_package() call. Files in the redirectsDir must always
      // take priority over everything else.
      forceConfigMode = true;
      this->UseConfigFiles = true;
      this->UseFindModules = false;
      this->Names.clear();
      this->Names.emplace_back(overrideName); // Force finding this one
      this->Variable = cmStrCat(this->Name, "_DIR");
      this->SetConfigDirCacheVariable(redirectsDir);
      break;
    }
  }

  // See if there is a Find<PackageName>.cmake module.
  bool loadedPackage = false;
  if (forceConfigMode) {
    loadedPackage = this->FindPackageUsingConfigMode();
  } else if (this->Makefile->IsOn("CMAKE_FIND_PACKAGE_PREFER_CONFIG")) {
    if (this->UseConfigFiles && this->FindPackageUsingConfigMode()) {
      loadedPackage = true;
    } else {
      if (this->FindPackageUsingModuleMode()) {
        loadedPackage = true;
      } else {
        // The package was not loaded. Report errors.
        if (this->HandlePackageMode(HandlePackageModeType::Module)) {
          loadedPackage = true;
        }
      }
    }
  } else {
    if (this->UseFindModules && this->FindPackageUsingModuleMode()) {
      loadedPackage = true;
    } else {
      // Handle CMAKE_FIND_PACKAGE_WARN_NO_MODULE (warn when CONFIG mode is
      // implicitly assumed)
      if (this->UseFindModules && this->UseConfigFiles &&
          this->Makefile->IsOn("CMAKE_FIND_PACKAGE_WARN_NO_MODULE")) {
        std::ostringstream aw;
        if (this->RequiredCMakeVersion >= CMake_VERSION_ENCODE(2, 8, 8)) {
          aw << "find_package called without either MODULE or CONFIG option "
                "and "
                "no Find"
             << this->Name
             << ".cmake module is in CMAKE_MODULE_PATH.  "
                "Add MODULE to exclusively request Module mode and fail if "
                "Find"
             << this->Name
             << ".cmake is missing.  "
                "Add CONFIG to exclusively request Config mode and search for "
                "a "
                "package configuration file provided by "
             << this->Name << " (" << this->Name << "Config.cmake or "
             << cmSystemTools::LowerCase(this->Name) << "-config.cmake).  ";
        } else {
          aw << "find_package called without NO_MODULE option and no "
                "Find"
             << this->Name
             << ".cmake module is in CMAKE_MODULE_PATH.  "
                "Add NO_MODULE to exclusively request Config mode and search "
                "for a "
                "package configuration file provided by "
             << this->Name << " (" << this->Name << "Config.cmake or "
             << cmSystemTools::LowerCase(this->Name)
             << "-config.cmake).  Otherwise make Find" << this->Name
             << ".cmake available in CMAKE_MODULE_PATH.";
        }
        aw << "\n"
              "(Variable CMAKE_FIND_PACKAGE_WARN_NO_MODULE enabled this "
              "warning.)";
        this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, aw.str());
      }

      if (this->FindPackageUsingConfigMode()) {
        loadedPackage = true;
      }
    }
  }

  this->AppendSuccessInformation();

  return loadedPackage;
}

bool cmFindPackageCommand::FindPackageUsingModuleMode()
{
  bool foundModule = false;
  if (!this->FindModule(foundModule)) {
    return false;
  }
  return foundModule;
}

bool cmFindPackageCommand::FindPackageUsingConfigMode()
{
  this->Variable = cmStrCat(this->Name, "_DIR");

  // Add the default name.
  if (this->Names.empty()) {
    this->Names.push_back(this->Name);
  }

  // Add the default configs.
  if (this->Configs.empty()) {
    for (std::string const& n : this->Names) {
      std::string config;
      if (this->UseCpsFiles) {
        config = cmStrCat(n, ".cps");
        this->Configs.emplace_back(std::move(config), pdt::Cps);

        config = cmStrCat(cmSystemTools::LowerCase(n), ".cps");
        if (config != this->Configs.front().Name) {
          this->Configs.emplace_back(std::move(config), pdt::Cps);
        }
      }

      config = cmStrCat(n, "Config.cmake");
      this->Configs.emplace_back(std::move(config), pdt::CMake);

      config = cmStrCat(cmSystemTools::LowerCase(n), "-config.cmake");
      this->Configs.emplace_back(std::move(config), pdt::CMake);
    }
  }

  // get igonored paths from vars and reroot them.
  std::vector<std::string> ignored;
  this->GetIgnoredPaths(ignored);
  this->RerootPaths(ignored);

  // Construct a set of ignored paths
  this->IgnoredPaths.clear();
  this->IgnoredPaths.insert(ignored.begin(), ignored.end());

  // get igonored prefix paths from vars and reroot them.
  std::vector<std::string> ignoredPrefixes;
  this->GetIgnoredPrefixPaths(ignoredPrefixes);
  this->RerootPaths(ignoredPrefixes);

  // Construct a set of ignored prefix paths
  this->IgnoredPrefixPaths.clear();
  this->IgnoredPrefixPaths.insert(ignoredPrefixes.begin(),
                                  ignoredPrefixes.end());

  // Find and load the package.
  return this->HandlePackageMode(HandlePackageModeType::Config);
}

void cmFindPackageCommand::SetVersionVariables(
  const std::function<void(const std::string&, cm::string_view)>&
    addDefinition,
  const std::string& prefix, const std::string& version,
  const unsigned int count, const unsigned int major, const unsigned int minor,
  const unsigned int patch, const unsigned int tweak)
{
  addDefinition(prefix, version);

  char buf[64];
  snprintf(buf, sizeof(buf), "%u", major);
  addDefinition(prefix + "_MAJOR", buf);
  snprintf(buf, sizeof(buf), "%u", minor);
  addDefinition(prefix + "_MINOR", buf);
  snprintf(buf, sizeof(buf), "%u", patch);
  addDefinition(prefix + "_PATCH", buf);
  snprintf(buf, sizeof(buf), "%u", tweak);
  addDefinition(prefix + "_TWEAK", buf);
  snprintf(buf, sizeof(buf), "%u", count);
  addDefinition(prefix + "_COUNT", buf);
}

void cmFindPackageCommand::SetModuleVariables()
{
  this->AddFindDefinition("CMAKE_FIND_PACKAGE_NAME", this->Name);

  // Store the list of components and associated variable definitions.
  std::string components_var = this->Name + "_FIND_COMPONENTS";
  this->AddFindDefinition(components_var, this->Components);
  for (auto const& component : this->OptionalComponents) {
    this->AddFindDefinition(
      cmStrCat(this->Name, "_FIND_REQUIRED_"_s, component), "0"_s);
  }
  for (auto const& component : this->RequiredComponents) {
    this->AddFindDefinition(
      cmStrCat(this->Name, "_FIND_REQUIRED_"_s, component), "1"_s);
  }

  if (this->Quiet) {
    // Tell the module that is about to be read that it should find
    // quietly.
    std::string quietly = cmStrCat(this->Name, "_FIND_QUIETLY");
    this->AddFindDefinition(quietly, "1"_s);
  }

  if (this->Required) {
    // Tell the module that is about to be read that it should report
    // a fatal error if the package is not found.
    std::string req = cmStrCat(this->Name, "_FIND_REQUIRED");
    this->AddFindDefinition(req, "1"_s);
  }

  if (!this->VersionComplete.empty()) {
    std::string req = cmStrCat(this->Name, "_FIND_VERSION_COMPLETE");
    this->AddFindDefinition(req, this->VersionComplete);
  }

  // Tell the module that is about to be read what version of the
  // package has been requested.
  auto addDefinition = [this](const std::string& variable,
                              cm::string_view value) {
    this->AddFindDefinition(variable, value);
  };

  if (!this->Version.empty()) {
    auto prefix = cmStrCat(this->Name, "_FIND_VERSION"_s);
    this->SetVersionVariables(addDefinition, prefix, this->Version,
                              this->VersionCount, this->VersionMajor,
                              this->VersionMinor, this->VersionPatch,
                              this->VersionTweak);

    // Tell the module whether an exact version has been requested.
    auto exact = cmStrCat(this->Name, "_FIND_VERSION_EXACT");
    this->AddFindDefinition(exact, this->VersionExact ? "1"_s : "0"_s);
  }
  if (!this->VersionRange.empty()) {
    auto prefix = cmStrCat(this->Name, "_FIND_VERSION_MIN"_s);
    this->SetVersionVariables(addDefinition, prefix, this->Version,
                              this->VersionCount, this->VersionMajor,
                              this->VersionMinor, this->VersionPatch,
                              this->VersionTweak);

    prefix = cmStrCat(this->Name, "_FIND_VERSION_MAX"_s);
    this->SetVersionVariables(addDefinition, prefix, this->VersionMax,
                              this->VersionMaxCount, this->VersionMaxMajor,
                              this->VersionMaxMinor, this->VersionMaxPatch,
                              this->VersionMaxTweak);

    auto id = cmStrCat(this->Name, "_FIND_VERSION_RANGE");
    this->AddFindDefinition(id, this->VersionRange);
    id = cmStrCat(this->Name, "_FIND_VERSION_RANGE_MIN");
    this->AddFindDefinition(id, this->VersionRangeMin);
    id = cmStrCat(this->Name, "_FIND_VERSION_RANGE_MAX");
    this->AddFindDefinition(id, this->VersionRangeMax);
  }

  if (this->RegistryViewDefined) {
    this->AddFindDefinition(cmStrCat(this->Name, "_FIND_REGISTRY_VIEW"),
                            cmWindowsRegistry::FromView(this->RegistryView));
  }
}

void cmFindPackageCommand::AddFindDefinition(const std::string& var,
                                             const cm::string_view value)
{
  if (cmValue old = this->Makefile->GetDefinition(var)) {
    this->OriginalDefs[var].exists = true;
    this->OriginalDefs[var].value = *old;
  } else {
    this->OriginalDefs[var].exists = false;
  }
  this->Makefile->AddDefinition(var, value);
}

void cmFindPackageCommand::RestoreFindDefinitions()
{
  for (auto const& i : this->OriginalDefs) {
    OriginalDef const& od = i.second;
    if (od.exists) {
      this->Makefile->AddDefinition(i.first, od.value);
    } else {
      this->Makefile->RemoveDefinition(i.first);
    }
  }
}

bool cmFindPackageCommand::FindModule(bool& found)
{
  std::string moduleFileName = cmStrCat("Find", this->Name, ".cmake");

  bool system = false;
  std::string debugBuffer = cmStrCat(
    "find_package considered the following paths for ", moduleFileName, ":\n");
  std::string mfile = this->Makefile->GetModulesFile(
    moduleFileName, system, this->DebugMode, debugBuffer);
  if (this->DebugMode) {
    if (mfile.empty()) {
      debugBuffer = cmStrCat(debugBuffer, "The file was not found.\n");
    } else {
      debugBuffer =
        cmStrCat(debugBuffer, "The file was found at\n  ", mfile, '\n');
    }
    this->DebugBuffer = cmStrCat(this->DebugBuffer, debugBuffer);
  }

  if (!mfile.empty()) {
    if (system) {
      auto const it = this->DeprecatedFindModules.find(this->Name);
      if (it != this->DeprecatedFindModules.end()) {
        cmPolicies::PolicyStatus status =
          this->Makefile->GetPolicyStatus(it->second);
        switch (status) {
          case cmPolicies::WARN: {
            this->Makefile->IssueMessage(
              MessageType::AUTHOR_WARNING,
              cmStrCat(cmPolicies::GetPolicyWarning(it->second), '\n'));
            CM_FALLTHROUGH;
          }
          case cmPolicies::OLD:
            break;
          case cmPolicies::NEW:
            return true;
        }
      }
    }

    // Load the module we found, and set "<name>_FIND_MODULE" to true
    // while inside it.
    found = true;
    std::string const var = cmStrCat(this->Name, "_FIND_MODULE");
    this->Makefile->AddDefinition(var, "1");
    bool result = this->ReadListFile(mfile, DoPolicyScope);
    this->Makefile->RemoveDefinition(var);

    if (this->DebugMode) {
      std::string const foundVar = cmStrCat(this->Name, "_FOUND");
      if (this->Makefile->IsDefinitionSet(foundVar) &&
          !this->Makefile->IsOn(foundVar)) {

        this->DebugBuffer = cmStrCat(
          this->DebugBuffer, "The module is considered not found due to ",
          foundVar, " being FALSE.");
      }
    }
    return result;
  }
  return true;
}

bool cmFindPackageCommand::HandlePackageMode(
  const HandlePackageModeType handlePackageModeType)
{
  this->ConsideredConfigs.clear();

  // Try to find the config file.
  cmValue def = this->Makefile->GetDefinition(this->Variable);

  // Try to load the config file if the directory is known
  bool fileFound = false;
  if (this->UseConfigFiles) {
    if (!def.IsOff()) {
      // Get the directory from the variable value.
      std::string dir = *def;
      cmSystemTools::ConvertToUnixSlashes(dir);

      // Treat relative paths with respect to the current source dir.
      if (!cmSystemTools::FileIsFullPath(dir)) {
        dir = "/" + dir;
        dir = this->Makefile->GetCurrentSourceDirectory() + dir;
      }
      // The file location was cached.  Look for the correct file.
      std::string file;
      if (this->FindConfigFile(dir, pdt::Any, file)) {
        this->FileFound = std::move(file);
        fileFound = true;
      }
      def = this->Makefile->GetDefinition(this->Variable);
    }

    // Search for the config file if it is not already found.
    if (def.IsOff() || !fileFound) {
      fileFound = this->FindConfig();
    }

    // Sanity check.
    if (fileFound && this->FileFound.empty()) {
      this->Makefile->IssueMessage(
        MessageType::INTERNAL_ERROR,
        "fileFound is true but FileFound is empty!");
      fileFound = false;
    }
  }

  std::string const foundVar = cmStrCat(this->Name, "_FOUND");
  std::string const notFoundMessageVar =
    cmStrCat(this->Name, "_NOT_FOUND_MESSAGE");
  std::string notFoundMessage;

  // If the directory for the config file was found, try to read the file.
  bool result = true;
  bool found = false;
  bool configFileSetFOUNDFalse = false;

  if (fileFound) {
    if (this->Makefile->IsDefinitionSet(foundVar) &&
        !this->Makefile->IsOn(foundVar)) {
      // by removing Foo_FOUND here if it is FALSE, we don't really change
      // the situation for the Config file which is about to be included,
      // but we make it possible to detect later on whether the Config file
      // has set Foo_FOUND to FALSE itself:
      this->Makefile->RemoveDefinition(foundVar);
    }
    this->Makefile->RemoveDefinition(notFoundMessageVar);

    // Set the version variables before loading the config file.
    // It may override them.
    this->StoreVersionFound();

    // Parse the configuration file.
    if (this->CpsReader) {
      // The package has been found.
      found = true;
      result = this->ReadPackage();
    } else if (this->ReadListFile(this->FileFound, DoPolicyScope)) {
      // The package has been found.
      found = true;

      // Check whether the Config file has set Foo_FOUND to FALSE:
      if (this->Makefile->IsDefinitionSet(foundVar) &&
          !this->Makefile->IsOn(foundVar)) {
        // we get here if the Config file has set Foo_FOUND actively to FALSE
        found = false;
        configFileSetFOUNDFalse = true;
        notFoundMessage =
          this->Makefile->GetSafeDefinition(notFoundMessageVar);
      }
    } else {
      // The configuration file is invalid.
      result = false;
    }
  }

  if (this->UseFindModules && !found &&
      handlePackageModeType == HandlePackageModeType::Config &&
      this->Makefile->IsOn("CMAKE_FIND_PACKAGE_PREFER_CONFIG")) {
    // Config mode failed. Allow Module case.
    result = false;
  }

  // package not found
  if (result && !found) {
    // warn if package required or neither quiet nor in config mode
    if (this->Required ||
        !(this->Quiet ||
          (this->UseConfigFiles && !this->UseFindModules &&
           this->ConsideredConfigs.empty()))) {
      // The variable is not set.
      std::ostringstream e;
      std::ostringstream aw;
      if (configFileSetFOUNDFalse) {
        e << "Found package configuration file:\n"
             "  "
          << this->FileFound
          << "\n"
             "but it set "
          << foundVar << " to FALSE so package \"" << this->Name
          << "\" is considered to be NOT FOUND.";
        if (!notFoundMessage.empty()) {
          e << " Reason given by package: \n" << notFoundMessage << "\n";
        }
      }
      // If there are files in ConsideredConfigs, it means that FooConfig.cmake
      // have been found, but they didn't have appropriate versions.
      else if (!this->ConsideredConfigs.empty()) {
        auto duplicate_end = cmRemoveDuplicates(this->ConsideredConfigs);
        e << "Could not find a configuration file for package \"" << this->Name
          << "\" that "
          << (this->VersionExact ? "exactly matches" : "is compatible with")
          << " requested version "
          << (this->VersionRange.empty() ? "" : "range ") << '"'
          << this->VersionComplete
          << "\".\n"
             "The following configuration files were considered but not "
             "accepted:\n";

        for (ConfigFileInfo const& info :
             cmMakeRange(this->ConsideredConfigs.cbegin(), duplicate_end)) {
          e << "  " << info.filename << ", version: " << info.version << '\n';
        }
      } else {
        std::string requestedVersionString;
        if (!this->VersionComplete.empty()) {
          requestedVersionString =
            cmStrCat(" (requested version ", this->VersionComplete, ')');
        }

        if (this->UseConfigFiles) {
          if (this->UseFindModules) {
            e << "By not providing \"Find" << this->Name
              << ".cmake\" in "
                 "CMAKE_MODULE_PATH this project has asked CMake to find a "
                 "package configuration file provided by \""
              << this->Name
              << "\", "
                 "but CMake did not find one.\n";
          }

          if (this->Configs.size() == 1) {
            e << "Could not find a package configuration file named \""
              << this->Configs[0].Name << "\" provided by package \""
              << this->Name << "\"" << requestedVersionString << ".\n";
          } else {
            auto configs = cmMakeRange(this->Configs);
            auto configNames =
              configs.transform([](ConfigName const& cn) { return cn.Name; });
            e << "Could not find a package configuration file provided by \""
              << this->Name << "\"" << requestedVersionString
              << " with any of the following names:\n"
              << cmWrap("  "_s, configNames, ""_s, "\n"_s) << '\n';
          }

          e << "Add the installation prefix of \"" << this->Name
            << "\" to CMAKE_PREFIX_PATH or set \"" << this->Variable
            << "\" to a directory containing one of the above files. "
               "If \""
            << this->Name
            << "\" provides a separate development "
               "package or SDK, be sure it has been installed.";
        } else // if(!this->UseFindModules && !this->UseConfigFiles)
        {
          e << "No \"Find" << this->Name
            << ".cmake\" found in "
               "CMAKE_MODULE_PATH.";

          aw
            << "Find" << this->Name
            << ".cmake must either be part of this "
               "project itself, in this case adjust CMAKE_MODULE_PATH so that "
               "it points to the correct location inside its source tree.\n"
               "Or it must be installed by a package which has already been "
               "found via find_package().  In this case make sure that "
               "package has indeed been found and adjust CMAKE_MODULE_PATH to "
               "contain the location where that package has installed "
               "Find"
            << this->Name
            << ".cmake.  This must be a location "
               "provided by that package.  This error in general means that "
               "the buildsystem of this project is relying on a Find-module "
               "without ensuring that it is actually available.\n";
        }
      }

      this->Makefile->IssueMessage(this->Required ? MessageType::FATAL_ERROR
                                                  : MessageType::WARNING,
                                   e.str());
      if (this->Required) {
        cmSystemTools::SetFatalErrorOccurred();
      }

      if (!aw.str().empty()) {
        this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, aw.str());
      }
    }
    // output result if in config mode but not in quiet mode
    else if (!this->Quiet) {
      this->Makefile->DisplayStatus(cmStrCat("Could NOT find ", this->Name,
                                             " (missing: ", this->Name,
                                             "_DIR)"),
                                    -1);
    }
  }

  // Set a variable marking whether the package was found.
  this->Makefile->AddDefinition(foundVar, found ? "1" : "0");

  // Set a variable naming the configuration file that was found.
  std::string const fileVar = cmStrCat(this->Name, "_CONFIG");
  if (found) {
    this->Makefile->AddDefinition(fileVar, this->FileFound);
  } else {
    this->Makefile->RemoveDefinition(fileVar);
  }

  std::string const consideredConfigsVar =
    cmStrCat(this->Name, "_CONSIDERED_CONFIGS");
  std::string const consideredVersionsVar =
    cmStrCat(this->Name, "_CONSIDERED_VERSIONS");

  std::string consideredConfigFiles;
  std::string consideredVersions;

  const char* sep = "";
  for (ConfigFileInfo const& i : this->ConsideredConfigs) {
    consideredConfigFiles += sep;
    consideredVersions += sep;
    consideredConfigFiles += i.filename;
    consideredVersions += i.version;
    sep = ";";
  }

  this->Makefile->AddDefinition(consideredConfigsVar, consideredConfigFiles);

  this->Makefile->AddDefinition(consideredVersionsVar, consideredVersions);

  return result;
}

bool cmFindPackageCommand::FindConfig()
{
  // Compute the set of search prefixes.
  this->ComputePrefixes();

  // Look for the project's configuration file.
  bool found = false;
  if (this->DebugMode) {
    this->DebugBuffer = cmStrCat(this->DebugBuffer,
                                 "find_package considered the following "
                                 "locations for ",
                                 this->Name, "'s Config module:\n");
  }

  if (!found && this->UseCpsFiles) {
    found = this->FindEnvironmentConfig();
  }

  // Search for frameworks.
  if (!found && (this->SearchFrameworkFirst || this->SearchFrameworkOnly)) {
    found = this->FindFrameworkConfig();
  }

  // Search for apps.
  if (!found && (this->SearchAppBundleFirst || this->SearchAppBundleOnly)) {
    found = this->FindAppBundleConfig();
  }

  // Search prefixes.
  if (!found && !(this->SearchFrameworkOnly || this->SearchAppBundleOnly)) {
    found = this->FindPrefixedConfig();
  }

  // Search for frameworks.
  if (!found && this->SearchFrameworkLast) {
    found = this->FindFrameworkConfig();
  }

  // Search for apps.
  if (!found && this->SearchAppBundleLast) {
    found = this->FindAppBundleConfig();
  }

  if (this->DebugMode) {
    if (found) {
      this->DebugBuffer = cmStrCat(
        this->DebugBuffer, "The file was found at\n  ", this->FileFound, '\n');
    } else {
      this->DebugBuffer =
        cmStrCat(this->DebugBuffer, "The file was not found.\n");
    }
  }

  // Store the entry in the cache so it can be set by the user.
  std::string init;
  if (found) {
    init = cmSystemTools::GetFilenamePath(this->FileFound);
  } else {
    init = this->Variable + "-NOTFOUND";
  }
  // We force the value since we do not get here if it was already set.
  this->SetConfigDirCacheVariable(init);

  return found;
}

void cmFindPackageCommand::SetConfigDirCacheVariable(const std::string& value)
{
  std::string const help =
    cmStrCat("The directory containing a CMake configuration file for ",
             this->Name, '.');
  this->Makefile->AddCacheDefinition(this->Variable, value, help,
                                     cmStateEnums::PATH, true);
  if (this->Makefile->GetPolicyStatus(cmPolicies::CMP0126) ==
        cmPolicies::NEW &&
      this->Makefile->IsNormalDefinitionSet(this->Variable)) {
    this->Makefile->AddDefinition(this->Variable, value);
  }
}

bool cmFindPackageCommand::FindPrefixedConfig()
{
  std::vector<std::string> const& prefixes = this->SearchPaths;
  return std::any_of(
    prefixes.begin(), prefixes.end(),
    [this](std::string const& p) -> bool { return this->SearchPrefix(p); });
}

bool cmFindPackageCommand::FindFrameworkConfig()
{
  std::vector<std::string> const& prefixes = this->SearchPaths;
  return std::any_of(prefixes.begin(), prefixes.end(),
                     [this](std::string const& p) -> bool {
                       return this->SearchFrameworkPrefix(p);
                     });
}

bool cmFindPackageCommand::FindAppBundleConfig()
{
  std::vector<std::string> const& prefixes = this->SearchPaths;
  return std::any_of(prefixes.begin(), prefixes.end(),
                     [this](std::string const& p) -> bool {
                       return this->SearchAppBundlePrefix(p);
                     });
}

bool cmFindPackageCommand::FindEnvironmentConfig()
{
  std::vector<std::string> const& prefixes =
    cmSystemTools::GetEnvPathNormalized("CPS_PATH");
  return std::any_of(prefixes.begin(), prefixes.end(),
                     [this](std::string const& p) -> bool {
                       return this->SearchEnvironmentPrefix(p);
                     });
}

cmFindPackageCommand::AppendixMap cmFindPackageCommand::FindAppendices(
  std::string const& base) const
{
  AppendixMap appendices;

  // Find package appendices.
  cmsys::Glob glob;
  glob.RecurseOff();
  if (glob.FindFiles(cmStrCat(cmSystemTools::GetFilenamePath(base), "/"_s,
                              cmSystemTools::GetFilenameWithoutExtension(base),
                              "[-:]*.[Cc][Pp][Ss]"_s))) {
    // Check glob results for valid appendices.
    for (std::string const& extra : glob.GetFiles()) {
      // Exclude configuration-specific files for now; we look at them later
      // when we load their respective configuration-agnostic appendices.
      if (extra.find('@') != std::string::npos) {
        continue;
      }

      std::unique_ptr<cmPackageInfoReader> reader =
        cmPackageInfoReader::Read(extra, this->CpsReader.get());
      if (reader && reader->GetName() == this->Name) {
        appendices.emplace(extra, std::move(reader));
      }
    }
  }

  return appendices;
}

bool cmFindPackageCommand::ReadListFile(const std::string& f,
                                        const PolicyScopeRule psr)
{
  const bool noPolicyScope = !this->PolicyScope || psr == NoPolicyScope;

  using ITScope = cmMakefile::ImportedTargetScope;
  ITScope scope = this->GlobalScope ? ITScope::Global : ITScope::Local;
  cmMakefile::SetGlobalTargetImportScope globScope(this->Makefile, scope);

  if (this->Makefile->ReadDependentFile(f, noPolicyScope)) {
    return true;
  }
  std::string const e = cmStrCat("Error reading CMake code from \"", f, "\".");
  this->SetError(e);
  return false;
}

bool cmFindPackageCommand::ReadPackage()
{
  // Resolve any transitive dependencies.
  if (!FindPackageDependencies(this->FileFound, *this->CpsReader,
                               this->Required)) {
    return false;
  }

  cmMakefile::CallRAII scope{ this->Makefile, this->FileFound, this->Status };

  // Locate appendices.
  cmFindPackageCommand::AppendixMap appendices =
    this->FindAppendices(this->FileFound);

  auto iter = appendices.begin();
  while (iter != appendices.end()) {
    bool providesRequiredComponents = false; // TODO
    bool required = providesRequiredComponents && this->Required;
    if (!this->FindPackageDependencies(iter->first, *iter->second, required)) {
      if (providesRequiredComponents) {
        return false;
      }
      iter = appendices.erase(iter);
    } else {
      ++iter;
    }
  }

  // Import targets from root file.
  if (!this->ImportPackageTargets(this->FileFound, *this->CpsReader)) {
    return false;
  }

  // Import targets from appendices.
  for (auto const& appendix : appendices) {
    cmMakefile::CallRAII appendixScope{ this->Makefile, appendix.first,
                                        this->Status };
    if (!this->ImportPackageTargets(appendix.first, *appendix.second)) {
      return false;
    }
  }

  return true;
}

bool cmFindPackageCommand::FindPackageDependencies(
  std::string const& fileName, cmPackageInfoReader const& reader,
  bool required)
{
  // Get package requirements.
  for (cmPackageRequirement const& dep : reader.GetRequirements()) {
    cmExecutionStatus status{ *this->Makefile };
    cmMakefile::CallRAII scope{ this->Makefile, fileName, status };

    // For each requirement, set up a nested instance to find it.
    cmFindPackageCommand fp{ status };
    fp.InheritOptions(this);

    fp.Name = dep.Name;
    fp.Required = required;
    fp.UseFindModules = false;
    fp.UseCpsFiles = true;

    fp.Version = dep.Version;
    fp.VersionComplete = dep.Version;
    fp.VersionCount =
      parseVersion(fp.Version, fp.VersionMajor, fp.VersionMinor,
                   fp.VersionPatch, fp.VersionTweak);

    fp.Components = cmJoin(cmMakeRange(dep.Components), ";"_s);
    fp.RequiredComponents =
      std::set<std::string>{ dep.Components.begin(), dep.Components.end() };

    // TODO set hints

    // Try to find the requirement; fail if we can't.
    if (!fp.FindPackage() || fp.FileFound.empty()) {
      return false;
    }
  }

  // All requirements (if any) were found.
  return true;
}

bool cmFindPackageCommand::ImportPackageTargets(std::string const& fileName,
                                                cmPackageInfoReader& reader)
{
  // Import base file.
  if (!reader.ImportTargets(this->Makefile, this->Status)) {
    return false;
  }

  // Find supplemental configuration files.
  cmsys::Glob glob;
  glob.RecurseOff();
  if (glob.FindFiles(
        cmStrCat(cmSystemTools::GetFilenamePath(fileName), "/"_s,
                 cmSystemTools::GetFilenameWithoutExtension(fileName),
                 "@*.[Cc][Pp][Ss]"_s))) {

    // Try to read supplemental data from each file found.
    for (std::string const& extra : glob.GetFiles()) {
      std::unique_ptr<cmPackageInfoReader> configReader =
        cmPackageInfoReader::Read(extra, &reader);
      if (configReader && configReader->GetName() == this->Name) {
        if (!configReader->ImportTargetConfigurations(this->Makefile,
                                                      this->Status)) {
          return false;
        }
      }
    }
  }

  return true;
}

void cmFindPackageCommand::AppendToFoundProperty(const bool found)
{
  cmList foundContents;
  cmValue foundProp =
    this->Makefile->GetState()->GetGlobalProperty("PACKAGES_FOUND");
  if (!foundProp.IsEmpty()) {
    foundContents.assign(*foundProp);
    foundContents.remove_items({ this->Name });
  }

  cmList notFoundContents;
  cmValue notFoundProp =
    this->Makefile->GetState()->GetGlobalProperty("PACKAGES_NOT_FOUND");
  if (!notFoundProp.IsEmpty()) {
    notFoundContents.assign(*notFoundProp);
    notFoundContents.remove_items({ this->Name });
  }

  if (found) {
    foundContents.push_back(this->Name);
  } else {
    notFoundContents.push_back(this->Name);
  }

  this->Makefile->GetState()->SetGlobalProperty("PACKAGES_FOUND",
                                                foundContents.to_string());

  this->Makefile->GetState()->SetGlobalProperty("PACKAGES_NOT_FOUND",
                                                notFoundContents.to_string());
}

void cmFindPackageCommand::AppendSuccessInformation()
{
  {
    std::string const transitivePropName =
      cmStrCat("_CMAKE_", this->Name, "_TRANSITIVE_DEPENDENCY");
    this->Makefile->GetState()->SetGlobalProperty(transitivePropName, "False");
  }
  std::string const found = cmStrCat(this->Name, "_FOUND");
  std::string const upperFound = cmSystemTools::UpperCase(found);

  bool const upperResult = this->Makefile->IsOn(upperFound);
  bool const result = this->Makefile->IsOn(found);
  bool const packageFound = (result || upperResult);

  this->AppendToFoundProperty(packageFound);

  // Record whether the find was quiet or not, so this can be used
  // e.g. in FeatureSummary.cmake
  std::string const quietInfoPropName =
    cmStrCat("_CMAKE_", this->Name, "_QUIET");
  this->Makefile->GetState()->SetGlobalProperty(
    quietInfoPropName, this->Quiet ? "TRUE" : "FALSE");

  // set a global property to record the required version of this package
  std::string const versionInfoPropName =
    cmStrCat("_CMAKE_", this->Name, "_REQUIRED_VERSION");
  std::string versionInfo;
  if (!this->VersionRange.empty()) {
    versionInfo = this->VersionRange;
  } else if (!this->Version.empty()) {
    versionInfo =
      cmStrCat(this->VersionExact ? "==" : ">=", ' ', this->Version);
  }
  this->Makefile->GetState()->SetGlobalProperty(versionInfoPropName,
                                                versionInfo);
  if (this->Required) {
    std::string const requiredInfoPropName =
      cmStrCat("_CMAKE_", this->Name, "_TYPE");
    this->Makefile->GetState()->SetGlobalProperty(requiredInfoPropName,
                                                  "REQUIRED");
  }
}

void cmFindPackageCommand::PushFindPackageRootPathStack()
{
  // Allocate a PACKAGE_ROOT_PATH for the current find_package call.
  this->Makefile->FindPackageRootPathStack.emplace_back();
  std::vector<std::string>& rootPaths =
    this->Makefile->FindPackageRootPathStack.back();

  // Add root paths from <PackageName>_ROOT CMake and environment variables,
  // subject to CMP0074.
  std::string const rootVar = this->Name + "_ROOT";
  cmValue rootDef = this->Makefile->GetDefinition(rootVar);
  if (rootDef && rootDef.IsEmpty()) {
    rootDef = nullptr;
  }
  cm::optional<std::string> rootEnv = cmSystemTools::GetEnvVar(rootVar);
  if (rootEnv && rootEnv->empty()) {
    rootEnv = cm::nullopt;
  }
  switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0074)) {
    case cmPolicies::WARN:
      this->Makefile->MaybeWarnCMP0074(rootVar, rootDef, rootEnv);
      CM_FALLTHROUGH;
    case cmPolicies::OLD:
      // OLD behavior is to ignore the <PackageName>_ROOT variables.
      return;
    case cmPolicies::NEW: {
      // NEW behavior is to honor the <PackageName>_ROOT variables.
    } break;
  }

  // Add root paths from <PACKAGENAME>_ROOT CMake and environment variables,
  // if they are different than <PackageName>_ROOT, and subject to CMP0144.
  std::string const rootVAR = cmSystemTools::UpperCase(rootVar);
  cmValue rootDEF;
  cm::optional<std::string> rootENV;
  if (rootVAR != rootVar) {
    rootDEF = this->Makefile->GetDefinition(rootVAR);
    if (rootDEF && (rootDEF.IsEmpty() || rootDEF == rootDef)) {
      rootDEF = nullptr;
    }
    rootENV = cmSystemTools::GetEnvVar(rootVAR);
    if (rootENV && (rootENV->empty() || rootENV == rootEnv)) {
      rootENV = cm::nullopt;
    }
  }

  switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0144)) {
    case cmPolicies::WARN:
      this->Makefile->MaybeWarnCMP0144(rootVAR, rootDEF, rootENV);
      CM_FALLTHROUGH;
    case cmPolicies::OLD:
      // OLD behavior is to ignore the <PACKAGENAME>_ROOT variables.
      rootDEF = nullptr;
      rootENV = cm::nullopt;
      break;
    case cmPolicies::NEW: {
      // NEW behavior is to honor the <PACKAGENAME>_ROOT variables.
    } break;
  }

  if (rootDef) {
    cmExpandList(*rootDef, rootPaths);
  }
  if (rootDEF) {
    cmExpandList(*rootDEF, rootPaths);
  }
  if (rootEnv) {
    std::vector<std::string> p =
      cmSystemTools::SplitEnvPathNormalized(*rootEnv);
    std::move(p.begin(), p.end(), std::back_inserter(rootPaths));
  }
  if (rootENV) {
    std::vector<std::string> p =
      cmSystemTools::SplitEnvPathNormalized(*rootENV);
    std::move(p.begin(), p.end(), std::back_inserter(rootPaths));
  }
}

void cmFindPackageCommand::PopFindPackageRootPathStack()
{
  this->Makefile->FindPackageRootPathStack.pop_back();
}

void cmFindPackageCommand::ComputePrefixes()
{
  this->FillPrefixesPackageRedirect();

  if (!this->NoDefaultPath) {
    if (!this->NoPackageRootPath) {
      this->FillPrefixesPackageRoot();
    }
    if (!this->NoCMakePath) {
      this->FillPrefixesCMakeVariable();
    }
    if (!this->NoCMakeEnvironmentPath) {
      this->FillPrefixesCMakeEnvironment();
    }
  }

  this->FillPrefixesUserHints();

  if (!this->NoDefaultPath) {
    if (!this->NoSystemEnvironmentPath) {
      this->FillPrefixesSystemEnvironment();
    }
    if (!this->NoUserRegistry) {
      this->FillPrefixesUserRegistry();
    }
    if (!this->NoCMakeSystemPath) {
      this->FillPrefixesCMakeSystemVariable();
    }
    if (!this->NoSystemRegistry) {
      this->FillPrefixesSystemRegistry();
    }
  }
  this->FillPrefixesUserGuess();

  this->ComputeFinalPaths(IgnorePaths::No, &this->DebugBuffer);
}

void cmFindPackageCommand::FillPrefixesPackageRedirect()
{
  cmSearchPath& paths = this->LabeledPaths[PathLabel::PackageRedirect];

  const auto redirectDir =
    this->Makefile->GetDefinition("CMAKE_FIND_PACKAGE_REDIRECTS_DIR");
  if (redirectDir && !redirectDir->empty()) {
    paths.AddPath(*redirectDir);
  }
  if (this->DebugMode) {
    std::string debugBuffer =
      "The internally managed CMAKE_FIND_PACKAGE_REDIRECTS_DIR.\n";
    collectPathsForDebug(debugBuffer, paths);
    this->DebugBuffer = cmStrCat(this->DebugBuffer, debugBuffer);
  }
}

void cmFindPackageCommand::FillPrefixesPackageRoot()
{
  cmSearchPath& paths = this->LabeledPaths[PathLabel::PackageRoot];

  // Add the PACKAGE_ROOT_PATH from each enclosing find_package call.
  for (auto pkgPaths = this->Makefile->FindPackageRootPathStack.rbegin();
       pkgPaths != this->Makefile->FindPackageRootPathStack.rend();
       ++pkgPaths) {
    for (std::string const& path : *pkgPaths) {
      paths.AddPath(path);
    }
  }
  if (this->DebugMode) {
    std::string debugBuffer = "<PackageName>_ROOT CMake variable "
                              "[CMAKE_FIND_USE_PACKAGE_ROOT_PATH].\n";
    collectPathsForDebug(debugBuffer, paths);
    this->DebugBuffer = cmStrCat(this->DebugBuffer, debugBuffer);
  }
}

void cmFindPackageCommand::FillPrefixesCMakeEnvironment()
{
  cmSearchPath& paths = this->LabeledPaths[PathLabel::CMakeEnvironment];
  std::string debugBuffer;
  std::size_t debugOffset = 0;

  // Check the environment variable with the same name as the cache
  // entry.
  paths.AddEnvPath(this->Variable);
  if (this->DebugMode) {
    debugBuffer = cmStrCat("Env variable ", this->Variable,
                           " [CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH].\n");
    debugOffset = collectPathsForDebug(debugBuffer, paths);
  }

  // And now the general CMake environment variables
  paths.AddEnvPath("CMAKE_PREFIX_PATH");
  if (this->DebugMode) {
    debugBuffer = cmStrCat(debugBuffer,
                           "CMAKE_PREFIX_PATH env variable "
                           "[CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH].\n");
    debugOffset = collectPathsForDebug(debugBuffer, paths, debugOffset);
  }

  paths.AddEnvPath("CMAKE_FRAMEWORK_PATH");
  paths.AddEnvPath("CMAKE_APPBUNDLE_PATH");
  if (this->DebugMode) {
    debugBuffer =
      cmStrCat(debugBuffer,
               "CMAKE_FRAMEWORK_PATH and CMAKE_APPBUNDLE_PATH env "
               "variables [CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH].\n");
    collectPathsForDebug(debugBuffer, paths, debugOffset);
    this->DebugBuffer = cmStrCat(this->DebugBuffer, debugBuffer);
  }
}

void cmFindPackageCommand::FillPrefixesCMakeVariable()
{
  cmSearchPath& paths = this->LabeledPaths[PathLabel::CMake];
  std::string debugBuffer;
  std::size_t debugOffset = 0;

  paths.AddCMakePath("CMAKE_PREFIX_PATH");
  if (this->DebugMode) {
    debugBuffer = "CMAKE_PREFIX_PATH variable [CMAKE_FIND_USE_CMAKE_PATH].\n";
    debugOffset = collectPathsForDebug(debugBuffer, paths);
  }

  paths.AddCMakePath("CMAKE_FRAMEWORK_PATH");
  paths.AddCMakePath("CMAKE_APPBUNDLE_PATH");
  if (this->DebugMode) {
    debugBuffer =
      cmStrCat(debugBuffer,
               "CMAKE_FRAMEWORK_PATH and CMAKE_APPBUNDLE_PATH variables "
               "[CMAKE_FIND_USE_CMAKE_PATH].\n");
    collectPathsForDebug(debugBuffer, paths, debugOffset);
    this->DebugBuffer = cmStrCat(this->DebugBuffer, debugBuffer);
  }
}

void cmFindPackageCommand::FillPrefixesSystemEnvironment()
{
  cmSearchPath& paths = this->LabeledPaths[PathLabel::SystemEnvironment];

  // Use the system search path to generate prefixes.
  // Relative paths are interpreted with respect to the current
  // working directory.
  std::vector<std::string> envPATH =
    cmSystemTools::GetEnvPathNormalized("PATH");
  for (std::string const& i : envPATH) {
    // If the path is a PREFIX/bin case then add its parent instead.
    if ((cmHasLiteralSuffix(i, "/bin")) || (cmHasLiteralSuffix(i, "/sbin"))) {
      paths.AddPath(cmSystemTools::GetFilenamePath(i));
    } else {
      paths.AddPath(i);
    }
  }
  if (this->DebugMode) {
    std::string debugBuffer = "Standard system environment variables "
                              "[CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH].\n";
    collectPathsForDebug(debugBuffer, paths);
    this->DebugBuffer = cmStrCat(this->DebugBuffer, debugBuffer);
  }
}

void cmFindPackageCommand::FillPrefixesUserRegistry()
{
#if defined(_WIN32) && !defined(__CYGWIN__)
  this->LoadPackageRegistryWinUser();
#elif defined(__HAIKU__)
  char dir[B_PATH_NAME_LENGTH];
  if (find_directory(B_USER_SETTINGS_DIRECTORY, -1, false, dir, sizeof(dir)) ==
      B_OK) {
    std::string fname = cmStrCat(dir, "/cmake/packages/", Name);
    this->LoadPackageRegistryDir(fname,
                                 this->LabeledPaths[PathLabel::UserRegistry]);
  }
#else
  std::string dir;
  if (cmSystemTools::GetEnv("HOME", dir)) {
    dir += "/.cmake/packages/";
    dir += this->Name;
    this->LoadPackageRegistryDir(dir,
                                 this->LabeledPaths[PathLabel::UserRegistry]);
  }
#endif
  if (this->DebugMode) {
    std::string debugBuffer =
      "CMake User Package Registry [CMAKE_FIND_USE_PACKAGE_REGISTRY].\n";
    collectPathsForDebug(debugBuffer,
                         this->LabeledPaths[PathLabel::UserRegistry]);
    this->DebugBuffer = cmStrCat(this->DebugBuffer, debugBuffer);
  }
}

void cmFindPackageCommand::FillPrefixesSystemRegistry()
{
  if (this->NoSystemRegistry || this->NoDefaultPath) {
    return;
  }

#if defined(_WIN32) && !defined(__CYGWIN__)
  this->LoadPackageRegistryWinSystem();
#endif

  if (this->DebugMode) {
    std::string debugBuffer =
      "CMake System Package Registry "
      "[CMAKE_FIND_PACKAGE_NO_SYSTEM_PACKAGE_REGISTRY].\n";
    collectPathsForDebug(debugBuffer,
                         this->LabeledPaths[PathLabel::SystemRegistry]);
    this->DebugBuffer = cmStrCat(this->DebugBuffer, debugBuffer);
  }
}

#if defined(_WIN32) && !defined(__CYGWIN__)
void cmFindPackageCommand::LoadPackageRegistryWinUser()
{
  // HKEY_CURRENT_USER\\Software shares 32-bit and 64-bit views.
  this->LoadPackageRegistryWin(true, 0,
                               this->LabeledPaths[PathLabel::UserRegistry]);
}

void cmFindPackageCommand::LoadPackageRegistryWinSystem()
{
  cmSearchPath& paths = this->LabeledPaths[PathLabel::SystemRegistry];

  // HKEY_LOCAL_MACHINE\\SOFTWARE has separate 32-bit and 64-bit views.
  // Prefer the target platform view first.
  if (this->Makefile->PlatformIs64Bit()) {
    this->LoadPackageRegistryWin(false, KEY_WOW64_64KEY, paths);
    this->LoadPackageRegistryWin(false, KEY_WOW64_32KEY, paths);
  } else {
    this->LoadPackageRegistryWin(false, KEY_WOW64_32KEY, paths);
    this->LoadPackageRegistryWin(false, KEY_WOW64_64KEY, paths);
  }
}

void cmFindPackageCommand::LoadPackageRegistryWin(const bool user,
                                                  const unsigned int view,
                                                  cmSearchPath& outPaths)
{
  std::wstring key = L"Software\\Kitware\\CMake\\Packages\\";
  key += cmsys::Encoding::ToWide(this->Name);
  std::set<std::wstring> bad;
  HKEY hKey;
  if (RegOpenKeyExW(user ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE, key.c_str(),
                    0, KEY_QUERY_VALUE | view, &hKey) == ERROR_SUCCESS) {
    DWORD valueType = REG_NONE;
    wchar_t name[16383]; // RegEnumValue docs limit name to 32767 _bytes_
    std::vector<wchar_t> data(512);
    bool done = false;
    DWORD index = 0;
    while (!done) {
      DWORD nameSize = static_cast<DWORD>(sizeof(name));
      DWORD dataSize = static_cast<DWORD>(data.size() * sizeof(data[0]));
      switch (RegEnumValueW(hKey, index, name, &nameSize, 0, &valueType,
                            (BYTE*)&data[0], &dataSize)) {
        case ERROR_SUCCESS:
          ++index;
          if (valueType == REG_SZ) {
            data[dataSize] = 0;
            if (!this->CheckPackageRegistryEntry(
                  cmsys::Encoding::ToNarrow(&data[0]), outPaths)) {
              // The entry is invalid.
              bad.insert(name);
            }
          }
          break;
        case ERROR_MORE_DATA:
          data.resize((dataSize + sizeof(data[0]) - 1) / sizeof(data[0]));
          break;
        case ERROR_NO_MORE_ITEMS:
        default:
          done = true;
          break;
      }
    }
    RegCloseKey(hKey);
  }

  // Remove bad values if possible.
  if (user && !bad.empty() &&
      RegOpenKeyExW(HKEY_CURRENT_USER, key.c_str(), 0, KEY_SET_VALUE | view,
                    &hKey) == ERROR_SUCCESS) {
    for (std::wstring const& v : bad) {
      RegDeleteValueW(hKey, v.c_str());
    }
    RegCloseKey(hKey);
  }
}

#else
void cmFindPackageCommand::LoadPackageRegistryDir(std::string const& dir,
                                                  cmSearchPath& outPaths)
{
  cmsys::Directory files;
  if (!files.Load(dir)) {
    return;
  }

  std::string fname;
  for (unsigned long i = 0; i < files.GetNumberOfFiles(); ++i) {
    fname = cmStrCat(dir, '/', files.GetFile(i));

    if (!cmSystemTools::FileIsDirectory(fname)) {
      // Hold this file hostage until it behaves.
      cmFindPackageCommandHoldFile holdFile(fname.c_str());

      // Load the file.
      cmsys::ifstream fin(fname.c_str(), std::ios::in | std::ios::binary);
      std::string fentry;
      if (fin && cmSystemTools::GetLineFromStream(fin, fentry) &&
          this->CheckPackageRegistryEntry(fentry, outPaths)) {
        // The file references an existing package, so release it.
        holdFile.Release();
      }
    }
  }

  // TODO: Wipe out the directory if it is empty.
}
#endif

bool cmFindPackageCommand::CheckPackageRegistryEntry(const std::string& fname,
                                                     cmSearchPath& outPaths)
{
  // Parse the content of one package registry entry.
  if (cmSystemTools::FileIsFullPath(fname)) {
    // The first line in the stream is the full path to a file or
    // directory containing the package.
    if (cmSystemTools::FileExists(fname)) {
      // The path exists.  Look for the package here.
      if (!cmSystemTools::FileIsDirectory(fname)) {
        outPaths.AddPath(cmSystemTools::GetFilenamePath(fname));
      } else {
        outPaths.AddPath(fname);
      }
      return true;
    }
    // The path does not exist.  Assume the stream content is
    // associated with an old package that no longer exists, and
    // delete it to keep the package registry clean.
    return false;
  }
  // The first line in the stream is not the full path to a file or
  // directory.  Assume the stream content was created by a future
  // version of CMake that uses a different format, and leave it.
  return true;
}

void cmFindPackageCommand::FillPrefixesCMakeSystemVariable()
{
  cmSearchPath& paths = this->LabeledPaths[PathLabel::CMakeSystem];

  const bool install_prefix_in_list =
    !this->Makefile->IsOn("CMAKE_FIND_NO_INSTALL_PREFIX");
  const bool remove_install_prefix = this->NoCMakeInstallPath;
  const bool add_install_prefix = !this->NoCMakeInstallPath &&
    this->Makefile->IsDefinitionSet("CMAKE_FIND_USE_INSTALL_PREFIX");

  // We have 3 possible states for `CMAKE_SYSTEM_PREFIX_PATH` and
  // `CMAKE_INSTALL_PREFIX`.
  // Either we need to remove `CMAKE_INSTALL_PREFIX`, add
  // `CMAKE_INSTALL_PREFIX`, or do nothing.
  //
  // When we need to remove `CMAKE_INSTALL_PREFIX` we remove the Nth occurrence
  // of `CMAKE_INSTALL_PREFIX` from `CMAKE_SYSTEM_PREFIX_PATH`, where `N` is
  // computed by `CMakeSystemSpecificInformation.cmake` while constructing
  // `CMAKE_SYSTEM_PREFIX_PATH`. This ensures that if projects / toolchains
  // have removed `CMAKE_INSTALL_PREFIX` from the list, we don't remove
  // some other entry by mistake
  long install_prefix_count = -1;
  std::string install_path_to_remove;
  if (cmValue to_skip = this->Makefile->GetDefinition(
        "_CMAKE_SYSTEM_PREFIX_PATH_INSTALL_PREFIX_COUNT")) {
    cmStrToLong(*to_skip, &install_prefix_count);
  }
  if (cmValue install_value = this->Makefile->GetDefinition(
        "_CMAKE_SYSTEM_PREFIX_PATH_INSTALL_PREFIX_VALUE")) {
    install_path_to_remove = *install_value;
  }

  if (remove_install_prefix && install_prefix_in_list &&
      install_prefix_count > 0 && !install_path_to_remove.empty()) {

    cmValue prefix_paths =
      this->Makefile->GetDefinition("CMAKE_SYSTEM_PREFIX_PATH");
    // remove entry from CMAKE_SYSTEM_PREFIX_PATH
    cmList expanded{ *prefix_paths };
    long count = 0;
    for (const auto& path : expanded) {
      bool const to_add =
        !(path == install_path_to_remove && ++count == install_prefix_count);
      if (to_add) {
        paths.AddPath(path);
      }
    }
  } else if (add_install_prefix && !install_prefix_in_list) {
    paths.AddCMakePath("CMAKE_INSTALL_PREFIX");
    paths.AddCMakePath("CMAKE_SYSTEM_PREFIX_PATH");
  } else {
    // Otherwise the current setup of `CMAKE_SYSTEM_PREFIX_PATH` is correct
    paths.AddCMakePath("CMAKE_SYSTEM_PREFIX_PATH");
  }

  paths.AddCMakePath("CMAKE_SYSTEM_FRAMEWORK_PATH");
  paths.AddCMakePath("CMAKE_SYSTEM_APPBUNDLE_PATH");

  if (this->DebugMode) {
    std::string debugBuffer = "CMake variables defined in the Platform file "
                              "[CMAKE_FIND_USE_CMAKE_SYSTEM_PATH].\n";
    collectPathsForDebug(debugBuffer, paths);
    this->DebugBuffer = cmStrCat(this->DebugBuffer, debugBuffer);
  }
}

void cmFindPackageCommand::FillPrefixesUserGuess()
{
  cmSearchPath& paths = this->LabeledPaths[PathLabel::Guess];

  for (std::string const& p : this->UserGuessArgs) {
    paths.AddUserPath(p);
  }
  if (this->DebugMode) {
    std::string debugBuffer =
      "Paths specified by the find_package PATHS option.\n";
    collectPathsForDebug(debugBuffer, paths);
    this->DebugBuffer = cmStrCat(this->DebugBuffer, debugBuffer);
  }
}

void cmFindPackageCommand::FillPrefixesUserHints()
{
  cmSearchPath& paths = this->LabeledPaths[PathLabel::Hints];

  for (std::string const& p : this->UserHintsArgs) {
    paths.AddUserPath(p);
  }
  if (this->DebugMode) {
    std::string debugBuffer =
      "Paths specified by the find_package HINTS option.\n";
    collectPathsForDebug(debugBuffer, paths);
    this->DebugBuffer = cmStrCat(this->DebugBuffer, debugBuffer);
  }
}

bool cmFindPackageCommand::SearchDirectory(std::string const& dir,
                                           PackageDescriptionType type)
{
  assert(!dir.empty() && dir.back() == '/');

  // Check each path suffix on this directory.
  for (std::string const& s : this->SearchPathSuffixes) {
    std::string d = dir;
    if (!s.empty()) {
      d += s;
      d += '/';
    }
    if (this->CheckDirectory(d, type)) {
      return true;
    }
  }
  return false;
}

bool cmFindPackageCommand::CheckDirectory(std::string const& dir,
                                          PackageDescriptionType type)
{
  assert(!dir.empty() && dir.back() == '/');

  std::string const d = dir.substr(0, dir.size() - 1);
  if (cm::contains(this->IgnoredPaths, d)) {
    return false;
  }

  // Look for the file in this directory.
  std::string file;
  if (this->FindConfigFile(d, type, file)) {
    this->FileFound = std::move(file);
    return true;
  }
  return false;
}

bool cmFindPackageCommand::FindConfigFile(std::string const& dir,
                                          PackageDescriptionType type,
                                          std::string& file)
{
  for (auto const& config : this->Configs) {
    if (type != pdt::Any && config.Type != type) {
      continue;
    }
    file = cmStrCat(dir, '/', config.Name);
    if (this->DebugMode) {
      this->DebugBuffer = cmStrCat(this->DebugBuffer, "  ", file, '\n');
    }
    if (cmSystemTools::FileExists(file, true) && this->CheckVersion(file)) {
      // Allow resolving symlinks when the config file is found through a link
      if (this->UseRealPath) {
        file = cmSystemTools::GetRealPath(file);
      } else {
        file = cmSystemTools::ToNormalizedPathOnDisk(file);
      }
      return true;
    }
  }
  return false;
}

bool cmFindPackageCommand::CheckVersion(std::string const& config_file)
{
  bool result = false; // by default, assume the version is not ok.
  bool haveResult = false;
  std::string version = "unknown";

  // Get the file extension.
  std::string::size_type pos = config_file.rfind('.');
  std::string ext = cmSystemTools::LowerCase(config_file.substr(pos));

  if (ext == ".cps"_s) {
    std::unique_ptr<cmPackageInfoReader> reader =
      cmPackageInfoReader::Read(config_file);
    if (reader && reader->GetName() == this->Name) {
      cm::optional<std::string> cpsVersion = reader->GetVersion();
      if (cpsVersion) {
        // TODO: Implement version check for CPS
        this->VersionFound = (version = std::move(*cpsVersion));

        std::vector<unsigned> const& versionParts = reader->ParseVersion();
        this->VersionFoundCount = static_cast<unsigned>(versionParts.size());
        switch (this->VersionFoundCount) {
          case 4:
            this->VersionFoundTweak = versionParts[3];
            CM_FALLTHROUGH;
          case 3:
            this->VersionFoundPatch = versionParts[2];
            CM_FALLTHROUGH;
          case 2:
            this->VersionFoundMinor = versionParts[1];
            CM_FALLTHROUGH;
          case 1:
            this->VersionFoundMajor = versionParts[0];
            CM_FALLTHROUGH;
          default:
            break;
        }
      }
      this->CpsReader = std::move(reader);
      result = true;
    }
  } else {
    // Get the filename without the .cmake extension.
    std::string version_file_base = config_file.substr(0, pos);

    // Look for foo-config-version.cmake
    std::string version_file = cmStrCat(version_file_base, "-version.cmake");
    if (!haveResult && cmSystemTools::FileExists(version_file, true)) {
      result = this->CheckVersionFile(version_file, version);
      haveResult = true;
    }

    // Look for fooConfigVersion.cmake
    version_file = cmStrCat(version_file_base, "Version.cmake");
    if (!haveResult && cmSystemTools::FileExists(version_file, true)) {
      result = this->CheckVersionFile(version_file, version);
      haveResult = true;
    }

    // If no version was requested a versionless package is acceptable.
    if (!haveResult && this->Version.empty()) {
      result = true;
    }
  }

  ConfigFileInfo configFileInfo;
  configFileInfo.filename = config_file;
  configFileInfo.version = version;
  this->ConsideredConfigs.push_back(std::move(configFileInfo));

  return result;
}

bool cmFindPackageCommand::CheckVersionFile(std::string const& version_file,
                                            std::string& result_version)
{
  // The version file will be loaded in an isolated scope.
  cmMakefile::ScopePushPop const varScope(this->Makefile);
  cmMakefile::PolicyPushPop const polScope(this->Makefile);
  static_cast<void>(varScope);
  static_cast<void>(polScope);

  // Clear the output variables.
  this->Makefile->RemoveDefinition("PACKAGE_VERSION");
  this->Makefile->RemoveDefinition("PACKAGE_VERSION_UNSUITABLE");
  this->Makefile->RemoveDefinition("PACKAGE_VERSION_COMPATIBLE");
  this->Makefile->RemoveDefinition("PACKAGE_VERSION_EXACT");

  // Set the input variables.
  this->Makefile->AddDefinition("PACKAGE_FIND_NAME", this->Name);
  this->Makefile->AddDefinition("PACKAGE_FIND_VERSION_COMPLETE",
                                this->VersionComplete);

  auto addDefinition = [this](const std::string& variable,
                              cm::string_view value) {
    this->Makefile->AddDefinition(variable, value);
  };
  this->SetVersionVariables(addDefinition, "PACKAGE_FIND_VERSION",
                            this->Version, this->VersionCount,
                            this->VersionMajor, this->VersionMinor,
                            this->VersionPatch, this->VersionTweak);
  if (!this->VersionRange.empty()) {
    this->SetVersionVariables(addDefinition, "PACKAGE_FIND_VERSION_MIN",
                              this->Version, this->VersionCount,
                              this->VersionMajor, this->VersionMinor,
                              this->VersionPatch, this->VersionTweak);
    this->SetVersionVariables(addDefinition, "PACKAGE_FIND_VERSION_MAX",
                              this->VersionMax, this->VersionMaxCount,
                              this->VersionMaxMajor, this->VersionMaxMinor,
                              this->VersionMaxPatch, this->VersionMaxTweak);

    this->Makefile->AddDefinition("PACKAGE_FIND_VERSION_RANGE",
                                  this->VersionComplete);
    this->Makefile->AddDefinition("PACKAGE_FIND_VERSION_RANGE_MIN",
                                  this->VersionRangeMin);
    this->Makefile->AddDefinition("PACKAGE_FIND_VERSION_RANGE_MAX",
                                  this->VersionRangeMax);
  }

  // Load the version check file.
  // Pass NoPolicyScope because we do our own policy push/pop.
  bool suitable = false;
  if (this->ReadListFile(version_file, NoPolicyScope)) {
    // Check the output variables.
    bool okay = this->Makefile->IsOn("PACKAGE_VERSION_EXACT");
    bool const unsuitable = this->Makefile->IsOn("PACKAGE_VERSION_UNSUITABLE");
    if (!okay && !this->VersionExact) {
      okay = this->Makefile->IsOn("PACKAGE_VERSION_COMPATIBLE");
    }

    // The package is suitable if the version is okay and not
    // explicitly unsuitable.
    suitable = !unsuitable && (okay || this->Version.empty());
    if (suitable) {
      // Get the version found.
      this->VersionFound =
        this->Makefile->GetSafeDefinition("PACKAGE_VERSION");

      // Try to parse the version number and store the results that were
      // successfully parsed.
      unsigned int parsed_major;
      unsigned int parsed_minor;
      unsigned int parsed_patch;
      unsigned int parsed_tweak;
      this->VersionFoundCount =
        parseVersion(this->VersionFound, parsed_major, parsed_minor,
                     parsed_patch, parsed_tweak);
      switch (this->VersionFoundCount) {
        case 4:
          this->VersionFoundTweak = parsed_tweak;
          CM_FALLTHROUGH;
        case 3:
          this->VersionFoundPatch = parsed_patch;
          CM_FALLTHROUGH;
        case 2:
          this->VersionFoundMinor = parsed_minor;
          CM_FALLTHROUGH;
        case 1:
          this->VersionFoundMajor = parsed_major;
          CM_FALLTHROUGH;
        default:
          break;
      }
    }
  }

  result_version = this->Makefile->GetSafeDefinition("PACKAGE_VERSION");
  if (result_version.empty()) {
    result_version = "unknown";
  }

  // Succeed if the version is suitable.
  return suitable;
}

void cmFindPackageCommand::StoreVersionFound()
{
  // Store the whole version string.
  std::string const ver = cmStrCat(this->Name, "_VERSION");
  auto addDefinition = [this](const std::string& variable,
                              cm::string_view value) {
    this->Makefile->AddDefinition(variable, value);
  };

  this->SetVersionVariables(addDefinition, ver, this->VersionFound,
                            this->VersionFoundCount, this->VersionFoundMajor,
                            this->VersionFoundMinor, this->VersionFoundPatch,
                            this->VersionFoundTweak);

  if (this->VersionFound.empty()) {
    this->Makefile->RemoveDefinition(ver);
  }
}

bool cmFindPackageCommand::SearchPrefix(std::string const& prefix)
{
  assert(!prefix.empty() && prefix.back() == '/');

  // Skip this if the prefix does not exist.
  if (!cmSystemTools::FileIsDirectory(prefix)) {
    return false;
  }

  // Skip this if it's in ignored paths.
  std::string prefixWithoutSlash = prefix;
  if (prefixWithoutSlash != "/" && prefixWithoutSlash.back() == '/') {
    prefixWithoutSlash.erase(prefixWithoutSlash.length() - 1);
  }
  if (this->IgnoredPaths.count(prefixWithoutSlash) ||
      this->IgnoredPrefixPaths.count(prefixWithoutSlash)) {
    return false;
  }

  auto searchFn = [this](const std::string& fullPath,
                         PackageDescriptionType type) -> bool {
    return this->SearchDirectory(fullPath, type);
  };

  auto iCpsGen = cmCaseInsensitiveDirectoryListGenerator{ "cps"_s };
  auto iCMakeGen = cmCaseInsensitiveDirectoryListGenerator{ "cmake"_s };
  auto anyDirGen =
    cmAnyDirectoryListGenerator{ this->SortOrder, this->SortDirection };
  auto cpsPkgDirGen =
    cmProjectDirectoryListGenerator{ &this->Names, this->SortOrder,
                                     this->SortDirection, true };
  auto cmakePkgDirGen =
    cmProjectDirectoryListGenerator{ &this->Names, this->SortOrder,
                                     this->SortDirection, false };

  // PREFIX/(Foo|foo|FOO)/(cps|CPS)/
  if (TryGeneratedPaths(searchFn, pdt::Cps, prefix, cpsPkgDirGen, iCpsGen)) {
    return true;
  }

  // PREFIX/(Foo|foo|FOO)/*/(cps|CPS)/
  if (TryGeneratedPaths(searchFn, pdt::Cps, prefix, cpsPkgDirGen, iCpsGen,
                        anyDirGen)) {
    return true;
  }

  // PREFIX/(cps|CPS)/(Foo|foo|FOO)/
  if (TryGeneratedPaths(searchFn, pdt::Cps, prefix, iCpsGen, cpsPkgDirGen)) {
    return true;
  }

  // PREFIX/(cps|CPS)/(Foo|foo|FOO)/*/
  if (TryGeneratedPaths(searchFn, pdt::Cps, prefix, iCpsGen, cpsPkgDirGen,
                        anyDirGen)) {
    return true;
  }

  // PREFIX/(cps|CPS)/ (useful on windows or in build trees)
  if (TryGeneratedPaths(searchFn, pdt::Cps, prefix, iCpsGen)) {
    return true;
  }

  // PREFIX/ (useful on windows or in build trees)
  if (this->SearchDirectory(prefix, pdt::CMake)) {
    return true;
  }

  // PREFIX/(cmake|CMake)/ (useful on windows or in build trees)
  if (TryGeneratedPaths(searchFn, pdt::CMake, prefix, iCMakeGen)) {
    return true;
  }

  // PREFIX/(Foo|foo|FOO).*/
  if (TryGeneratedPaths(searchFn, pdt::CMake, prefix, cmakePkgDirGen)) {
    return true;
  }

  // PREFIX/(Foo|foo|FOO).*/(cmake|CMake)/
  if (TryGeneratedPaths(searchFn, pdt::CMake, prefix, cmakePkgDirGen,
                        iCMakeGen)) {
    return true;
  }

  auto secondPkgDirGen =
    cmProjectDirectoryListGenerator{ &this->Names, this->SortOrder,
                                     this->SortDirection, false };

  // PREFIX/(Foo|foo|FOO).*/(cmake|CMake)/(Foo|foo|FOO).*/
  if (TryGeneratedPaths(searchFn, pdt::CMake, prefix, cmakePkgDirGen,
                        iCMakeGen, secondPkgDirGen)) {
    return true;
  }

  // Construct list of common install locations (lib and share).
  std::vector<cm::string_view> common;
  std::string libArch;
  if (!this->LibraryArchitecture.empty()) {
    libArch = "lib/" + this->LibraryArchitecture;
    common.emplace_back(libArch);
  }
  if (this->UseLib32Paths) {
    common.emplace_back("lib32"_s);
  }
  if (this->UseLib64Paths) {
    common.emplace_back("lib64"_s);
  }
  if (this->UseLibx32Paths) {
    common.emplace_back("libx32"_s);
  }
  common.emplace_back("lib"_s);
  common.emplace_back("share"_s);

  auto commonGen = cmEnumPathSegmentsGenerator{ common };
  auto cmakeGen = cmAppendPathSegmentGenerator{ "cmake"_s };
  auto cpsGen = cmAppendPathSegmentGenerator{ "cps"_s };

  // PREFIX/(lib/ARCH|lib*|share)/cps/(Foo|foo|FOO)/
  if (TryGeneratedPaths(searchFn, pdt::Cps, prefix, commonGen, cpsGen,
                        cpsPkgDirGen)) {
    return true;
  }

  // PREFIX/(lib/ARCH|lib*|share)/cps/(Foo|foo|FOO)/*/
  if (TryGeneratedPaths(searchFn, pdt::Cps, prefix, commonGen, cpsGen,
                        cpsPkgDirGen, anyDirGen)) {
    return true;
  }

  // PREFIX/(lib/ARCH|lib*|share)/cps/
  if (TryGeneratedPaths(searchFn, pdt::Cps, prefix, commonGen, cpsGen)) {
    return true;
  }

  // PREFIX/(lib/ARCH|lib*|share)/cmake/(Foo|foo|FOO).*/
  if (TryGeneratedPaths(searchFn, pdt::CMake, prefix, commonGen, cmakeGen,
                        cmakePkgDirGen)) {
    return true;
  }

  // PREFIX/(lib/ARCH|lib*|share)/(Foo|foo|FOO).*/
  if (TryGeneratedPaths(searchFn, pdt::CMake, prefix, commonGen,
                        cmakePkgDirGen)) {
    return true;
  }

  // PREFIX/(lib/ARCH|lib*|share)/(Foo|foo|FOO).*/(cmake|CMake)/
  if (TryGeneratedPaths(searchFn, pdt::CMake, prefix, commonGen,
                        cmakePkgDirGen, iCMakeGen)) {
    return true;
  }

  // PREFIX/(Foo|foo|FOO).*/(lib/ARCH|lib*|share)/cmake/(Foo|foo|FOO).*/
  if (TryGeneratedPaths(searchFn, pdt::CMake, prefix, cmakePkgDirGen,
                        commonGen, cmakeGen, secondPkgDirGen)) {
    return true;
  }

  // PREFIX/(Foo|foo|FOO).*/(lib/ARCH|lib*|share)/(Foo|foo|FOO).*/
  if (TryGeneratedPaths(searchFn, pdt::CMake, prefix, cmakePkgDirGen,
                        commonGen, secondPkgDirGen)) {
    return true;
  }

  // PREFIX/(Foo|foo|FOO).*/(lib/ARCH|lib*|share)/(Foo|foo|FOO).*/(cmake|CMake)/
  return TryGeneratedPaths(searchFn, pdt::CMake, prefix, cmakePkgDirGen,
                           commonGen, secondPkgDirGen, iCMakeGen);
}

bool cmFindPackageCommand::SearchFrameworkPrefix(std::string const& prefix)
{
  assert(!prefix.empty() && prefix.back() == '/');

  auto searchFn = [this](const std::string& fullPath,
                         PackageDescriptionType type) -> bool {
    return this->SearchDirectory(fullPath, type);
  };

  auto iCMakeGen = cmCaseInsensitiveDirectoryListGenerator{ "cmake"_s };
  auto iCpsGen = cmCaseInsensitiveDirectoryListGenerator{ "cps"_s };
  auto fwGen =
    cmMacProjectDirectoryListGenerator{ &this->Names, ".framework"_s };
  auto rGen = cmAppendPathSegmentGenerator{ "Resources"_s };
  auto vGen = cmAppendPathSegmentGenerator{ "Versions"_s };
  auto anyGen =
    cmAnyDirectoryListGenerator{ this->SortOrder, this->SortDirection };

  // <prefix>/Foo.framework/Versions/*/Resources/CPS/
  if (TryGeneratedPaths(searchFn, pdt::Cps, prefix, fwGen, vGen, anyGen, rGen,
                        iCpsGen)) {
    return true;
  }

  // <prefix>/Foo.framework/Resources/CPS/
  if (TryGeneratedPaths(searchFn, pdt::Cps, prefix, fwGen, rGen, iCpsGen)) {
    return true;
  }

  // <prefix>/Foo.framework/Resources/
  if (TryGeneratedPaths(searchFn, pdt::CMake, prefix, fwGen, rGen)) {
    return true;
  }

  // <prefix>/Foo.framework/Resources/CMake/
  if (TryGeneratedPaths(searchFn, pdt::CMake, prefix, fwGen, rGen,
                        iCMakeGen)) {
    return true;
  }

  // <prefix>/Foo.framework/Versions/*/Resources/
  if (TryGeneratedPaths(searchFn, pdt::CMake, prefix, fwGen, vGen, anyGen,
                        rGen)) {
    return true;
  }

  // <prefix>/Foo.framework/Versions/*/Resources/CMake/
  return TryGeneratedPaths(searchFn, pdt::CMake, prefix, fwGen, vGen, anyGen,
                           rGen, iCMakeGen);
}

bool cmFindPackageCommand::SearchAppBundlePrefix(std::string const& prefix)
{
  assert(!prefix.empty() && prefix.back() == '/');

  auto searchFn = [this](const std::string& fullPath,
                         PackageDescriptionType type) -> bool {
    return this->SearchDirectory(fullPath, type);
  };

  auto appGen = cmMacProjectDirectoryListGenerator{ &this->Names, ".app"_s };
  auto crGen = cmAppendPathSegmentGenerator{ "Contents/Resources"_s };

  // <prefix>/Foo.app/Contents/Resources/CPS/
  if (TryGeneratedPaths(searchFn, pdt::Cps, prefix, appGen, crGen,
                        cmCaseInsensitiveDirectoryListGenerator{ "cps"_s })) {
    return true;
  }

  // <prefix>/Foo.app/Contents/Resources/
  if (TryGeneratedPaths(searchFn, pdt::CMake, prefix, appGen, crGen)) {
    return true;
  }

  // <prefix>/Foo.app/Contents/Resources/CMake/
  return TryGeneratedPaths(
    searchFn, pdt::CMake, prefix, appGen, crGen,
    cmCaseInsensitiveDirectoryListGenerator{ "cmake"_s });
}

bool cmFindPackageCommand::SearchEnvironmentPrefix(std::string const& prefix)
{
  assert(!prefix.empty() && prefix.back() == '/');

  // Skip this if the prefix does not exist.
  if (!cmSystemTools::FileIsDirectory(prefix)) {
    return false;
  }

  auto searchFn = [this](const std::string& fullPath,
                         PackageDescriptionType type) -> bool {
    return this->SearchDirectory(fullPath, type);
  };

  auto pkgDirGen =
    cmProjectDirectoryListGenerator{ &this->Names, this->SortOrder,
                                     this->SortDirection, true };

  // <environment-path>/(Foo|foo|FOO)/cps/
  if (TryGeneratedPaths(searchFn, pdt::Cps, prefix, pkgDirGen,
                        cmAppendPathSegmentGenerator{ "cps"_s })) {
    return true;
  }

  // <environment-path>/(Foo|foo|FOO)/
  return TryGeneratedPaths(searchFn, pdt::Cps, prefix, pkgDirGen);
}

// TODO: Debug cmsys::Glob double slash problem.

bool cmFindPackage(std::vector<std::string> const& args,
                   cmExecutionStatus& status)
{
  return cmFindPackageCommand(status).InitialPass(args);
}
