mirror of
https://github.com/Kitware/CMake.git
synced 2025-10-14 10:47:59 +08:00
find_package: Refactor in support of recursion
Separate argument handling and actual operation of the find_package command into separate methods. This is preparatory to adding improved support for transitive dependencies and will allow nested calls to be set up using structured data types, rather than having to perform all communication via a constructed argument list. As a consequence, the sets of required and optional components, as well as the component list string, are now members rather than local variables. This also allows us to drop some parameters and simplify how we set the variables indicating which components are required.
This commit is contained in:
@@ -468,12 +468,10 @@ class cmFindPackageCommand::SetRestoreFindDefinitions
|
||||
cmFindPackageCommand& Command;
|
||||
|
||||
public:
|
||||
SetRestoreFindDefinitions(
|
||||
cmFindPackageCommand& command, const std::string& components,
|
||||
const std::vector<std::pair<std::string, const char*>>& componentVarDefs)
|
||||
SetRestoreFindDefinitions(cmFindPackageCommand& command)
|
||||
: Command(command)
|
||||
{
|
||||
Command.SetModuleVariables(components, componentVarDefs);
|
||||
Command.SetModuleVariables();
|
||||
}
|
||||
~SetRestoreFindDefinitions() { Command.RestoreFindDefinitions(); }
|
||||
};
|
||||
@@ -651,11 +649,7 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args)
|
||||
|
||||
// Record options.
|
||||
this->Name = args[0];
|
||||
std::string components;
|
||||
const char* components_sep = "";
|
||||
std::set<std::string> requiredComponents;
|
||||
std::set<std::string> optionalComponents;
|
||||
std::vector<std::pair<std::string, const char*>> componentVarDefs;
|
||||
cm::string_view componentsSep = ""_s;
|
||||
bool bypassProvider = false;
|
||||
|
||||
// Always search directly in a generated path.
|
||||
@@ -769,21 +763,16 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args)
|
||||
(doing == DoingOptionalComponents)) {
|
||||
// Set a variable telling the find script whether this component
|
||||
// is required.
|
||||
const char* isRequired = "1";
|
||||
if (doing == DoingOptionalComponents) {
|
||||
isRequired = "0";
|
||||
optionalComponents.insert(args[i]);
|
||||
this->OptionalComponents.insert(args[i]);
|
||||
} else {
|
||||
requiredComponents.insert(args[i]);
|
||||
this->RequiredComponents.insert(args[i]);
|
||||
}
|
||||
|
||||
componentVarDefs.emplace_back(this->Name + "_FIND_REQUIRED_" + args[i],
|
||||
isRequired);
|
||||
|
||||
// Append to the list of required components.
|
||||
components += components_sep;
|
||||
components += args[i];
|
||||
components_sep = ";";
|
||||
this->Components += componentsSep;
|
||||
this->Components += args[i];
|
||||
componentsSep = ";"_s;
|
||||
} else if (doing == DoingNames) {
|
||||
this->Names.push_back(args[i]);
|
||||
} else if (doing == DoingPaths) {
|
||||
@@ -819,9 +808,10 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args)
|
||||
}
|
||||
|
||||
std::vector<std::string> doubledComponents;
|
||||
std::set_intersection(requiredComponents.begin(), requiredComponents.end(),
|
||||
optionalComponents.begin(), optionalComponents.end(),
|
||||
std::back_inserter(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 "
|
||||
@@ -856,7 +846,7 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args)
|
||||
"Ignoring EXACT since no version is requested.");
|
||||
}
|
||||
|
||||
if (this->VersionComplete.empty() || components.empty()) {
|
||||
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");
|
||||
@@ -871,9 +861,12 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args)
|
||||
std::string const exact = cmStrCat(this->Name, "_FIND_VERSION_EXACT");
|
||||
this->VersionExact = this->Makefile->IsOn(exact);
|
||||
}
|
||||
if (components.empty()) {
|
||||
if (this->Components.empty()) {
|
||||
std::string const components_var = this->Name + "_FIND_COMPONENTS";
|
||||
components = this->Makefile->GetSafeDefinition(components_var);
|
||||
this->Components = this->Makefile->GetSafeDefinition(components_var);
|
||||
for (auto const& component : cmList{ this->Components }) {
|
||||
this->RequiredComponents.insert(component);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -924,6 +917,12 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args)
|
||||
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 =
|
||||
@@ -997,7 +996,7 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args)
|
||||
cmState* const state = this->Makefile->GetState();
|
||||
cmState::Command const providerCommand = state->GetDependencyProviderCommand(
|
||||
cmDependencyProvider::Method::FindPackage);
|
||||
if (bypassProvider) {
|
||||
if (argsForProvider.empty()) {
|
||||
if (this->DebugMode && providerCommand) {
|
||||
this->DebugMessage(
|
||||
"BYPASS_PROVIDER given, skipping dependency provider");
|
||||
@@ -1008,11 +1007,11 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args)
|
||||
state->GetDependencyProvider()->GetCommand(),
|
||||
"()"));
|
||||
}
|
||||
std::vector<cmListFileArgument> listFileArgs(args.size() + 1);
|
||||
std::vector<cmListFileArgument> listFileArgs(argsForProvider.size() + 1);
|
||||
listFileArgs[0] =
|
||||
cmListFileArgument("FIND_PACKAGE", cmListFileArgument::Unquoted, 0);
|
||||
std::transform(args.begin(), args.end(), listFileArgs.begin() + 1,
|
||||
[](const std::string& arg) {
|
||||
std::transform(argsForProvider.begin(), argsForProvider.end(),
|
||||
listFileArgs.begin() + 1, [](const std::string& arg) {
|
||||
return cmListFileArgument(arg,
|
||||
cmListFileArgument::Bracket, 0);
|
||||
});
|
||||
@@ -1043,11 +1042,10 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args)
|
||||
}
|
||||
}
|
||||
|
||||
// RAII objects to ensure we leave this function with consistent state
|
||||
// RAII objects to ensure we leave this function with consistent state.
|
||||
FlushDebugBufferOnExit flushDebugBufferOnExit(*this);
|
||||
PushPopRootPathStack pushPopRootPathStack(*this);
|
||||
SetRestoreFindDefinitions setRestoreFindDefinitions(*this, components,
|
||||
componentVarDefs);
|
||||
SetRestoreFindDefinitions setRestoreFindDefinitions(*this);
|
||||
cmMakefile::FindPackageStackRAII findPackageStackRAII(this->Makefile,
|
||||
this->Name);
|
||||
|
||||
@@ -1247,17 +1245,20 @@ void cmFindPackageCommand::SetVersionVariables(
|
||||
addDefinition(prefix + "_COUNT", buf);
|
||||
}
|
||||
|
||||
void cmFindPackageCommand::SetModuleVariables(
|
||||
const std::string& components,
|
||||
const std::vector<std::pair<std::string, const char*>>& componentVarDefs)
|
||||
void cmFindPackageCommand::SetModuleVariables()
|
||||
{
|
||||
this->AddFindDefinition("CMAKE_FIND_PACKAGE_NAME", this->Name);
|
||||
|
||||
// Store the list of components and associated variable definitions
|
||||
// Store the list of components and associated variable definitions.
|
||||
std::string components_var = this->Name + "_FIND_COMPONENTS";
|
||||
this->AddFindDefinition(components_var, components);
|
||||
for (const auto& varDef : componentVarDefs) {
|
||||
this->AddFindDefinition(varDef.first, varDef.second);
|
||||
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) {
|
||||
|
@@ -9,7 +9,6 @@
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <cm/string_view>
|
||||
@@ -83,6 +82,11 @@ private:
|
||||
static PathLabel SystemRegistry;
|
||||
};
|
||||
|
||||
// Try to find a package, assuming most state has already been set up. This
|
||||
// is used for recursive dependency solving, particularly when importing
|
||||
// packages via CPS. Bypasses providers if argsForProvider is empty.
|
||||
bool FindPackage(std::vector<std::string> const& argsForProvider);
|
||||
|
||||
bool FindPackageUsingModuleMode();
|
||||
bool FindPackageUsingConfigMode();
|
||||
|
||||
@@ -98,9 +102,7 @@ private:
|
||||
const std::string& prefix, const std::string& version, unsigned int count,
|
||||
unsigned int major, unsigned int minor, unsigned int patch,
|
||||
unsigned int tweak);
|
||||
void SetModuleVariables(
|
||||
const std::string& components,
|
||||
const std::vector<std::pair<std::string, const char*>>& componentVarDefs);
|
||||
void SetModuleVariables();
|
||||
bool FindModule(bool& found);
|
||||
void AddFindDefinition(const std::string& var, cm::string_view value);
|
||||
void RestoreFindDefinitions();
|
||||
@@ -216,6 +218,9 @@ private:
|
||||
std::vector<std::string> Configs;
|
||||
std::set<std::string> IgnoredPaths;
|
||||
std::set<std::string> IgnoredPrefixPaths;
|
||||
std::string Components;
|
||||
std::set<std::string> RequiredComponents;
|
||||
std::set<std::string> OptionalComponents;
|
||||
std::string DebugBuffer;
|
||||
|
||||
class FlushDebugBufferOnExit;
|
||||
|
Reference in New Issue
Block a user