瀏覽代碼

ENH: reduce the number of files produced still needs a bit more cleanup

Ken Martin 20 年之前
父節點
當前提交
f85f919dbc

+ 13 - 65
Source/cmDepends.cxx

@@ -32,55 +32,14 @@ cmDepends::~cmDepends()
 {
 }
 
-void cmDepends::SetTargetFile(const char* dir, const char* targetFile, 
-                              const char *markExt, const char *makeExt)
-{
-  m_Directory = dir;
-  m_TargetFile = targetFile;
-  
-  // Construct the path to the make and mark files.  Append
-  // appropriate extensions to their names.
-  m_DependsMarkFile = dir;
-  m_DependsMakeFile = dir;
-  m_DependsMakeFile += "/";
-  m_DependsMarkFile += "/";
-  m_DependsMakeFile += m_TargetFile;
-  m_DependsMarkFile += m_TargetFile;
-  m_DependsMakeFile += makeExt;
-  m_DependsMarkFile += markExt;
-
-  if (!m_CompileDirectory.size())
-    {
-    m_CompileDirectory = dir;
-    }
-}
-
-
 //----------------------------------------------------------------------------
-bool cmDepends::Write()
+bool cmDepends::Write(const char *src, const char *obj, std::ostream &fout)
 {
-  // Dependency generation must always be done in the current working
-  // directory.
-  assert(m_Directory == ".");
-
-  // Try to generate dependencies for the target file.
-  cmGeneratedFileStream fout(m_DependsMakeFile.c_str());
-  fout << "# Dependencies for " << m_TargetFile.c_str() << std::endl;
-  if(this->WriteDependencies(fout) && fout)
-    {
-    // Dependencies were generated.  Touch the mark file.
-    std::ofstream fmark(m_DependsMarkFile.c_str());
-    fmark << "Dependencies updated for " << m_TargetFile.c_str() << std::endl;
-    return true;
-    }
-  else
-    {
-    return false;
-    }
+  return this->WriteDependencies(src, obj, fout);
 }
 
 //----------------------------------------------------------------------------
-void cmDepends::Check()
+void cmDepends::Check(const char *file)
 {
   // Dependency checks must be done in proper working directory.
   std::string oldcwd = ".";
@@ -93,11 +52,11 @@ void cmDepends::Check()
     }
 
   // Check whether dependencies must be regenerated.
-  std::ifstream fin(m_DependsMakeFile.c_str());
+  std::ifstream fin(file);
   if(!(fin && this->CheckDependencies(fin)))
     {
     // Clear all dependencies so they will be regenerated.
-    this->Clear();
+    this->Clear(file);
     }
 
   // Restore working directory.
@@ -108,37 +67,26 @@ void cmDepends::Check()
 }
 
 //----------------------------------------------------------------------------
-void cmDepends::Clear()
+void cmDepends::Clear(const char *file)
 {
   // Print verbose output.
   if(m_Verbose)
     {
     cmOStringStream msg;
-    msg << "Clearing dependencies for \"" << m_TargetFile << "\"." << std::endl;
+    msg << "Clearing dependencies in \"" << file << "\"." << std::endl;
     cmSystemTools::Stdout(msg.str().c_str());
     }
 
   // Remove the dependency mark file to be sure dependencies will be
   // regenerated.
-  cmSystemTools::RemoveFile(m_DependsMarkFile.c_str());
-
+  std::string markFile = file;
+  markFile += ".mark";
+  cmSystemTools::RemoveFile(markFile.c_str());
+  
   // Write an empty dependency file.
-  cmGeneratedFileStream depFileStream(m_DependsMakeFile.c_str());
+  cmGeneratedFileStream depFileStream(file);
   depFileStream
-    << "# Empty dependencies file for " << m_TargetFile.c_str() << ".\n"
+    << "# Empty dependencies file\n"
     << "# This may be replaced when dependencies are built." << std::endl;
 }
 
-//----------------------------------------------------------------------------
-const char* cmDepends::GetMakeFileName()
-{
-  // Skip over the directory part of the name.
-  return m_DependsMakeFile.c_str() + m_Directory.length() + 1;
-}
-
-//----------------------------------------------------------------------------
-const char* cmDepends::GetMarkFileName()
-{
-  // Skip over the directory part of the name.
-  return m_DependsMarkFile.c_str() + m_Directory.length() + 1;
-}

+ 7 - 25
Source/cmDepends.h

@@ -33,10 +33,6 @@ public:
       path from the build directory to the target file.  */
   cmDepends();
   
-  /** set the name directory and extensions of the target file to scan */
-  void SetTargetFile(const char* dir, const char* targetFile, 
-                     const char *markExt, const char *makeExt);
-
   /** at what level will the compile be done from */
   void SetCompileDirectory(const char *dir) {m_CompileDirectory = dir;};
     
@@ -47,44 +43,30 @@ public:
   virtual ~cmDepends();
 
   /** Write dependencies for the target file.  */
-  bool Write();
-
+  bool Write(const char *src, const char *obj, std::ostream &os);
+  
   /** Check dependencies for the target file.  */
-  void Check();
+  void Check(const char *file);
 
   /** Clear dependencies for the target file so they will be regenerated.  */
-  void Clear();
-
-  /** Get the name of the dependency make file.  */
-  const char* GetMakeFileName();
-
-  /** Get the name of the dependency mark file.  */
-  const char* GetMarkFileName();
+  void Clear(const char *file);
 
 protected:
 
   // Write dependencies for the target file to the given stream.
   // Return true for success and false for failure.
-  virtual bool WriteDependencies(std::ostream& os)=0;
+  virtual bool WriteDependencies(const char *src, 
+                                 const char* obj, std::ostream& os)=0;
 
   // Check dependencies for the target file in the given stream.
   // Return false if dependencies must be regenerated and true
   // otherwise.
-  virtual bool CheckDependencies(std::istream& is)=0;
+  virtual bool CheckDependencies(std::istream& is) = 0;
 
   // The directory in which the build rule for the target file is executed.
   std::string m_Directory;
   std::string m_CompileDirectory;
 
-  // The name of the target file for which dependencies are maintained.
-  std::string m_TargetFile;
-
-  // The name of the .depends.make file corresponding to the target.
-  std::string m_DependsMakeFile;
-
-  // The name of the .depends file marking when dependencies were generated.
-  std::string m_DependsMarkFile;
-
   // Flag for verbose output.
   bool m_Verbose;
 

+ 18 - 10
Source/cmDependsC.cxx

@@ -27,10 +27,8 @@ cmDependsC::cmDependsC()
 
 //----------------------------------------------------------------------------
 // yummy look at all those constructor arguments
-cmDependsC::cmDependsC(const char* sourceFile,
-                       std::vector<std::string> const& includes,
+cmDependsC::cmDependsC(std::vector<std::string> const& includes,
                        const char* scanRegex, const char* complainRegex):
-  m_SourceFile(sourceFile),
   m_IncludePath(&includes),
   m_IncludeRegexLine("^[ \t]*#[ \t]*include[ \t]*[<\"]([^\">]+)([\">])"),
   m_IncludeRegexScan(scanRegex),
@@ -44,12 +42,18 @@ cmDependsC::~cmDependsC()
 }
 
 //----------------------------------------------------------------------------
