瀏覽代碼

Keep track of properties used to determine linker libraries.

Those properties can't later be implicitly defined by the interface
of those link libraries.
Stephen Kelly 13 年之前
父節點
當前提交
bf5ece51c3

+ 9 - 1
Source/cmGeneratorExpression.cxx

@@ -94,7 +94,15 @@ const char *cmCompiledGeneratorExpression::Evaluate(
 
 
   for ( ; it != end; ++it)
   for ( ; it != end; ++it)
     {
     {
-    this->Output += (*it)->Evaluate(&context, dagChecker);
+    const std::string result = (*it)->Evaluate(&context, dagChecker);
+    this->Output += result;
+
+    for(std::set<cmStdString>::const_iterator
+          p = context.SeenTargetProperties.begin();
+          p != context.SeenTargetProperties.end(); ++p)
+      {
+      this->SeenTargetProperties[*p] += result + ";";
+      }
     if (context.HadError)
     if (context.HadError)
       {
       {
       this->Output = "";
       this->Output = "";

+ 4 - 0
Source/cmGeneratorExpression.h

@@ -83,6 +83,9 @@ public:
   std::set<cmTarget*> const& GetTargets() const
   std::set<cmTarget*> const& GetTargets() const
     { return this->Targets; }
     { return this->Targets; }
 
 
+  std::map<cmStdString, cmStdString> const& GetSeenTargetProperties() const
+    { return this->SeenTargetProperties; }
+
   ~cmCompiledGeneratorExpression();
   ~cmCompiledGeneratorExpression();
 
 
   std::string GetInput() const
   std::string GetInput() const
@@ -110,6 +113,7 @@ private:
   bool NeedsParsing;
   bool NeedsParsing;
 
 
   mutable std::set<cmTarget*> Targets;
   mutable std::set<cmTarget*> Targets;
+  mutable std::map<cmStdString, cmStdString> SeenTargetProperties;
   mutable std::string Output;
   mutable std::string Output;
 };
 };
 
 

+ 8 - 0
Source/cmGeneratorExpressionEvaluator.cxx

@@ -380,6 +380,14 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
         }
         }
       }
       }
 
 
