diff options
author | Craig Scott <craig.scott@crascit.com> | 2022-04-28 13:00:19 (GMT) |
---|---|---|
committer | Craig Scott <craig.scott@crascit.com> | 2022-05-03 06:48:11 (GMT) |
commit | 29e31e2825a2cd5099b8abe66f4816919cec934a (patch) | |
tree | a1590254fba9ed2a4e5e80b6725fc3f9795ac269 /Source/cmFindPackageCommand.cxx | |
parent | 1d82670bd4daff26d0d0169820b289bc401f4943 (diff) | |
download | CMake-29e31e2825a2cd5099b8abe66f4816919cec934a.zip CMake-29e31e2825a2cd5099b8abe66f4816919cec934a.tar.gz CMake-29e31e2825a2cd5099b8abe66f4816919cec934a.tar.bz2 |
Packages: Integrate FetchContent and find_package()
Allow FetchContent_MakeAvailable() to try a call to
find_package() first, or redirect a find_package() call to
FetchContent_MakeAvailable(). The user can set variables
to control which of these are allowed or tried by default.
Fixes: #21687
Diffstat (limited to 'Source/cmFindPackageCommand.cxx')
-rw-r--r-- | Source/cmFindPackageCommand.cxx | 98 |
1 files changed, 91 insertions, 7 deletions
diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx index 9a89935..4031864 100644 --- a/Source/cmFindPackageCommand.cxx +++ b/Source/cmFindPackageCommand.cxx @@ -22,6 +22,7 @@ #include "cmsys/String.h" #include "cmAlgorithms.h" +#include "cmListFileCache.h" #include "cmMakefile.h" #include "cmMessageType.h" #include "cmPolicies.h" @@ -42,6 +43,8 @@ class cmExecutionStatus; class cmFileList; +cmFindPackageCommand::PathLabel + cmFindPackageCommand::PathLabel::PackageRedirect("PACKAGE_REDIRECT"); cmFindPackageCommand::PathLabel cmFindPackageCommand::PathLabel::UserRegistry( "PACKAGE_REGISTRY"); cmFindPackageCommand::PathLabel cmFindPackageCommand::PathLabel::Builds( @@ -109,8 +112,10 @@ void cmFindPackageCommand::AppendSearchPathGroups() { std::vector<cmFindCommon::PathLabel>* labels; - // Update the All group with new paths + // 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. labels = &this->PathGroupLabelMap[PathGroup::All]; + labels->insert(labels->begin(), PathLabel::PackageRedirect); labels->insert( std::find(labels->begin(), labels->end(), PathLabel::CMakeSystem), PathLabel::UserRegistry); @@ -122,6 +127,8 @@ void cmFindPackageCommand::AppendSearchPathGroups() // Create the new path objects this->LabeledPaths.insert( + std::make_pair(PathLabel::PackageRedirect, cmSearchPath(this))); + this->LabeledPaths.insert( std::make_pair(PathLabel::UserRegistry, cmSearchPath(this))); this->LabeledPaths.insert( std::make_pair(PathLabel::Builds, cmSearchPath(this))); @@ -552,9 +559,62 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args) this->SetModuleVariables(components); + // 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 (this->Makefile->IsOn("CMAKE_FIND_PACKAGE_PREFER_CONFIG")) { + if (forceConfigMode) { + loadedPackage = this->FindPackageUsingConfigMode(); + } else if (this->Makefile->IsOn("CMAKE_FIND_PACKAGE_PREFER_CONFIG")) { if (this->UseConfigFiles && this->FindPackageUsingConfigMode()) { loadedPackage = true; } else { @@ -1164,19 +1224,24 @@ bool cmFindPackageCommand::FindConfig() } 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 help = cmStrCat("The directory containing a CMake configuration file for ", this->Name, '.'); - // We force the value since we do not get here if it was already set. - this->Makefile->AddCacheDefinition(this->Variable, init, help.c_str(), + this->Makefile->AddCacheDefinition(this->Variable, value, help.c_str(), cmStateEnums::PATH, true); if (this->Makefile->GetPolicyStatus(cmPolicies::CMP0126) == cmPolicies::NEW && this->Makefile->IsNormalDefinitionSet(this->Variable)) { - this->Makefile->AddDefinition(this->Variable, init); + this->Makefile->AddDefinition(this->Variable, value); } - - return found; } bool cmFindPackageCommand::FindPrefixedConfig() @@ -1327,6 +1392,8 @@ inline std::size_t collectPathsForDebug(std::string& buffer, void cmFindPackageCommand::ComputePrefixes() { + this->FillPrefixesPackageRedirect(); + if (!this->NoDefaultPath) { if (!this->NoPackageRootPath) { this->FillPrefixesPackageRoot(); @@ -1360,6 +1427,23 @@ void cmFindPackageCommand::ComputePrefixes() this->ComputeFinalPaths(IgnorePaths::No); } +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]; |