-bool cmDependsC::WriteDependencies(std::ostream& os)
+bool cmDependsC::WriteDependencies(const char *src, 
+                                   const char *obj, std::ostream& os)
 {
   // Make sure this is a scanning instance.
-  if(m_SourceFile == "")
+  if(!src || src[0] == '\0')
     {
-    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')
+    {
+    cmSystemTools::Error("Cannot scan dependencies without an object file.");
     return false;
     }
   if(!m_IncludePath)
@@ -61,10 +65,10 @@ bool cmDependsC::WriteDependencies(std::ostream& os)
   // Walk the dependency graph starting with the source file.
   bool first = true;
   UnscannedEntry root;
-  root.FileName = m_SourceFile;
+  root.FileName = src;
   m_Unscanned.push(root);
   m_Encountered.clear();
-  m_Encountered.insert(m_SourceFile);
+  m_Encountered.insert(src);
   std::set<cmStdString> dependencies;
   std::set<cmStdString> scanned;
   while(!m_Unscanned.empty())
@@ -155,7 +159,7 @@ bool cmDependsC::WriteDependencies(std::ostream& os)
   for(std::set<cmStdString>::iterator i=dependencies.begin();
       i != dependencies.end(); ++i)
     {
-    os << m_TargetFile.c_str() << ": "
+    os << obj << ": "
        << cmSystemTools::ConvertToOutputPath(i->c_str()).c_str()
        << std::endl;
     }
@@ -313,8 +317,12 @@ const char* cmDependsC::ParseFileName(const char* in, std::string& name)
   bool quoted = false;
   char* buf = new char[strlen(in)+1];
   char* pos = buf;
+  
+  // for every character while we haven't hit the end of the string AND we
+  // are in a quoted string OR the current character isn't a : or the second
+  // character AND it isn't a space
   for(;*c && (quoted ||
-              ((*c != ':' || pos > buf+1) && !isspace(*c))); ++c)
+              ((*c != ':' || pos > buf) && !isspace(*c))); ++c)
     {
     if(*c == '"')
       {

+ 5 - 14
Source/cmDependsC.h

@@ -30,22 +30,16 @@ public:
   /** Checking instances need to know the build directory name and the
       relative path from the build directory to the target file.  */
   cmDependsC();
-
-  /** Scanning need to know the build directory name, the relative
-      path from the build directory to the target file, the source
-      file from which to start scanning, and the include file search
-      path.  It also uses the include file regular expressions.  
-      This is a good example of why constructors should not take arguments.
-  */
-  cmDependsC(const char* sourceFile, std::vector<std::string> const& includes,
+  cmDependsC(std::vector<std::string> const& includes,
              const char* scanRegex, const char* complainRegex);
 
   /** Virtual destructor to cleanup subclasses properly.  */
   virtual ~cmDependsC();
-
+  
 protected:
   // Implement writing/checking methods required by superclass.
-  virtual bool WriteDependencies(std::ostream& os);
+  virtual bool WriteDependencies(const char *src, 
+                                 const char *file, std::ostream& os);
   virtual bool CheckDependencies(std::istream& is);
 
   // Method to scan a single file.
@@ -56,9 +50,6 @@ protected:
                        std::string& dependee);
   const char* ParseFileName(const char* in, std::string& name);
 
-  // The source file from which to start scanning.
-  std::string m_SourceFile;
-
   // The include file search path.
   std::vector<std::string> const* m_IncludePath;
 
@@ -69,7 +60,7 @@ protected:
   // recursively and which to complain about not finding.
   cmsys::RegularExpression m_IncludeRegexScan;
   cmsys::RegularExpression m_IncludeRegexComplain;
-
+  
   // Data structures for dependency graph walk.
   struct UnscannedEntry
   {

+ 15 - 40
Source/cmDependsFortran.cxx

@@ -77,15 +77,12 @@ struct cmDependsFortranParser_s
 
 //----------------------------------------------------------------------------
 cmDependsFortran::cmDependsFortran():
-  m_SourceFile(),
   m_IncludePath(0)
 {
 }
 
 //----------------------------------------------------------------------------
-cmDependsFortran::cmDependsFortran(const char* sourceFile,
-                                   std::vector<std::string> const& includes):
-  m_SourceFile(sourceFile),
+cmDependsFortran::cmDependsFortran(std::vector<std::string> const& includes):
   m_IncludePath(&includes)
 {
 }
@@ -96,14 +93,20 @@ cmDependsFortran::~cmDependsFortran()
 }
 
 //----------------------------------------------------------------------------
-bool cmDependsFortran::WriteDependencies(std::ostream& os)
+bool cmDependsFortran::WriteDependencies(const char *src,
+                                         const char *obj, std::ostream& os)
 {
   // Make sure this is a scanning instance.
-  if(m_SourceFile == "")
+  if(!src || src[0] == '\0')
     {
     cmSystemTools::Error("Cannot scan dependencies without an source file.");
     return false;
     }
+  if(!obj || obj[0] == '\0')
+    {
+    cmSystemTools::Error("Cannot scan dependencies without an object file.");
+    return false;
+    }
   if(!m_IncludePath)
     {
     cmSystemTools::Error("Cannot scan dependencies without an include path.");
@@ -114,7 +117,7 @@ bool cmDependsFortran::WriteDependencies(std::ostream& os)
   cmDependsFortranParser parser(this);
 
   // Push on the starting file.
-  cmDependsFortranParser_FilePush(&parser, m_SourceFile.c_str());
+  cmDependsFortranParser_FilePush(&parser, src);
 
   // Parse the translation unit.
   if(cmDependsFortran_yyparse(parser.Scanner) != 0)
@@ -127,7 +130,7 @@ bool cmDependsFortran::WriteDependencies(std::ostream& os)
   for(std::set<cmStdString>::const_iterator i = parser.Includes.begin();
       i != parser.Includes.end(); ++i)
     {
-    os << m_TargetFile.c_str() << ": "
+    os << obj << ": "
        << cmSystemTools::ConvertToOutputPath(i->c_str()).c_str()
        << std::endl;
     }
@@ -141,25 +144,8 @@ bool cmDependsFortran::WriteDependencies(std::ostream& os)
     if(parser.Provides.find(*i) == parser.Provides.end())
       {
       // since we require some things add them to our list of requirements
-      os << m_TargetFile.c_str() << ".requires: " << i->c_str() << ".mod.proxy"
+      os << obj << ".requires: " << i->c_str() << ".mod.proxy"
          << std::endl;
-#if 0
-      // Always use lower case for the mod stamp file name.
-      std::string m = cmSystemTools::LowerCase(*i);
-      os << m_TargetFile.c_str() << ": " << m.c_str() << ".mod.stamp"
-         << std::endl;
-      os << i->c_str() << ".mod.proxy:" << std::endl;
-      std::string stampName = m_Directory;
-      stampName += "/";
-      stampName += m;
-      stampName += ".mod.stamp";
-      if(!cmSystemTools::FileExists(stampName.c_str()))
-        {
-        std::ofstream stamp(stampName.c_str());
-        stamp << "# Dummy stamp file in case nothing provides it."
-              << std::endl;
-        }
-#endif
       }
     }
 
@@ -167,14 +153,14 @@ bool cmDependsFortran::WriteDependencies(std::ostream& os)
   for(std::set<cmStdString>::const_iterator i = parser.Provides.begin();
       i != parser.Provides.end(); ++i)
     {
-    os << i->c_str() << ".mod.proxy: " << m_TargetFile.c_str()
+    os << i->c_str() << ".mod.proxy: " << obj
        << ".provides" << std::endl;
     }
   
   // If any modules are provided then they must be converted to stamp files.
   if(!parser.Provides.empty())
     {
-    os << m_TargetFile.c_str() << ".provides.build:\n";
+    os << obj << ".provides.build:\n";
     for(std::set<cmStdString>::const_iterator i = parser.Provides.begin();
         i != parser.Provides.end(); ++i)
       {
@@ -185,20 +171,9 @@ bool cmDependsFortran::WriteDependencies(std::ostream& os)
       os << "\t$(CMAKE_COMMAND) -E cmake_copy_f90_mod "
          << i->c_str() << " " << m.c_str() << ".mod.stamp\n";
       }
-    os << "\t@touch " << m_TargetFile.c_str() << ".provides.build\n";
+    os << "\t@touch " << obj << ".provides.build\n";
     }
 
-#if 0
-  // if it provides something then connect the requires rule to the build rule
-  if(!parser.Provides.empty())
-    {
-    os << m_TargetFile.c_str() << ".requires: " << m_TargetFile.c_str()
-       << ".requires.build" << std::endl;
-    // provide empty build rule for old gen for now, TODO remove later
-    os << m_TargetFile.c_str() << ".requires.build:" << std::endl;    
-    }
-#endif
-  
   /*
   // TODO:
   What about .mod files provided in another directory and found with a

+ 3 - 2
Source/cmDependsFortran.h

@@ -33,7 +33,7 @@ public:
       path from the build directory to the target file, the source
       file from which to start scanning, and the include file search
       path.  */
-  cmDependsFortran(const char* sourceFile, std::vector<std::string> const& includes);
+  cmDependsFortran(std::vector<std::string> const& includes);
 
   /** Virtual destructor to cleanup subclasses properly.  */
   virtual ~cmDependsFortran();
@@ -51,7 +51,8 @@ public:
 
 protected:
   // Implement writing/checking methods required by superclass.
-  virtual bool WriteDependencies(std::ostream& os);
+  virtual bool WriteDependencies(const char *src,
+                                 const char *file, std::ostream& os);
   virtual bool CheckDependencies(std::istream& is);
 
   // The source file from which to start scanning.

+ 4 - 10
Source/cmDependsJava.cxx

@@ -20,14 +20,7 @@
 #include "cmSystemTools.h"
 
 //----------------------------------------------------------------------------
-cmDependsJava::cmDependsJava():
-  m_SourceFile()
-{
-}
-
-//----------------------------------------------------------------------------
-cmDependsJava::cmDependsJava(const char* sourceFile):
-  m_SourceFile(sourceFile)
+cmDependsJava::cmDependsJava()
 {
 }
 
@@ -37,10 +30,11 @@ cmDependsJava::~cmDependsJava()
 }
 
 //----------------------------------------------------------------------------
-bool cmDependsJava::WriteDependencies(std::ostream&)
+bool cmDependsJava::WriteDependencies(const char *src, 
+                                      const char *file, std::ostream&)
 {
   // Make sure this is a scanning instance.
-  if(m_SourceFile == "")
+  if(!src || src[0] == '\0')
     {
     cmSystemTools::Error("Cannot scan dependencies without an source file.");
     return false;

+ 2 - 9
Source/cmDependsJava.h

@@ -29,22 +29,15 @@ public:
       relative path from the build directory to the target file.  */
   cmDependsJava();
 
-  /** Scanning need to know the build directory name, the relative
-      path from the build directory to the target file and the source
-      file to scan.  */
-  cmDependsJava(const char* sourceFile);
-
   /** Virtual destructor to cleanup subclasses properly.  */
   virtual ~cmDependsJava();
 
 protected:
   // Implement writing/checking methods required by superclass.
-  virtual bool WriteDependencies(std::ostream& os);
+  virtual bool WriteDependencies(const char *src,
+                                 const char *file, std::ostream& os);
   virtual bool CheckDependencies(std::istream& is);
 
-  // The source file from which to start scanning.
-  std::string m_SourceFile;
-
 private:
   cmDependsJava(cmDependsJava const&); // Purposely not implemented.
   void operator=(cmDependsJava const&); // Purposely not implemented.

+ 19 - 52
Source/cmGlobalUnixMakefileGenerator3.cxx

@@ -328,67 +328,34 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile()
     }
   cmakefileStream << "  )\n\n";
 
-  this->WriteMainCMakefileLanguageRules(cmakefileStream);
+  this->WriteMainCMakefileLanguageRules(cmakefileStream, m_LocalGenerators);
 }
   
 void cmGlobalUnixMakefileGenerator3
-::WriteMainCMakefileLanguageRules(cmGeneratedFileStream& cmakefileStream)
+::WriteMainCMakefileLanguageRules(cmGeneratedFileStream& cmakefileStream,
+                                  std::vector<cmLocalGenerator *> &lGenerators)
 {
   cmLocalUnixMakefileGenerator3 *lg;
 
-  // now write all the language stuff
-  // Set the set of files to check for dependency integrity.
-  // loop over all of the local generators to collect this
-  std::set<cmStdString> checkSetLangs;
-  for (unsigned int i = 0; i < m_LocalGenerators.size(); ++i)
-    {
-    lg = static_cast<cmLocalUnixMakefileGenerator3 *>(m_LocalGenerators[i]);
-    std::map<cmStdString,cmLocalUnixMakefileGenerator3::IntegrityCheckSet>& checkSet = 
-      lg->GetIntegrityCheckSet();
-    for(std::map<cmStdString, 
-          cmLocalUnixMakefileGenerator3::IntegrityCheckSet>::const_iterator
-          l = checkSet.begin(); l != checkSet.end(); ++l)
-      {
-      checkSetLangs.insert(l->first);
-      }
-    }
-  
-  // list the languages
+  // now list all the target info files
   cmakefileStream
     << "# The set of files whose dependency integrity should be checked:\n";
   cmakefileStream
-    << "SET(CMAKE_DEPENDS_LANGUAGES\n";
-  for(std::set<cmStdString>::iterator
-        l = checkSetLangs.begin(); l != checkSetLangs.end(); ++l)
+    << "SET(CMAKE_DEPEND_INFO_FILES\n";
+  for (unsigned int i = 0; i < lGenerators.size(); ++i)
     {
-    cmakefileStream << "  \"" << l->c_str() << "\"\n";
-    }
-  cmakefileStream << "  )\n";
-  
-  // now list the files for each language
-  for(std::set<cmStdString>::iterator
-        l = checkSetLangs.begin(); l != checkSetLangs.end(); ++l)
-    {
-    cmakefileStream
-      << "SET(CMAKE_DEPENDS_CHECK_" << l->c_str() << "\n";
-    // now for each local gen get the checkset
-    for (unsigned int i = 0; i < m_LocalGenerators.size(); ++i)
+    lg = static_cast<cmLocalUnixMakefileGenerator3 *>(lGenerators[i]);
+    // for all of out targets
+    for (cmTargets::iterator l = lg->GetMakefile()->GetTargets().begin();
+         l != lg->GetMakefile()->GetTargets().end(); l++)
       {
-      lg = static_cast<cmLocalUnixMakefileGenerator3 *>(m_LocalGenerators[i]);
-      // get the check set for this local gen and language
-      cmLocalUnixMakefileGenerator3::IntegrityCheckSet iCheckSet = 
-        lg->GetIntegrityCheckSet()[*l];
-      // for each file
-      for(cmLocalUnixMakefileGenerator3::IntegrityCheckSet::const_iterator csIter = 
-            iCheckSet.begin();
-          csIter != iCheckSet.end(); ++csIter)
-        {
-        cmakefileStream << "  \"" << 
-          lg->Convert(csIter->c_str(),cmLocalGenerator::HOME_OUTPUT).c_str() << "\"\n";
-        }
+      std::string tname = lg->GetRelativeTargetDirectory(l->second);
+      tname += "/DependInfo.cmake";
+      cmSystemTools::ConvertToUnixSlashes(tname);
+      cmakefileStream << "  \"" << tname.c_str() << "\"\n";
       }
-    cmakefileStream << "  )\n";
     }
+  cmakefileStream << "  )\n";
 }
 
 //----------------------------------------------------------------------------
@@ -768,7 +735,6 @@ cmGlobalUnixMakefileGenerator3
 
   // for each target Generate the rule files for each target.
   cmTargets& targets = lg->GetMakefile()->GetTargets();
-  bool needRequiresStep = this->NeedRequiresStep(lg);
   for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t)
     {
     if (((t->second.GetType() == cmTarget::EXECUTABLE) ||
@@ -779,6 +745,8 @@ cmGlobalUnixMakefileGenerator3
         t->second.GetName() &&
         strlen(t->second.GetName()))  
       {
+      bool needRequiresStep = 
+        this->NeedRequiresStep(lg,t->second.GetName());
       // Add a rule to build the target by name.
       localName = lg->GetRelativeTargetDirectory(t->second);
       std::string makefileName = localName;
@@ -1006,10 +974,10 @@ cmGlobalUnixMakefileGenerator3::WriteHelpRule(std::ostream& ruleFileStream)
 
 
 bool cmGlobalUnixMakefileGenerator3
-::NeedRequiresStep(cmLocalUnixMakefileGenerator3 *lg)
+::NeedRequiresStep(cmLocalUnixMakefileGenerator3 *lg,const char *name)
 {
   std::map<cmStdString,cmLocalUnixMakefileGenerator3::IntegrityCheckSet>& 
-    checkSet = lg->GetIntegrityCheckSet();
+    checkSet = lg->GetIntegrityCheckSet()[name];
   for(std::map<cmStdString, 
         cmLocalUnixMakefileGenerator3::IntegrityCheckSet>::const_iterator
         l = checkSet.begin(); l != checkSet.end(); ++l)
@@ -1022,6 +990,5 @@ bool cmGlobalUnixMakefileGenerator3
       return true;
       }
     }
-  
   return false;
 }

+ 5 - 2
Source/cmGlobalUnixMakefileGenerator3.h

@@ -83,12 +83,15 @@ public:
    * requests that they Generate.  
    */
   virtual void Generate();
+  
+  
+  void WriteMainCMakefileLanguageRules(cmGeneratedFileStream& cmakefileStream,
+                                       std::vector<cmLocalGenerator *> &);
 
 protected:
   void WriteMainMakefile();
   void WriteMainMakefile2();
   void WriteMainCMakefile();
-  void WriteMainCMakefileLanguageRules(cmGeneratedFileStream& cmakefileStream);
   void WriteAllRules(cmLocalUnixMakefileGenerator3 *lg, 
                      std::ostream& makefileStream);
   void WriteHelpRule(std::ostream& ruleFileStream);
@@ -111,7 +114,7 @@ protected:
                              const char* name, std::set<cmStdString>& emitted);
 
   // does this generator need a requires step for any of its targets
-  bool NeedRequiresStep(cmLocalUnixMakefileGenerator3 *lg);
+  bool NeedRequiresStep(cmLocalUnixMakefileGenerator3 *lg, const char *);
 
 };
 

