Jelajahi Sumber

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
Alex Neundorf 14 tahun lalu
induk
melakukan
f2e0a18761
1 mengubah file dengan 39 tambahan dan 5 penghapusan
  1. 39 5
      Source/cmFindPackageCommand.cxx

+ 39 - 5
Source/cmFindPackageCommand.cxx

@@ -410,6 +410,8 @@ bool cmFindPackageCommand
   this->Name = args[0];
   std::string components;
   const char* components_sep = "";
+  std::set<std::string> requiredComponents;
+  std::set<std::string> optionalComponents;
 
   // Check ancient compatibility.
   this->Compatibility_1_6 =
@@ -420,8 +422,8 @@ bool cmFindPackageCommand
   this->SearchPathSuffixes.push_back("");
 
   // Parse the arguments.
-  enum Doing { DoingNone, DoingComponents, DoingNames, DoingPaths,
-               DoingPathSuffixes, DoingConfigs, DoingHints };
+  enum Doing { DoingNone, DoingComponents, DoingOptionalComponents, DoingNames,
+               DoingPaths, DoingPathSuffixes, DoingConfigs, DoingHints };
   Doing doing = DoingNone;
   cmsys::RegularExpression version("^[0-9.]+$");
   bool haveVersion = false;
@@ -465,6 +467,11 @@ bool cmFindPackageCommand
       this->Compatibility_1_6 = false;
       doing = DoingComponents;
       }
+    else if(args[i] == "OPTIONAL_COMPONENTS")
+      {
+      this->Compatibility_1_6 = false;
+      doing = DoingOptionalComponents;
+      }
     else if(args[i] == "NAMES")
       {
       configArgs.insert(i);
@@ -528,12 +535,23 @@ bool cmFindPackageCommand
       this->Compatibility_1_6 = false;
       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.
+      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];
-      this->AddFindDefinition(req_var.c_str(), "1");
+      this->AddFindDefinition(req_var.c_str(), isRequired);
 
       // Append to the list of required components.
       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.
   this->UseFindModules = configArgs.empty();
   this->UseConfigFiles = moduleArgs.empty();