Forráskód Böngészése

cmDepends: allow multiple dependees per depender

This patch is heavily inspired by Michael Wild.

The interfaces cmDepends::Write and cmDepends::WriteDependencies where
extended to allow multiple dependees (sources) per depender (object).
cmDepends::Write first collect all dependencies into a std::set before
passing it to cmDepends::WriteDependencies.

cmDependsC::WriteDependencies also first collects all explicit and
implicit dependencies into a std::set and only then writes
depend.{internal,make}. The implementation of cmDependsFortran simply
loops over all sources and proceeds as before, whereas the cmDependsJava
implementation is as trivial as before.

This is for preventing exponential growth of depend.{internal,make} in
the next commit which fixes dependency-vector erasure in
cmDepends::CheckDependencies.

Inspired-by: Michael Wild <[email protected]>
Alex Neundorf 13 éve
szülő
commit
e74ff7c29f

+ 10 - 3
Source/cmDepends.cxx

@@ -50,6 +50,7 @@ bool cmDepends::Write(std::ostream &makeDepends,
   std::vector<std::string> pairs;
   cmSystemTools::ExpandListArgument(srcStr, pairs);
 
+  std::map<std::string, std::set<std::string> > dependencies;
   for(std::vector<std::string>::iterator si = pairs.begin();
       si != pairs.end();)
     {
@@ -62,9 +63,14 @@ bool cmDepends::Write(std::ostream &makeDepends,
     obj = this->LocalGenerator->Convert(obj.c_str(),
                                         cmLocalGenerator::HOME_OUTPUT,
                                         cmLocalGenerator::MAKEFILE);
+    dependencies[obj].insert(src);
+    }
+  for(std::map<std::string, std::set<std::string> >::const_iterator
+      it = dependencies.begin(); it != dependencies.end(); ++it)
+    {
 
     // Write the dependencies for this pair.
-    if(!this->WriteDependencies(src.c_str(), obj.c_str(),
+    if(!this->WriteDependencies(it->second, it->first,
                                 makeDepends, internalDepends))
       {
       return false;
@@ -134,8 +140,9 @@ void cmDepends::Clear(const char *file)
 }
 
 //----------------------------------------------------------------------------
-bool cmDepends::WriteDependencies(const char*, const char*,
-                                  std::ostream&, std::ostream&)
+bool cmDepends::WriteDependencies(
+    const std::set<std::string>&, const std::string&,
+    std::ostream&, std::ostream&)
 {
   // This should be implemented by the subclass.
   return false;

+ 4 - 2
Source/cmDepends.h

@@ -76,8 +76,10 @@ protected:
 
   // Write dependencies for the target file to the given stream.
   // Return true for success and false for failure.
-  virtual bool WriteDependencies(const char *src, const char* obj,
-    std::ostream& makeDepends, std::ostream& internalDepends);
+  virtual bool WriteDependencies(const std::set<std::string>& sources,
+                                 const std::string& obj,
+                                 std::ostream& makeDepends,
+                                 std::ostream& internalDepends);
 
   // Check dependencies for the target file in the given stream.
   // Return false if dependencies must be regenerated and true

+ 21 - 12
Source/cmDependsC.cxx

@@ -98,16 +98,18 @@ cmDependsC::~cmDependsC()
 }
 
 //----------------------------------------------------------------------------
-bool cmDependsC::WriteDependencies(const char *src, const char *obj,
-  std::ostream& makeDepends, std::ostream& internalDepends)
+bool cmDependsC::WriteDependencies(const std::set<std::string>& sources,
+                                   const std::string& obj,
+                                   std::ostream& makeDepends,
+                                   std::ostream& internalDepends)
 {
   // Make sure this is a scanning instance.
-  if(!src || src[0] == '\0')
+  if(sources.empty() || sources.begin()->empty())
     {
     cmSystemTools::Error("Cannot scan dependencies without a source file.");
     return false;
     }
-  if(!obj || obj[0] == '\0')
+  if(obj.empty())
     {
     cmSystemTools::Error("Cannot scan dependencies without an object file.");
     return false;
@@ -134,12 +136,18 @@ bool cmDependsC::WriteDependencies(const char *src, const char *obj,
   if (!haveDeps)
     {
     // Walk the dependency graph starting with the source file.
-    bool first = true;
-    UnscannedEntry root;
-    root.FileName = src;
-    this->Unscanned.push(root);
+    int srcFiles = (int)sources.size();
     this->Encountered.clear();
-    this->Encountered.insert(src);
+
+    for(std::set<std::string>::const_iterator srcIt = sources.begin();
+        srcIt != sources.end(); ++srcIt)
+      {
+      UnscannedEntry root;
+      root.FileName = *srcIt;
+      this->Unscanned.push(root);
+      this->Encountered.insert(*srcIt);
+      }
+
     std::set<cmStdString> scanned;
 
     // Use reserve to allocate enough memory for tempPathStr
@@ -155,7 +163,8 @@ bool cmDependsC::WriteDependencies(const char *src, const char *obj,
 
       // If not a full path, find the file in the include path.
       std::string fullName;
-      if(first || cmSystemTools::FileIsFullPath(current.FileName.c_str()))
+      if((srcFiles>0)
+         || cmSystemTools::FileIsFullPath(current.FileName.c_str()))
         {
         if(cmSystemTools::FileExists(current.FileName.c_str(), true))
           {
@@ -260,7 +269,7 @@ bool cmDependsC::WriteDependencies(const char *src, const char *obj,
           }
         }
 
-      first = false;
+      srcFiles--;
       }
     }
 
@@ -269,7 +278,7 @@ bool cmDependsC::WriteDependencies(const char *src, const char *obj,
   // convert the dependencies to paths relative to the home output
   // directory.  We must do the same here.
   internalDepends << obj << std::endl;
-  for(std::set<cmStdString>::iterator i=dependencies.begin();
+  for(std::set<cmStdString>::const_iterator i=dependencies.begin();
       i != dependencies.end(); ++i)
     {
     makeDepends << obj << ": " <<

+ 2 - 2
Source/cmDependsC.h

@@ -33,8 +33,8 @@ public:
 
 protected:
   // Implement writing/checking methods required by superclass.
-  virtual bool WriteDependencies(const char *src,
-                                 const char *file,
+  virtual bool WriteDependencies(const std::set<std::string>& sources,
+                                 const std::string&           obj,
                                  std::ostream& makeDepends,
                                  std::ostream& internalDepends);
 

+ 29 - 23
Source/cmDependsFortran.cxx

@@ -170,44 +170,50 @@ cmDependsFortran::~cmDependsFortran()
 }
 
 //----------------------------------------------------------------------------
-bool cmDependsFortran::WriteDependencies(const char *src, const char *obj,
-                                         std::ostream&, std::ostream&)
+bool cmDependsFortran::WriteDependencies(
+    const std::set<std::string>& sources, const std::string& obj,
+    std::ostream&, std::ostream&)
 {
   // Make sure this is a scanning instance.
-  if(!src || src[0] == '\0')
+  if(sources.empty() || sources.begin()->empty())
     {
-    cmSystemTools::Error("Cannot scan dependencies without an source file.");
+    cmSystemTools::Error("Cannot scan dependencies without a source file.");
     return false;
     }
-  if(!obj || obj[0] == '\0')
+  if(obj.empty())
     {
     cmSystemTools::Error("Cannot scan dependencies without an object file.");
     return false;
     }
 
-  // Get the information object for this source.
-  cmDependsFortranSourceInfo& info =
-    this->Internal->CreateObjectInfo(obj, src);
+  bool okay = true;
+  for(std::set<std::string>::const_iterator it = sources.begin();
+      it != sources.end(); ++it)
+    {
+    const std::string& src = *it;
+    // Get the information object for this source.
+    cmDependsFortranSourceInfo& info =
+      this->Internal->CreateObjectInfo(obj.c_str(), src.c_str());
 
-  // Make a copy of the macros defined via ADD_DEFINITIONS
-  std::set<std::string> ppDefines(this->PPDefinitions.begin(),
-                                  this->PPDefinitions.end());
+    // Make a copy of the macros defined via ADD_DEFINITIONS
+    std::set<std::string> ppDefines(this->PPDefinitions.begin(),
+                                    this->PPDefinitions.end());
 
-  // Create the parser object. The constructor takes ppMacro and info per
-  // reference, so we may look into the resulting objects later.
-  cmDependsFortranParser parser(this, ppDefines, info);
+    // Create the parser object. The constructor takes ppMacro and info per
+    // reference, so we may look into the resulting objects later.
+    cmDependsFortranParser parser(this, ppDefines, info);
 
-  // Push on the starting file.
-  cmDependsFortranParser_FilePush(&parser, src);
+    // Push on the starting file.
+    cmDependsFortranParser_FilePush(&parser, src.c_str());
 
-  // Parse the translation unit.
-  if(cmDependsFortran_yyparse(parser.Scanner) != 0)
-    {
-    // Failed to parse the file.  Report failure to write dependencies.
-    return false;
+    // Parse the translation unit.
+    if(cmDependsFortran_yyparse(parser.Scanner) != 0)
+      {
+      // Failed to parse the file.  Report failure to write dependencies.
+      okay = false;
+      }
     }
-
-  return true;
+  return okay;
 }
 
 //----------------------------------------------------------------------------

+ 1 - 1
Source/cmDependsFortran.h

@@ -66,7 +66,7 @@ protected:
 
   // Implement writing/checking methods required by superclass.
   virtual bool WriteDependencies(
-    const char *src, const char *file,
+    const std::set<std::string>& sources, const std::string& file,
     std::ostream& makeDepends, std::ostream& internalDepends);
 
   // Actually write the depenencies to the streams.

+ 3 - 3
Source/cmDependsJava.cxx

@@ -25,11 +25,11 @@ cmDependsJava::~cmDependsJava()
 }
 
 //----------------------------------------------------------------------------
-bool cmDependsJava::WriteDependencies(const char *src, const char *,
-  std::ostream&, std::ostream&)
+bool cmDependsJava::WriteDependencies(const std::set<std::string>& sources,
+    const std::string&, std::ostream&, std::ostream&)
 {
   // Make sure this is a scanning instance.
-  if(!src || src[0] == '\0')
+  if(sources.empty() || sources.begin()->empty())
     {
     cmSystemTools::Error("Cannot scan dependencies without an source file.");
     return false;

+ 2 - 1
Source/cmDependsJava.h

@@ -29,7 +29,8 @@ public:
 
 protected:
   // Implement writing/checking methods required by superclass.
-  virtual bool WriteDependencies(const char *src, const char *file,
+  virtual bool WriteDependencies(
+    const std::set<std::string>& sources, const std::string& file,
     std::ostream& makeDepends, std::ostream& internalDepends);
   virtual bool CheckDependencies(std::istream& internalDepends,
                                  const char* internalDependsFileName,