+ 13 - 7
Source/cmLocalGenerator.cxx

@@ -62,6 +62,17 @@ void cmLocalGenerator::Configure()
       }
     }  
   
+  this->SetupPathConversions();
+  
+  // Check whether relative paths should be used for optionally
+  // relative paths.
+  m_UseRelativePaths = m_Makefile->IsOn("CMAKE_USE_RELATIVE_PATHS");
+
+  this->Configured = true;
+}
+
+void cmLocalGenerator::SetupPathConversions()
+{  
   // Setup the current output directory components for use by
   // Convert
   std::string outdir; 
@@ -76,15 +87,10 @@ void cmLocalGenerator::Configure()
   cmSystemTools::SplitPath(outdir.c_str(), m_HomeOutputDirectoryComponents);
   outdir =
     cmSystemTools::CollapseFullPath(m_Makefile->GetStartOutputDirectory());
-  cmSystemTools::SplitPath(outdir.c_str(), m_StartOutputDirectoryComponents);
-
-  // Check whether relative paths should be used for optionally
-  // relative paths.
-  m_UseRelativePaths = m_Makefile->IsOn("CMAKE_USE_RELATIVE_PATHS");
-
-  this->Configured = true;
+cmSystemTools::SplitPath(outdir.c_str(), m_StartOutputDirectoryComponents);
 }
 
