Browse Source

Make calculation of link-interface-dependent properties type-sensitive.

Stephen Kelly 13 years ago
parent
commit
cd66b9131d
1 changed files with 118 additions and 48 deletions
  1. 118 48
      Source/cmTarget.cxx

+ 118 - 48
Source/cmTarget.cxx

@@ -4500,22 +4500,50 @@ void cmTarget::AddLinkDependentTargetsForProperties(
 }
 
 //----------------------------------------------------------------------------
-bool cmTarget::GetLinkInterfaceDependentBoolProperty(const std::string &p,
-                                                     const char *config)
+template<typename PropertyType>
+PropertyType getTypedProperty(cmTarget *tgt, const char *prop,
+                              PropertyType *);
+
+//----------------------------------------------------------------------------
+template<>
+bool getTypedProperty<bool>(cmTarget *tgt, const char *prop, bool *)
 {
-  bool propContent = this->GetPropertyAsBool(p.c_str());
-  const bool explicitlySet = this->GetProperties()
+  return tgt->GetPropertyAsBool(prop);
+}
+
+//----------------------------------------------------------------------------
+template<typename PropertyType>
+bool consistentProperty(PropertyType lhs, PropertyType rhs);
+
+//----------------------------------------------------------------------------
+template<>
+bool consistentProperty(bool lhs, bool rhs)
+{
+  return lhs == rhs;
+}
+
+//----------------------------------------------------------------------------
+template<typename PropertyType>
+PropertyType checkInterfacePropertyCompatibility(cmTarget *tgt,
+                                          const std::string &p,
+                                          const char *config,
+                                          const char *defaultValue,
+                                          PropertyType *)
+{
+  PropertyType propContent = getTypedProperty<PropertyType>(tgt, p.c_str(),
+                                                            0);
+  const bool explicitlySet = tgt->GetProperties()
                                   .find(p.c_str())
-                                  != this->GetProperties().end();
+                                  != tgt->GetProperties().end();
   std::set<std::string> dependentTargets;
-  this->GetLinkDependentTargetsForProperty(p,
+  tgt->GetLinkDependentTargetsForProperty(p,
                                           dependentTargets);
   const bool impliedByUse =
-          this->IsNullImpliedByLinkLibraries(p);
+          tgt->IsNullImpliedByLinkLibraries(p);
   assert((impliedByUse ^ explicitlySet)
       || (!impliedByUse && !explicitlySet));
 
-  cmComputeLinkInformation *info = this->GetLinkInformation(config);
+  cmComputeLinkInformation *info = tgt->GetLinkInformation(config);
   const cmComputeLinkInformation::ItemVector &deps = info->GetItems();
   bool propInitialized = explicitlySet;
 
@@ -4537,17 +4565,18 @@ bool cmTarget::GetLinkInterfaceDependentBoolProperty(const std::string &p,
     const bool ifaceIsSet = li->Target->GetProperties()
                             .find("INTERFACE_" + p)
                             != li->Target->GetProperties().end();
-    const bool ifacePropContent = li->Target->GetPropertyAsBool(
-                              ("INTERFACE_" + p).c_str());
+    PropertyType ifacePropContent =
+                    getTypedProperty<PropertyType>(li->Target,
+                              ("INTERFACE_" + p).c_str(), 0);
     if (explicitlySet)
       {
       if (ifaceIsSet)
         {
-        if (propContent != ifacePropContent)
+        if (!consistentProperty(propContent, ifacePropContent))
           {
           cmOStringStream e;
           e << "Property " << p << " on target \""
-            << this->GetName() << "\" does\nnot match the "
+            << tgt->GetName() << "\" does\nnot match the "
             "INTERFACE_" << p << " property requirement\nof "
             "dependency \"" << li->Target->GetName() << "\".\n";
           cmSystemTools::Error(e.str().c_str());
@@ -4569,13 +4598,13 @@ bool cmTarget::GetLinkInterfaceDependentBoolProperty(const std::string &p,
       {
       if (ifaceIsSet)
         {
-        if (propContent != ifacePropContent)
+        if (!consistentProperty(propContent, ifacePropContent))
           {
           cmOStringStream e;
           e << "Property " << p << " on target \""
-            << this->GetName() << "\" is\nimplied to be FALSE because it "
-            "was used to determine the link libraries\nalready. The "
-            "INTERFACE_" << p << " property on\ndependency \""
+            << tgt->GetName() << "\" is\nimplied to be " << defaultValue
+            << " because it was used to determine the link libraries\n"
+               "already. The INTERFACE_" << p << " property on\ndependency \""
             << li->Target->GetName() << "\" is in conflict.\n";
           cmSystemTools::Error(e.str().c_str());
           break;
@@ -4598,13 +4627,13 @@ bool cmTarget::GetLinkInterfaceDependentBoolProperty(const std::string &p,
         {
         if (propInitialized)
           {
-          if (propContent != ifacePropContent)
+          if (!consistentProperty(propContent, ifacePropContent))
             {
             cmOStringStream e;
             e << "The INTERFACE_" << p << " property of \""
               << li->Target->GetName() << "\" does\nnot agree with the value "
                 "of " << p << " already determined\nfor \""
-              << this->GetName() << "\".\n";
+              << tgt->GetName() << "\".\n";
             cmSystemTools::Error(e.str().c_str());
             break;
             }
@@ -4630,6 +4659,14 @@ bool cmTarget::GetLinkInterfaceDependentBoolProperty(const std::string &p,
   return propContent;
 }
 
+//----------------------------------------------------------------------------
+bool cmTarget::GetLinkInterfaceDependentBoolProperty(const std::string &p,
+                                                     const char *config)
+{
+  return checkInterfacePropertyCompatibility<bool>(this, p, config, "FALSE",
+                                                   0);
+}
+
 //----------------------------------------------------------------------------
 bool isLinkDependentProperty(cmTarget *tgt, const std::string &p,
                              const char *interfaceProperty,
@@ -5417,6 +5454,64 @@ std::string cmTarget::CheckCMP0004(std::string const& item)
   return lib;
 }
 
+template<typename PropertyType>
+PropertyType getLinkInterfaceDependentProperty(cmTarget *tgt,
+                                               const std::string prop,
+                                               const char *config,
+                                               PropertyType *);
+
+template<>
+bool getLinkInterfaceDependentProperty(cmTarget *tgt,
+                                         const std::string prop,
+                                         const char *config, bool *)
+{
+  return tgt->GetLinkInterfaceDependentBoolProperty(prop, config);
+}
+
+//----------------------------------------------------------------------------
+template<typename PropertyType>
+void checkPropertyConsistency(cmTarget *depender, cmTarget *dependee,
+                              const char *propName,
+                              std::set<cmStdString> &emitted,
+                              const char *config,
+                              PropertyType *)
+{
+  const char *prop = dependee->GetProperty(propName);
+  if (!prop)
+    {
+    return;
+    }
+
+  std::vector<std::string> props;
+  cmSystemTools::ExpandListArgument(prop, props);
+
+  for(std::vector<std::string>::iterator pi = props.begin();
+      pi != props.end(); ++pi)
+    {
+    if (depender->GetMakefile()->GetCMakeInstance()
+                      ->GetIsPropertyDefined(pi->c_str(),
+                                              cmProperty::TARGET))
+      {
+      cmOStringStream e;
+      e << "Target \"" << dependee->GetName() << "\" has property \""
+        << *pi << "\" listed in its " << propName << " property.  "
+          "This is not allowed.  Only user-defined properties may appear "
+          "listed in the " << propName << " property.";
+      depender->GetMakefile()->IssueMessage(cmake::FATAL_ERROR, e.str());
+      return;
+      }
+    if(emitted.insert(*pi).second)
+      {
+      getLinkInterfaceDependentProperty<PropertyType>(depender, *pi, config,
+                                                      0);
+      if (cmSystemTools::GetErrorOccuredFlag())
+        {
+        return;
+        }
+      }
+    }
+}
+
 //----------------------------------------------------------------------------
 void cmTarget::CheckPropertyCompatibility(cmComputeLinkInformation *info,
                                           const char* config)
@@ -5433,38 +5528,13 @@ void cmTarget::CheckPropertyCompatibility(cmComputeLinkInformation *info,
       {
       continue;
       }
-    const char *prop = li->Target->GetProperty("COMPATIBLE_INTERFACE_BOOL");
-    if (!prop)
-      {
-      continue;
-      }
-
-    std::vector<std::string> props;
-    cmSystemTools::ExpandListArgument(prop, props);
 
-    for(std::vector<std::string>::iterator pi = props.begin();
-        pi != props.end(); ++pi)
+    checkPropertyConsistency<bool>(this, li->Target,
+                                   "COMPATIBLE_INTERFACE_BOOL",
+                                   emitted, config, 0);
+    if (cmSystemTools::GetErrorOccuredFlag())
       {
-      if (this->Makefile->GetCMakeInstance()
-                        ->GetIsPropertyDefined(pi->c_str(),
-                                                cmProperty::TARGET))
-        {
-        cmOStringStream e;
-        e << "Target \"" << li->Target->GetName() << "\" has property \""
-          << *pi << "\" listed in its COMPATIBLE_INTERFACE_BOOL property.  "
-            "This is not allowed.  Only user-defined properties may appear "
-            "listed in the COMPATIBLE_INTERFACE_BOOL property.";
-        this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
-        return;
-        }
-      if(emitted.insert(*pi).second)
-        {
-        this->GetLinkInterfaceDependentBoolProperty(*pi, config);
-        if (cmSystemTools::GetErrorOccuredFlag())
-          {
-          return;
-          }
-        }
+      return;
       }
     }
 }