+    if (target == context->HeadTarget)
+      {
+      // Keep track of the properties seen while processing.
+      // The evaluation of the LINK_LIBRARIES generator expressions
+      // will check this to ensure that properties form a DAG.
+      context->SeenTargetProperties.insert(propertyName);
+      }
+
     if (propertyName.empty())
     if (propertyName.empty())
       {
       {
       reportError(context, content->GetOriginalExpression(),
       reportError(context, content->GetOriginalExpression(),

+ 1 - 0
Source/cmGeneratorExpressionEvaluator.h

@@ -24,6 +24,7 @@ struct cmGeneratorExpressionContext
 {
 {
   cmListFileBacktrace Backtrace;
   cmListFileBacktrace Backtrace;
   std::set<cmTarget*> Targets;
   std::set<cmTarget*> Targets;
+  std::set<cmStdString> SeenTargetProperties;
   cmMakefile *Makefile;
   cmMakefile *Makefile;
   const char *Config;
   const char *Config;
   cmTarget *HeadTarget; // The target whose property is being evaluated.
   cmTarget *HeadTarget; // The target whose property is being evaluated.

+ 41 - 1
Source/cmTarget.cxx

@@ -2164,16 +2164,19 @@ void cmTarget::GetDirectLinkLibraries(const char *config,
     {
     {
     cmListFileBacktrace lfbt;
     cmListFileBacktrace lfbt;
     cmGeneratorExpression ge(lfbt);
     cmGeneratorExpression ge(lfbt);
+    const cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(prop);
 
 
     cmGeneratorExpressionDAGChecker dagChecker(lfbt,
     cmGeneratorExpressionDAGChecker dagChecker(lfbt,
                                         this->GetName(),
                                         this->GetName(),
                                         "LINK_LIBRARIES", 0, 0);
                                         "LINK_LIBRARIES", 0, 0);
-    cmSystemTools::ExpandListArgument(ge.Parse(prop)->Evaluate(this->Makefile,
+    cmSystemTools::ExpandListArgument(cge->Evaluate(this->Makefile,
                                         config,
                                         config,
                                         false,
                                         false,
                                         head,
                                         head,
                                         &dagChecker),
                                         &dagChecker),
                                       libs);
                                       libs);
+
+    this->AddLinkDependentTargetsForProperties(cge->GetSeenTargetProperties());
     }
     }
 }
 }
 
 
@@ -4376,6 +4379,43 @@ const char* cmTarget::GetExportMacro()
     }
     }
 }
 }
 
 
+//----------------------------------------------------------------------------
+void cmTarget::GetLinkDependentTargetsForProperty(const std::string &p,
+                                          std::set<std::string> &targets)
+{
+  const std::map<cmStdString, std::set<std::string> >::const_iterator findIt
+                                  = this->LinkDependentProperties.find(p);
+  if (findIt != this->LinkDependentProperties.end())
+    {
+    targets = findIt->second;
+    }
+}
+
+//----------------------------------------------------------------------------
+bool cmTarget::IsNullImpliedByLinkLibraries(const std::string &p)
+{
+  return this->LinkImplicitNullProperties.find(p)
+      != this->LinkImplicitNullProperties.end();
+}
+
+//----------------------------------------------------------------------------
+void cmTarget::AddLinkDependentTargetsForProperties(
+                              const std::map<cmStdString, cmStdString> &map)
+{
+  for (std::map<cmStdString, cmStdString>::const_iterator it = map.begin();
+       it != map.end(); ++it)
+    {
+    std::vector<std::string> targets;
+    cmSystemTools::ExpandListArgument(it->second.c_str(), targets);
+    this->LinkDependentProperties[it->first].insert(targets.begin(),
+                                                    targets.end());
+    if (!this->GetProperty(it->first.c_str()))
+      {
+      this->LinkImplicitNullProperties.insert(it->first);
+      }
+    }
+}
+
 //----------------------------------------------------------------------------
 //----------------------------------------------------------------------------
 void cmTarget::GetLanguages(std::set<cmStdString>& languages) const
 void cmTarget::GetLanguages(std::set<cmStdString>& languages) const
 {
 {

+ 10 - 0
Source/cmTarget.h

@@ -487,6 +487,13 @@ public:
   std::vector<std::string> GetIncludeDirectories(const char *config);
   std::vector<std::string> GetIncludeDirectories(const char *config);
   void InsertInclude(const cmMakefileIncludeDirectoriesEntry &entry,
   void InsertInclude(const cmMakefileIncludeDirectoriesEntry &entry,
                      bool before = false);
                      bool before = false);
+
+  void GetLinkDependentTargetsForProperty(const std::string &p,
+                                       std::set<std::string> &targets);
+  bool IsNullImpliedByLinkLibraries(const std::string &p);
+
+  void AddLinkDependentTargetsForProperties(
+          const std::map<cmStdString, cmStdString> &map);
 private:
 private:
   /**
   /**
    * A list of direct dependencies. Use in conjunction with DependencyMap.
    * A list of direct dependencies. Use in conjunction with DependencyMap.
@@ -596,6 +603,9 @@ private:
   bool DLLPlatform;
   bool DLLPlatform;
   bool IsApple;
   bool IsApple;
   bool IsImportedTarget;
   bool IsImportedTarget;
+  mutable std::map<cmStdString, std::set<std::string> >
+                                                      LinkDependentProperties;
+  mutable std::set<std::string> LinkImplicitNullProperties;
 
 
   // Cache target output paths for each configuration.
   // Cache target output paths for each configuration.
   struct OutputInfo;
   struct OutputInfo;