+
 void cmLocalGenerator::SetGlobalGenerator(cmGlobalGenerator *gg)
 {
   m_GlobalGenerator = gg;

+ 3 - 0
Source/cmLocalGenerator.h

@@ -97,6 +97,9 @@ public:
                       OutputFormat output = UNCHANGED,
                       bool optional = false);
   
+  ///! Call this prior to using Convert
+  void SetupPathConversions();
+  
   /**
    * Convert the given path to an output path that is optionally
    * relative based on the cache option CMAKE_USE_RELATIVE_PATHS.  The

+ 307 - 265
Source/cmLocalUnixMakefileGenerator3.cxx

@@ -18,7 +18,7 @@
 
 #include "cmDepends.h"
 #include "cmGeneratedFileStream.h"
-#include "cmGlobalGenerator.h"
+#include "cmGlobalUnixMakefileGenerator3.h"
 #include "cmMakefile.h"
 #include "cmSourceFile.h"
 #include "cmake.h"
@@ -174,23 +174,18 @@ void cmLocalUnixMakefileGenerator3
   // Generate the rule files for each custom command.
   // get the classes from the source lists then add them to the groups
   const std::vector<cmSourceFile*> &classes = target.GetSourceFiles();
-  std::string objTarget;
   for(std::vector<cmSourceFile*>::const_iterator i = classes.begin(); 
       i != classes.end(); i++)
     {
     if(cmCustomCommand* cc = (*i)->GetCustomCommand())
       {
       cc->Used();
-      objTarget = this->GenerateCustomRuleFile(*cc,tgtDir.c_str());
+      this->GenerateCustomRuleFile(*cc,tgtDir.c_str(),ruleFileStream);
       if (clean)
         {
         cleanFiles.push_back
           (this->Convert(cc->GetOutput(),HOME_OUTPUT,SHELL));
         }
-      ruleFileStream
-        << m_IncludeDirective << " "
-        << this->ConvertToOutputForExisting(objTarget.c_str()).c_str()
-        << "\n";
       }
     }
 }
@@ -309,6 +304,49 @@ cmLocalUnixMakefileGenerator3
   std::string dir = this->GetTargetDirectory(target);
   cmSystemTools::MakeDirectory(this->ConvertToFullPath(dir).c_str());
 
+  // Generate the build-time dependencies file for this target.
+  std::string depBase = dir;
+  depBase += "/";
+  depBase += target.GetName();
+
+  // Construct the rule file name.
+  std::string ruleFileName = dir;
+  ruleFileName += "/build.make";
+
+  // Open the rule file.  This should be copy-if-different because the
+  // rules may depend on this file itself.
+  std::string ruleFileNameFull = this->ConvertToFullPath(ruleFileName);
+  cmGeneratedFileStream ruleFileStream(ruleFileNameFull.c_str());
+  ruleFileStream.SetCopyIfDifferent(true);
+  if(!ruleFileStream)
+    {
+    return;
+    }
+  this->WriteDisclaimer(ruleFileStream);
+  
+  this->WriteMakeVariables(ruleFileStream, HOME_OUTPUT);
+  
+  // Include the dependencies for the target.
+  std::string depPath = dir;
+  depPath += "/depend.make";
+  depPath = this->ConvertToFullPath(depPath.c_str());
+  depPath = this->Convert(depPath.c_str(),HOME_OUTPUT,MAKEFILE);
+  ruleFileStream
+    << "# Include any dependencies generated for this target.\n"
+    << m_IncludeDirective << " "
+    << depPath
+    << "\n\n";
+  
+  // make sure the depend file exists
+  if (!cmSystemTools::FileExists(depPath.c_str()))
+    {
+    // Write an empty dependency file.
+    cmGeneratedFileStream depFileStream(depPath.c_str());
+    depFileStream
+      << "# Empty dependencies file for " << target.GetName() << ".\n"
+      << "# This may be replaced when dependencies are built." << std::endl;
+    }
+  
   // First generate the object rule files.  Save a list of all object
   // files for this target.
   std::vector<std::string> objects;
@@ -323,7 +361,8 @@ cmLocalUnixMakefileGenerator3
       if(!m_GlobalGenerator->IgnoreFile((*source)->GetSourceExtension().c_str()))
         {
         // Generate this object file's rule file.
-        this->WriteObjectRuleFiles(target, *(*source), objects);
+        this->WriteObjectRuleFiles(target, *(*source), objects, 
+                                   ruleFileStream);
         }
       else if((*source)->GetPropertyAsBool("EXTERNAL_OBJECT"))
         {
@@ -332,28 +371,6 @@ cmLocalUnixMakefileGenerator3
         }
       }
     }
-
-  // Generate the build-time dependencies file for this target.
-  std::string depBase = dir;
-  depBase += "/";
-  depBase += target.GetName();
-
-  // Construct the rule file name.
-  std::string ruleFileName = dir;
-  ruleFileName += "/build.make";
-
-  // Open the rule file.  This should be copy-if-different because the
-  // rules may depend on this file itself.
-  std::string ruleFileNameFull = this->ConvertToFullPath(ruleFileName);
-  cmGeneratedFileStream ruleFileStream(ruleFileNameFull.c_str());
-  ruleFileStream.SetCopyIfDifferent(true);
-  if(!ruleFileStream)
-    {
-    return;
-    }
-  this->WriteDisclaimer(ruleFileStream);
-
-  this->WriteMakeVariables(ruleFileStream, HOME_OUTPUT);
   
   // write the custom commands for this target
   std::vector<std::string> cleanFiles;
@@ -368,24 +385,6 @@ cmLocalUnixMakefileGenerator3
   // Include the rule file for each object.
   std::string relPath = this->GetHomeRelativeOutputPath();
   std::string objTarget;
-  if(!objects.empty())
-    {
-    ruleFileStream
-      << "# Include make rules for object files.\n";
-    for(std::vector<std::string>::const_iterator obj = objects.begin();
-        obj != objects.end(); ++obj)
-      {
-      objTarget = relPath;
-      objTarget += *obj;
-      objTarget += ".build.make";
-      ruleFileStream
-        << m_IncludeDirective << " "
-        << this->ConvertToOutputForExisting(objTarget.c_str()).c_str()
-        << "\n";
-      }
-    ruleFileStream
-      << "\n";
-    }
 
   // Write the rule for this target type.
   switch(target.GetType())
@@ -427,20 +426,10 @@ cmLocalUnixMakefileGenerator3
 ::WriteObjectDependRules(std::ostream& ruleFileStream,
                          std::string &obj,
                          const char * lang,
-                         const cmSourceFile& source,
+                         cmSourceFile& source,
                          std::vector<std::string>& depends,
                          std::string& depMakeFile)
 {
-  // Generate the build-time dependencies file for this object file.
-  std::string depMarkFile;
-  if(!this->GenerateDependsMakeFile(lang, obj.c_str(),
-                                    depMakeFile, depMarkFile))
-    {
-    cmSystemTools::Error("No dependency checker available for language \"",
-                         lang, "\".");
-    return;
-    }
-
   // Create the list of dependencies known at cmake time.  These are
   // shared between the object file and dependency scanning rule.
   depends.push_back(source.GetFullPath());
@@ -454,40 +443,6 @@ cmLocalUnixMakefileGenerator3
       depends.push_back(i->c_str());
       }
     }
-  
-  // Write the dependency generation rule.
-  std::string relativeObj = this->GetHomeRelativeOutputPath();
-  relativeObj += obj;
-  std::vector<std::string> commands;
-  std::string depEcho = "Scanning ";
-  depEcho += lang;
-  depEcho += " dependencies of ";
-  depEcho += this->Convert(relativeObj.c_str(),NONE,SHELL);
-  this->AppendEcho(commands, depEcho.c_str());
-  
-  // Add a command to call CMake to scan dependencies.  CMake will
-  // touch the corresponding depends file after scanning dependencies.
-  cmOStringStream depCmd;
-  // TODO: Account for source file properties and directory-level
-  // definitions when scanning for dependencies.
-  depCmd << "$(CMAKE_COMMAND) -E cmake_depends " 
-         << " \""
-         << m_GlobalGenerator->GetName() << "\" "
-         << this->Convert(m_Makefile->GetHomeOutputDirectory(),FULL,SHELL)
-         << " "
-         << this->Convert(m_Makefile->GetStartOutputDirectory(),FULL,SHELL)
-         << " "
-         << lang << " "
-         << relativeObj.c_str() << " "
-         << this->Convert(source.GetFullPath().c_str(),HOME_OUTPUT,SHELL);
-  commands.push_back(depCmd.str());
-  
-  // compute the target
-  std::string relPath = this->GetHomeRelativeOutputPath();
-  relPath += depMarkFile;
-  // Write the rule.
-  this->WriteMakeRule(ruleFileStream, 0,
-                      relPath.c_str(), depends, commands);
 }
 
 
@@ -497,24 +452,16 @@ cmLocalUnixMakefileGenerator3
 ::WriteObjectBuildFile(std::string &obj,
                        const char *lang, 
                        cmTarget& target, 
-                       const cmSourceFile& source,
+                       cmSourceFile& source,
                        std::vector<std::string>& depends,
-                       std::string &depMakeFile)
+                       std::string &depMakeFile,
+                       std::ostream &ruleFileStream)
 {
   // Open the rule file for writing.  This should be copy-if-different
   // because the rules may depend on this file itself.
-  std::string ruleFileName = obj;
-  ruleFileName += ".build.make";
+  std::string ruleFileName = this->GetTargetDirectory(target);
+  ruleFileName += "/build.make";
   std::string ruleFileNameFull = this->ConvertToFullPath(ruleFileName);
-  cmGeneratedFileStream ruleFileStream(ruleFileNameFull.c_str());
-  ruleFileStream.SetCopyIfDifferent(true);
-  if(!ruleFileStream)
-    {
-    return;
-    }
-  this->WriteDisclaimer(ruleFileStream);
-  ruleFileStream
-    << "# Rule file for object file " << obj.c_str() << ".\n\n";
 
   // generate the depend scanning rule
   this->WriteObjectDependRules(ruleFileStream, obj, lang, source, 
@@ -522,16 +469,6 @@ cmLocalUnixMakefileGenerator3
 
   this->AppendRuleDepend(depends, ruleFileNameFull.c_str());
 
-  // Include the dependencies for the target.
-  std::string depPath = this->GetHomeRelativeOutputPath();
-  depPath += depMakeFile;
-  depMakeFile = this->Convert(depPath.c_str(),HOME_OUTPUT,MAKEFILE);
-  ruleFileStream
-    << "# Include any dependencies generated for this rule.\n"
-    << m_IncludeDirective << " "
-    << depMakeFile
-    << "\n\n";
-
   // Write the build rule.
   // Build the set of compiler flags.
   std::string flags;
@@ -649,8 +586,9 @@ cmLocalUnixMakefileGenerator3
 //----------------------------------------------------------------------------
 void
 cmLocalUnixMakefileGenerator3
-::WriteObjectRuleFiles(cmTarget& target, const cmSourceFile& source,
-                       std::vector<std::string>& objects)
+::WriteObjectRuleFiles(cmTarget& target, cmSourceFile& source,
+                       std::vector<std::string>& objects, 
+                       std::ostream &ruleFileStream)
 {
   // Identify the language of the source file.
   const char* lang = this->GetSourceFileLanguage(source);
@@ -698,50 +636,25 @@ cmLocalUnixMakefileGenerator3
   std::string depMakeFile;
   
   // generate the build rule file
-  this->WriteObjectBuildFile(obj, lang, target, source, depends, depMakeFile);
+  this->WriteObjectBuildFile(obj, lang, target, source, depends, depMakeFile,
+                             ruleFileStream);
   
   // The object file should be checked for dependency integrity.
-  m_CheckDependFiles[lang].insert(relativeObj);
-
+  m_CheckDependFiles[target.GetName()][lang].insert(&source);
+     
   // add this to the list of objects for this local generator
   m_LocalObjectFiles[cmSystemTools::GetFilenameName(obj)].push_back(&target);
 }
 
 //----------------------------------------------------------------------------
-std::string 
+void
 cmLocalUnixMakefileGenerator3
-::GenerateCustomRuleFile(const cmCustomCommand& cc, const char *dir)
+::GenerateCustomRuleFile(const cmCustomCommand& cc, const char *dir,
+                         std::ostream &ruleFileStream)
 {
   // Convert the output name to a relative path if possible.
   std::string output = this->Convert(cc.GetOutput(),START_OUTPUT);
 
-  // Construct the name of the rule file by transforming the output
-  // name to a valid file name.  Since the output is already a file
-  // everything but the path characters is valid.
-  std::string customName = output;
-  cmSystemTools::ReplaceString(customName, "../", "___");
-  cmSystemTools::ReplaceString(customName, "/", "_");
-  cmSystemTools::ReplaceString(customName, ":", "_");
-  std::string ruleFileName = dir;
-  ruleFileName += "/";
-  ruleFileName += customName;
-  ruleFileName += ".build.make";
-
-  // what is the relative path to the rule file
-  std::string relRuleFile = this->Convert(ruleFileName.c_str(),HOME_OUTPUT);
-  
-  // Open the rule file.  This should be copy-if-different because the
-  // rules may depend on this file itself.
-  cmGeneratedFileStream ruleFileStream(ruleFileName.c_str());
-  ruleFileStream.SetCopyIfDifferent(true);
-  if(!ruleFileStream)
-    {
-    return relRuleFile;
-    }
-  this->WriteDisclaimer(ruleFileStream);
-  ruleFileStream
-    << "# Custom command rule file for " << output.c_str() << ".\n\n";
-
   // Collect the commands.
   std::vector<std::string> commands;
   std::string preEcho = "Generating ";
@@ -753,9 +666,6 @@ cmLocalUnixMakefileGenerator3
   std::vector<std::string> depends;
   this->AppendCustomDepend(depends, cc);
 
-  // Add a dependency on the rule file itself.
-  this->AppendRuleDepend(depends, relRuleFile.c_str());
-
   // Write the rule.
   const char* comment = 0;
   if(cc.GetComment() && *cc.GetComment())
@@ -764,8 +674,6 @@ cmLocalUnixMakefileGenerator3
     }
   this->WriteMakeRule(ruleFileStream, comment,
                       cc.GetOutput(), depends, commands);
-
-  return relRuleFile;
 }
 
 //----------------------------------------------------------------------------
@@ -850,19 +758,17 @@ cmLocalUnixMakefileGenerator3
 {
   // Construct a checker for the given language.
   std::auto_ptr<cmDepends>
-    checker(this->GetDependsChecker(lang,
-                                    m_Makefile->GetStartOutputDirectory(),
-                                    objFile, false));
+    checker(this->GetDependsChecker(lang,false));
   if(checker.get())
     {
-    // Save the make and mark file names.
-    depMakeFile = checker->GetMakeFileName();
-    depMarkFile = checker->GetMarkFileName();
-
     // Check the dependencies. Ths is required because we need at least an
     // empty foo.obj.depends.make for make to include, so at cmake time the
     // ::Check() method will generate that if it does not exist
-    checker->Check();
+
+    
+    // Todo: could just make sure that file exists, 
+    // use different method not check
+    checker->Check(objFile);
     
     return true;
     }
@@ -1885,13 +1791,62 @@ cmLocalUnixMakefileGenerator3
                         cmTarget& target,
                         const std::vector<std::string>& objects)
 {
+  // must write the targets depend info file
+  std::string dir = this->GetTargetDirectory(target);
+  std::string infoFileName = dir;
+  infoFileName += "/DependInfo.cmake";
+  std::string ruleFileNameFull = this->ConvertToFullPath(infoFileName);
+  cmGeneratedFileStream infoFileStream(ruleFileNameFull.c_str());
+  infoFileStream.SetCopyIfDifferent(true);
+  if(!infoFileStream)
+    {
+    return;
+    }
+  cmGlobalUnixMakefileGenerator3 *gg = 
+    static_cast<cmGlobalUnixMakefileGenerator3 *>(m_GlobalGenerator);
+  this->WriteDependLanguageInfo(infoFileStream,target);
+  
+  // and now write the rule to use it
   std::vector<std::string> depends;
-  std::vector<std::string> no_commands;
+  std::vector<std::string> commands;
 
   // Construct the name of the dependency generation target.
   std::string depTarget = this->GetRelativeTargetDirectory(target);
   depTarget += "/depend";
+  
+  std::string depMark = depTarget;
+  depMark += ".make.mark";
+  depends.push_back(depMark);
+  
+  this->WriteMakeRule(ruleFileStream, 0,
+                      depTarget.c_str(), depends, commands);
+  depends.clear();
+  
+  // Write the dependency generation rule.
+  std::string depEcho = "Scanning dependencies of target ";
+  depEcho += target.GetName();
+  this->AppendEcho(commands, depEcho.c_str());
+  
+  // Add a command to call CMake to scan dependencies.  CMake will
+  // touch the corresponding depends file after scanning dependencies.
+  cmOStringStream depCmd;
+  // TODO: Account for source file properties and directory-level
+  // definitions when scanning for dependencies.
+  depCmd << "$(CMAKE_COMMAND) -E cmake_depends " 
+         << " \""
+         << m_GlobalGenerator->GetName() << "\" "
+         << this->Convert(m_Makefile->GetHomeOutputDirectory(),FULL,SHELL)
+         << " "
+         << this->Convert(m_Makefile->GetStartOutputDirectory(),FULL,SHELL)
+         << " "
+         << this->Convert(ruleFileNameFull.c_str(),FULL,SHELL);
+  commands.push_back(depCmd.str());
+  
+  // Write the rule.
+  this->WriteMakeRule(ruleFileStream, 0,
+                      depMark.c_str(), depends, commands);
 
+#if 0
   // This target drives dependency generation for all object files.
   std::string relPath = this->GetHomeRelativeOutputPath();
   std::string objTarget;
@@ -1903,10 +1858,7 @@ cmLocalUnixMakefileGenerator3
     objTarget += ".depend";
     depends.push_back(objTarget);
     }
-
-  // Write the rule.
-  this->WriteMakeRule(ruleFileStream, 0,
-                      depTarget.c_str(), depends, no_commands);
+#endif
 }
 
 //----------------------------------------------------------------------------
@@ -2632,8 +2584,6 @@ cmLocalUnixMakefileGenerator3
 //----------------------------------------------------------------------------
 cmDepends*
 cmLocalUnixMakefileGenerator3::GetDependsChecker(const std::string& lang,
-                                                 const char* dir,
-                                                 const char* objFile,
                                                  bool verbose)
 {
   cmDepends *ret = 0;
@@ -2653,8 +2603,6 @@ cmLocalUnixMakefileGenerator3::GetDependsChecker(const std::string& lang,
 #endif
   if (ret)
     {
-    ret->SetTargetFile(dir, objFile, ".depend",".build.depend.make");
-    ret->SetCompileDirectory(m_Makefile->GetHomeOutputDirectory());
     ret->SetVerbose(verbose);
     }
   return ret;
@@ -2666,17 +2614,11 @@ cmLocalUnixMakefileGenerator3
 ::ScanDependencies(std::vector<std::string> const& args)
 {
   // Format of arguments is:
-  // $(CMAKE_COMMAND), cmake_depends, home_output_dir, start_output_dir, GeneratorName, <lang>, <obj>, <src>
+  // $(CMAKE_COMMAND), cmake_depends, GeneratorName, home_output_dir, start_output_dir, info file
   // The caller has ensured that all required arguments exist.
 
-  // The language for which we are scanning dependencies.
-  std::string const& lang = args[5];
-
-  // The file to which to write dependencies.
-  const char* objFile = args[6].c_str();
-
-  // The source file at which to start the scan.
-  const char* srcFile = args[7].c_str();
+  // The info file for this target
+  std::string const& infoFile = args[5];
 
   // Read the directory information file.
   cmake cm;
@@ -2686,7 +2628,9 @@ cmLocalUnixMakefileGenerator3
   lg->SetGlobalGenerator(&gg);
   cmMakefile* mf = lg->GetMakefile();
   mf->SetHomeOutputDirectory(args[3].c_str());
-  mf->SetStartOutputDirectory(args[4].c_str());  
+  mf->SetStartOutputDirectory(args[4].c_str());
+  lg->SetupPathConversions();
+  
   bool haveDirectoryInfo = false;
   std::string dirInfoFile = args[4];
   dirInfoFile += "/CMakeDirectoryInformation.cmake";
@@ -2696,6 +2640,13 @@ cmLocalUnixMakefileGenerator3
     haveDirectoryInfo = true;
     }
   
+  // read in the target info file
+  if(!mf->ReadListFile(0, infoFile.c_str()) ||
+     cmSystemTools::GetErrorOccuredFlag())
+    {
+    cmSystemTools::Error("Target DependInfo.cmake file not found");    
+    }
+  
   // Test whether we need to force Unix paths.
   if(haveDirectoryInfo)
     {
@@ -2711,66 +2662,116 @@ cmLocalUnixMakefileGenerator3
     {
     cmSystemTools::Error("Directory Information file not found");
     }
-  
 
-  // Get the set of include directories.
-  std::vector<std::string> includes;
-  if(haveDirectoryInfo)
+  // create the file stream for the depends file
+  std::string dir = cmSystemTools::GetFilenamePath(infoFile);
+  dir += "/depend.make";
+  
+  // Open the rule file.  This should be copy-if-different because the
+  // rules may depend on this file itself.
+  std::string ruleFileNameFull = dir;
+  cmGeneratedFileStream ruleFileStream(ruleFileNameFull.c_str());
+  ruleFileStream.SetCopyIfDifferent(true);
+  if(!ruleFileStream)
     {
-    std::string includePathVar = "CMAKE_";
-    includePathVar += lang;
-    includePathVar += "_INCLUDE_PATH";
-    if(const char* includePath = mf->GetDefinition(includePathVar.c_str()))
+    return false;
+    }
+  this->WriteDisclaimer(ruleFileStream);
+  
+  // for each language we need to scan, scan it 
+  const char *langStr = mf->GetSafeDefinition("CMAKE_DEPENDS_LANGUAGES");
+  std::vector<std::string> langs;
+  cmSystemTools::ExpandListArgument(langStr, langs);
+  for (std::vector<std::string>::iterator li = 
+         langs.begin(); li != langs.end(); ++li)
+    {
+    // construct the checker
+    std::string lang = li->c_str();
+    
+    // Get the set of include directories.
+    std::vector<std::string> includes;
+    if(haveDirectoryInfo)
       {
-      cmSystemTools::ExpandListArgument(includePath, includes);
+      std::string includePathVar = "CMAKE_";
+      includePathVar += lang;
+      includePathVar += "_INCLUDE_PATH";
+      if(const char* includePath = mf->GetDefinition(includePathVar.c_str()))
+        {
+        cmSystemTools::ExpandListArgument(includePath, includes);
+        }
       }
-    }
-
-  // Get the include file regular expression.
-  std::string includeRegexScan = "^.*$";
-  std::string includeRegexComplain = "^$";
-  if(haveDirectoryInfo)
-    {
-    std::string scanRegexVar = "CMAKE_";
-    scanRegexVar += lang;
-    scanRegexVar += "_INCLUDE_REGEX_SCAN";
-    if(const char* scanRegex = mf->GetDefinition(scanRegexVar.c_str()))
+    
+    // Get the include file regular expression.
+    std::string includeRegexScan = "^.*$";
+    std::string includeRegexComplain = "^$";
+    if(haveDirectoryInfo)
       {
-      includeRegexScan = scanRegex;
+      std::string scanRegexVar = "CMAKE_";
+      scanRegexVar += lang;
+      scanRegexVar += "_INCLUDE_REGEX_SCAN";
+      if(const char* scanRegex = mf->GetDefinition(scanRegexVar.c_str()))
+        {
+        includeRegexScan = scanRegex;
+        }
+      std::string complainRegexVar = "CMAKE_";
+      complainRegexVar += lang;
+      complainRegexVar += "_INCLUDE_REGEX_COMPLAIN";
+      if(const char* complainRegex = mf->GetDefinition(complainRegexVar.c_str()))
+        {
+        includeRegexComplain = complainRegex;
+        }
       }
-    std::string complainRegexVar = "CMAKE_";
-    complainRegexVar += lang;
-    complainRegexVar += "_INCLUDE_REGEX_COMPLAIN";
-    if(const char* complainRegex = mf->GetDefinition(complainRegexVar.c_str()))
+    
+    // Create the scanner for this language
+    cmDepends *scanner = 0;
+    if(lang == "C" || lang == "CXX" || lang == "RC")
       {
-      includeRegexComplain = complainRegex;
+      // TODO: Handle RC (resource files) dependencies correctly.
+      scanner = new cmDependsC(includes,
+                               includeRegexScan.c_str(), 
+                               includeRegexComplain.c_str());
       }
-    }
-
-  // Dispatch the scan for each language.
-  if(lang == "C" || lang == "CXX" || lang == "RC")
-    {
-    // TODO: Handle RC (resource files) dependencies correctly.
-    cmDependsC scanner(srcFile, includes,
-                       includeRegexScan.c_str(), includeRegexComplain.c_str());
-    scanner.SetTargetFile(".",objFile,".depend",".build.depend.make");
-    return scanner.Write();
-    }
 #ifdef CMAKE_BUILD_WITH_CMAKE
-  else if(lang == "Fortran")
-    {
-    cmDependsFortran scanner(srcFile, includes);
-    scanner.SetTargetFile(".",objFile,".depend",".build.depend.make");
-    return scanner.Write();
-    }
-  else if(lang == "Java")
-    {
-    cmDependsJava scanner(srcFile);
-    scanner.SetTargetFile(".",objFile,".depend",".build.depend.make");
-    return scanner.Write();
-    }
+    else if(lang == "Fortran")
+      {
+      scanner = new cmDependsFortran(includes);
+      }
+    else if(lang == "Java")
+      {
+      scanner = new cmDependsJava();
+      }
 #endif
-  return false;
+    
+    // for each file we need to scan
+    std::string srcLang = "CMAKE_DEPENDS_CHECK_";
+    srcLang += lang;
+    const char *srcStr = mf->GetSafeDefinition(srcLang.c_str());
+    std::vector<std::string> srcs;
+    cmSystemTools::ExpandListArgument(srcStr, srcs);
+    for (std::vector<std::string>::iterator si = 
+           srcs.begin(); si != srcs.end(); ++si)
+      {
+      std::string &src = *si;
+      ++si;
+      // make sure the object file is relative to home output
+      std::string obj = *si;
+      obj = lg->Convert(obj.c_str(),HOME_OUTPUT,MAKEFILE);
+      scanner->Write(src.c_str(),obj.c_str(),ruleFileStream);
+      }
+    
+    // free the scanner for this language
+    if (scanner)
+      {
+      delete scanner;
+      }
+    }
+
+  // dependencies were generated, so touch the mark file
+  dir += ".mark";
+  std::ofstream fmark(dir.c_str());
+  fmark << "Dependencies updated>" << std::endl;
+  
+  return true;
 }
 
 //----------------------------------------------------------------------------
@@ -2942,45 +2943,31 @@ void cmLocalUnixMakefileGenerator3::CheckDependencies(cmMakefile* mf,
                                                       bool verbose,
                                                       bool clear)
 {
-  // Get the list of languages that may have sources to check.
-  const char* langDef = mf->GetDefinition("CMAKE_DEPENDS_LANGUAGES");
-  if(!langDef)
+  // Get the list of target files to check
+  const char* infoDef = mf->GetDefinition("CMAKE_DEPEND_INFO_FILES");
+  if(!infoDef)
     {
     return;
     }
-  std::vector<std::string> languages;
-  cmSystemTools::ExpandListArgument(langDef, languages);
+  std::vector<std::string> files;
+  cmSystemTools::ExpandListArgument(infoDef, files);
 
-  // For each language get the set of files to check.
-  for(std::vector<std::string>::iterator l = languages.begin();
-      l != languages.end(); ++l)
+  // For each info file run the check
+  cmDependsC checker;
+  checker.SetVerbose(verbose);
+  for(std::vector<std::string>::iterator l = files.begin();
+      l != files.end(); ++l)
     {
-    std::string depCheck = "CMAKE_DEPENDS_CHECK_";
-    depCheck += *l;
-    if(const char* fileDef = mf->GetDefinition(depCheck.c_str()))
+    // either clear or check the files
+    std::string dependFile = cmSystemTools::GetFilenamePath(l->c_str());
+    dependFile += "/depend.make";
+    if (clear)
       {
-      // Check each file.  The current working directory is already
-      // correct.
-      std::vector<std::string> files;
-      cmSystemTools::ExpandListArgument(fileDef, files);
-      for(std::vector<std::string>::iterator f = files.begin();
-          f != files.end(); ++f)
-        {
-        // Construct a checker for the given language.
-        std::auto_ptr<cmDepends>
-          checker(this->GetDependsChecker(*l, ".", f->c_str(), verbose));
-        if(checker.get())
-          {
-          if (clear)
-            {
-            checker->Clear();
-            }
-          else
-            {
-            checker->Check();
-            }
-          }
-        }
+      checker.Clear(dependFile.c_str());
+      }
+    else
+      {
+      checker.Check(dependFile.c_str());
       }
     }
 }
@@ -3063,3 +3050,58 @@ cmLocalUnixMakefileGenerator3::WriteHelpRule(std::ostream& ruleFileStream)
                       no_depends, commands);
   ruleFileStream << "\n\n";
 }
+
+void cmLocalUnixMakefileGenerator3
+::WriteDependLanguageInfo(std::ostream& cmakefileStream, cmTarget &target)
+{
+  // now write all the language stuff
+  // Set the set of files to check for dependency integrity.
+   std::set<cmStdString> checkSetLangs;
+  std::map<cmStdString,cmLocalUnixMakefileGenerator3::IntegrityCheckSet>& 
+    checkSet = this->GetIntegrityCheckSet()[target.GetName()];
+  for(std::map<cmStdString, 
+        cmLocalUnixMakefileGenerator3::IntegrityCheckSet>::const_iterator
+        l = checkSet.begin(); l != checkSet.end(); ++l)
+    {
+    checkSetLangs.insert(l->first);
+    }
+  
+  // list the languages
+  cmakefileStream
+    << "# The set of files whose dependency integrity should be checked:\n";
+  cmakefileStream
+    << "SET(CMAKE_DEPENDS_LANGUAGES\n";
+  for(std::set<cmStdString>::iterator
+        l = checkSetLangs.begin(); l != checkSetLangs.end(); ++l)
+    {
+    cmakefileStream << "  \"" << l->c_str() << "\"\n";
+    }
+  cmakefileStream << "  )\n";
+  
+  // now list the files for each language
+  for(std::set<cmStdString>::iterator
+        l = checkSetLangs.begin(); l != checkSetLangs.end(); ++l)
+    {
+    cmakefileStream
+      << "SET(CMAKE_DEPENDS_CHECK_" << l->c_str() << "\n";
+    // get the check set for this local gen and language
+    cmLocalUnixMakefileGenerator3::IntegrityCheckSet iCheckSet = 
+      checkSet[*l];
+    // for each file
+    for(cmLocalUnixMakefileGenerator3::IntegrityCheckSet::const_iterator 
+          csIter = iCheckSet.begin();
+        csIter != iCheckSet.end(); ++csIter)
+      {
+      cmakefileStream << "  \"" << (*csIter)->GetFullPath() << "\"\n";
+      // Get the full path name of the object file.
+      std::string obj = this->GetObjectFileName(target, **csIter);
+      cmakefileStream << "  \"" << 
+        this->Convert(obj.c_str(),
+                      cmLocalGenerator::FULL).c_str() << "\"\n";
+      }
+    cmakefileStream << "  )\n";
+    }
+
+
+
+}

+ 17 - 12
Source/cmLocalUnixMakefileGenerator3.h

@@ -140,8 +140,9 @@ public:
   // List the files for which to check dependency integrity.  Each
   // language has its own list because integrity may be checked
   // differently.
-  struct IntegrityCheckSet: public std::set<cmStdString> {};
-  std::map<cmStdString, IntegrityCheckSet> &GetIntegrityCheckSet() 
+  struct IntegrityCheckSet: public std::set<cmSourceFile *> {};
+  struct IntegrityCheckSetMap: public std::map<cmStdString, IntegrityCheckSet> {};
+  std::map<cmStdString, IntegrityCheckSetMap> &GetIntegrityCheckSet() 
   { return m_CheckDependFiles;}
   
   void AppendTargetDepends(std::vector<std::string>& depends,
@@ -155,6 +156,9 @@ public:
 
 protected:
 
+  // write the depend info 
+  void WriteDependLanguageInfo(std::ostream& cmakefileStream, cmTarget &tgt);
+  
   // write the target rules for the local Makefile into the stream
   void WriteLocalMakefileTargets(std::ostream& ruleFileStream);
 
@@ -195,22 +199,24 @@ protected:
   
   // create the rule files for an object
   void WriteObjectRuleFiles(cmTarget& target,
-                            const cmSourceFile& source,
-                            std::vector<std::string>& objects);
+                            cmSourceFile& source,
+                            std::vector<std::string>& objects,
+                            std::ostream &filestr);
 
   // write the build rule for an object
   void WriteObjectBuildFile(std::string &obj,
                             const char *lang, 
                             cmTarget& target, 
-                            const cmSourceFile& source,
+                            cmSourceFile& source,
                             std::vector<std::string>& depends,
-                            std::string &depMakeFile);
+                            std::string &depMakeFile,
+                            std::ostream &filestr);
   
   // write the depend.make file for an object
   void WriteObjectDependRules(std::ostream& ruleFileStream,
                               std::string& obj,
                               const char *lang,
-                              const cmSourceFile& source,
+                              cmSourceFile& source,
                               std::vector<std::string>& depends,
                               std::string& depMarkFile);
   
@@ -222,13 +228,12 @@ protected:
 
   // return the appropriate depends checker
   cmDepends* GetDependsChecker(const std::string& lang,
-                               const char* dir,
-                               const char* objFile,
                                bool verbose);
   
   
-  std::string GenerateCustomRuleFile(const cmCustomCommand& cc, 
-                                     const char *dir);
+  void GenerateCustomRuleFile(const cmCustomCommand& cc, 
+                              const char *dir,
+                              std::ostream &ruleStream);
   
   // these three make some simple changes and then call WriteLibraryRule
   void WriteStaticLibraryRule(std::ostream& ruleFileStream,
@@ -327,7 +332,7 @@ protected:
   void ComputeHomeRelativeOutputPath();
 
 private:
-  std::map<cmStdString, IntegrityCheckSet> m_CheckDependFiles;
+  std::map<cmStdString, IntegrityCheckSetMap> m_CheckDependFiles;
 
   //==========================================================================
   // Configuration settings.

+ 1 - 1
Source/cmake.cxx

@@ -887,7 +887,7 @@ int cmake::CMakeCommand(std::vector<std::string>& args)
       }
 
     // Internal CMake dependency scanning support.
-    else if (args[1] == "cmake_depends" && args.size() >= 8)
+    else if (args[1] == "cmake_depends" && args.size() >= 6)
       {
       cmake cm;
       cmGlobalGenerator *ggd = cm.CreateGlobalGenerator(args[2].c_str());