find_package: add OPTIONAL_COMPONENTS keyword

Add an OPTIONAL_COMPONENTS keyword to find_package() so we can have a
clear distinction between required and optional components.  Don't allow
a component to be both required and optional.

Alex
This commit is contained in:
Alex Neundorf 2012-03-18 12:41:28 +01:00 committed by Brad King
parent 0cf84472d7
commit f2e0a18761
1 changed files with 39 additions and 5 deletions

View File

@ -410,6 +410,8 @@ bool cmFindPackageCommand
this->Name = args[0]; this->Name = args[0];
std::string components; std::string components;
const char* components_sep = ""; const char* components_sep = "";
std::set<std::string> requiredComponents;
std::set<std::string> optionalComponents;
// Check ancient compatibility. // Check ancient compatibility.
this->Compatibility_1_6 = this->Compatibility_1_6 =
@ -420,8 +422,8 @@ bool cmFindPackageCommand
this->SearchPathSuffixes.push_back(""); this->SearchPathSuffixes.push_back("");
// Parse the arguments. // Parse the arguments.
enum Doing { DoingNone, DoingComponents, DoingNames, DoingPaths, enum Doing { DoingNone, DoingComponents, DoingOptionalComponents, DoingNames,
DoingPathSuffixes, DoingConfigs, DoingHints }; DoingPaths, DoingPathSuffixes, DoingConfigs, DoingHints };
Doing doing = DoingNone; Doing doing = DoingNone;
cmsys::RegularExpression version("^[0-9.]+$"); cmsys::RegularExpression version("^[0-9.]+$");
bool haveVersion = false; bool haveVersion = false;
@ -465,6 +467,11 @@ bool cmFindPackageCommand
this->Compatibility_1_6 = false; this->Compatibility_1_6 = false;
doing = DoingComponents; doing = DoingComponents;
} }
else if(args[i] == "OPTIONAL_COMPONENTS")
{
this->Compatibility_1_6 = false;
doing = DoingOptionalComponents;
}
else if(args[i] == "NAMES") else if(args[i] == "NAMES")
{ {
configArgs.insert(i); configArgs.insert(i);
@ -528,12 +535,23 @@ bool cmFindPackageCommand
this->Compatibility_1_6 = false; this->Compatibility_1_6 = false;
doing = DoingNone; doing = DoingNone;
} }
else if(doing == DoingComponents) else if((doing == DoingComponents) || (doing == DoingOptionalComponents))
{ {
// Set a variable telling the find script this component // Set a variable telling the find script whether this component
// is required. // is required.
const char* isRequired = "1";
if (doing == DoingOptionalComponents)
{
isRequired = "0";
optionalComponents.insert(args[i]);
}
else
{
requiredComponents.insert(args[i]);
}
std::string req_var = this->Name + "_FIND_REQUIRED_" + args[i]; std::string req_var = this->Name + "_FIND_REQUIRED_" + args[i];
this->AddFindDefinition(req_var.c_str(), "1"); this->AddFindDefinition(req_var.c_str(), isRequired);
// Append to the list of required components. // Append to the list of required components.
components += components_sep; components += components_sep;
@ -584,6 +602,22 @@ bool cmFindPackageCommand
} }
} }
std::vector<std::string> doubledComponents;
std::set_intersection(requiredComponents.begin(), requiredComponents.end(),
optionalComponents.begin(), optionalComponents.end(),
std::back_inserter(doubledComponents));
if(!doubledComponents.empty())
{
cmOStringStream e;
e << "called with components that are both required and optional:\n";
for(unsigned int i=0; i<doubledComponents.size(); ++i)
{
e << " " << doubledComponents[i] << "\n";
}
this->SetError(e.str().c_str());
return false;
}
// Maybe choose one mode exclusively. // Maybe choose one mode exclusively.
this->UseFindModules = configArgs.empty(); this->UseFindModules = configArgs.empty();
this->UseConfigFiles = moduleArgs.empty(); this->UseConfigFiles = moduleArgs.empty();