Jelajahi Sumber

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 tahun lalu
induk
melakukan
bf5ece51c3

+ 9 - 1
Source/cmGeneratorExpression.cxx

@@ -94,7 +94,15 @@ const char *cmCompiledGeneratorExpression::Evaluate(
 
   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)
       {
       this->Output = "";

+ 4 - 0
Source/cmGeneratorExpression.h

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

+ 1 - 0
Source/cmGeneratorExpressionEvaluator.h

@@ -24,6 +24,7 @@ struct cmGeneratorExpressionContext
 {
   cmListFileBacktrace Backtrace;
   std::set<cmTarget*> Targets;
+  std::set<cmStdString> SeenTargetProperties;
   cmMakefile *Makefile;
   const char *Config;
   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;
     cmGeneratorExpression ge(lfbt);
+    const cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(prop);
 
     cmGeneratorExpressionDAGChecker dagChecker(lfbt,
                                         this->GetName(),
                                         "LINK_LIBRARIES", 0, 0);
-    cmSystemTools::ExpandListArgument(ge.Parse(prop)->Evaluate(this->Makefile,
+    cmSystemTools::ExpandListArgument(cge->Evaluate(this->Makefile,
                                         config,
                                         false,
                                         head,
                                         &dagChecker),
                                       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
 {

+ 10 - 0
Source/cmTarget.h

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