Bläddra i källkod

ENH: Adding support for automatically adding the OBJECT_DEPENDS for generated header files.

Brad King 20 år sedan
förälder
incheckning
f4920b8369
3 ändrade filer med 109 tillägg och 13 borttagningar
  1. 36 6
      Source/cmDependsC.cxx
  2. 11 2
      Source/cmDependsC.h
  3. 62 5
      Source/cmLocalUnixMakefileGenerator3.cxx

+ 36 - 6
Source/cmDependsC.cxx

@@ -21,18 +21,21 @@
 #include <ctype.h> // isspace
 
 //----------------------------------------------------------------------------
-cmDependsC::cmDependsC()
+cmDependsC::cmDependsC():
+  m_IncludePath(0), m_GeneratedFiles(0)
 {
 }
 
 //----------------------------------------------------------------------------
 // yummy look at all those constructor arguments
 cmDependsC::cmDependsC(std::vector<std::string> const& includes,
-                       const char* scanRegex, const char* complainRegex):
+                       const char* scanRegex, const char* complainRegex,
+                       std::set<cmStdString> const& generatedFiles):
   m_IncludePath(&includes),
   m_IncludeRegexLine("^[ \t]*#[ \t]*include[ \t]*[<\"]([^\">]+)([\">])"),
   m_IncludeRegexScan(scanRegex),
-  m_IncludeRegexComplain(complainRegex)
+  m_IncludeRegexComplain(complainRegex),
+  m_GeneratedFiles(&generatedFiles)
 {
 }
 
@@ -81,13 +84,15 @@ bool cmDependsC::WriteDependencies(const char *src,
     std::string fullName;
     if(first || cmSystemTools::FileIsFullPath(current.FileName.c_str()))
       {
-      if(cmSystemTools::FileExists(current.FileName.c_str()))
+      if(this->FileExistsOrIsGenerated(current.FileName, scanned,
+                                       dependencies))
         {
         fullName = current.FileName;
         }
       }
     else if(!current.QuotedLocation.empty() &&
-            cmSystemTools::FileExists(current.QuotedLocation.c_str()))
+            this->FileExistsOrIsGenerated(current.QuotedLocation, scanned,
+                                          dependencies))
       {
       // The include statement producing this entry was a double-quote
       // include and the included file is present in the directory of
@@ -113,7 +118,7 @@ bool cmDependsC::WriteDependencies(const char *src,
         temp += current.FileName;
 
         // Look for the file in this location.
-        if(cmSystemTools::FileExists(temp.c_str()))
+        if(this->FileExistsOrIsGenerated(temp, scanned, dependencies))
           {
           fullName = temp;
           break;
@@ -346,3 +351,28 @@ const char* cmDependsC::ParseFileName(const char* in, std::string& name)
   // Return the ending position.
   return c;
 }
+
+//----------------------------------------------------------------------------
+bool cmDependsC::FileExistsOrIsGenerated(const std::string& fname,
+                                         std::set<cmStdString>& scanned,
+                                         std::set<cmStdString>& dependencies)
+{
+  // Check first for a generated file.
+  if(m_GeneratedFiles &&
+     m_GeneratedFiles->find(fname) != m_GeneratedFiles->end())
+    {
+    // If the file does not really exist yet pretend it has already
+    // been scanned.  When it exists later then dependencies will be
+    // rescanned.
+    if(!cmSystemTools::FileExists(fname.c_str()))
+      {
+      scanned.insert(fname);
+      dependencies.insert(fname);
+      }
+    return true;
+    }
+  else
+    {
+    return cmSystemTools::FileExists(fname.c_str());
+    }
+}

+ 11 - 2
Source/cmDependsC.h

@@ -31,7 +31,8 @@ public:
       relative path from the build directory to the target file.  */
   cmDependsC();
   cmDependsC(std::vector<std::string> const& includes,
-             const char* scanRegex, const char* complainRegex);
+             const char* scanRegex, const char* complainRegex,
+             std::set<cmStdString> const& generatedFiles);
 
   /** Virtual destructor to cleanup subclasses properly.  */
   virtual ~cmDependsC();
@@ -50,6 +51,11 @@ protected:
                        std::string& dependee);
   const char* ParseFileName(const char* in, std::string& name);
 
+  // Method to test for the existence of a file.
+  bool FileExistsOrIsGenerated(const std::string& fname,
+                               std::set<cmStdString>& scanned,
+                               std::set<cmStdString>& dependencies);
+
   // The include file search path.
   std::vector<std::string> const* m_IncludePath;
 
@@ -60,7 +66,10 @@ protected:
   // recursively and which to complain about not finding.
   cmsys::RegularExpression m_IncludeRegexScan;
   cmsys::RegularExpression m_IncludeRegexComplain;
-  
+
+  // Set of generated files available.
+  std::set<cmStdString> const* m_GeneratedFiles;
+
   // Data structures for dependency graph walk.
   struct UnscannedEntry
   {

+ 62 - 5
Source/cmLocalUnixMakefileGenerator3.cxx

@@ -203,6 +203,8 @@ void cmLocalUnixMakefileGenerator3::WriteDirectoryInformationFile()
   for(std::vector<std::string>::iterator i = includeDirs.begin();
       i != includeDirs.end(); ++i)
     {
+    // Note: This path conversion must match that used for
+    // CMAKE_GENERATED_FILES so that the file names match.
     infoFileStream
       << "  \"" << this->Convert(i->c_str(),HOME_OUTPUT).c_str() << "\"\n";
     }
@@ -231,6 +233,30 @@ void cmLocalUnixMakefileGenerator3::WriteDirectoryInformationFile()
     << "SET(CMAKE_CXX_INCLUDE_REGEX_SCAN ${CMAKE_C_INCLUDE_REGEX_SCAN})\n";
   infoFileStream
     << "SET(CMAKE_CXX_INCLUDE_REGEX_COMPLAIN ${CMAKE_C_INCLUDE_REGEX_COMPLAIN})\n";
+
+  // Store the set of available generated files.
+  infoFileStream
+    << "\n"
+    << "# The set of files generated by rules in this directory:\n";
+  infoFileStream
+    << "SET(CMAKE_GENERATED_FILES\n";
+  for(std::vector<cmSourceFile*>::const_iterator
+        i = m_Makefile->GetSourceFiles().begin();
+      i != m_Makefile->GetSourceFiles().end(); ++i)
+    {
+    cmSourceFile* src = *i;
+    if(src->GetPropertyAsBool("GENERATED"))
+      {
+      // Note: This path conversion must match that used for
+      // CMAKE_C_INCLUDE_PATH so that the file names match.
+      infoFileStream
+        << "  \""
+        << this->Convert(src->GetFullPath().c_str(), HOME_OUTPUT)
+        << "\"\n";
+      }
+    }
+  infoFileStream
+    << ")\n";
 }
 
 //----------------------------------------------------------------------------
@@ -546,6 +572,7 @@ cmLocalUnixMakefileGenerator3
   std::string objectFile = this->Convert(obj.c_str(),START_OUTPUT,SHELL);
 
   // Construct the build message.
+  std::vector<std::string> no_commands;
   std::vector<std::string> commands;
   std::string buildEcho = "Building ";
   buildEcho += lang;
@@ -575,6 +602,22 @@ cmLocalUnixMakefileGenerator3
                               flags.c_str());
     }
 
+  // Add dependencies known at CMake time.
+  std::string relativeObjDeps = relativeObj;
+  relativeObjDeps += "/depend";
+  this->WriteMakeRule(ruleFileStream, 0,
+                      relativeObjDeps.c_str(), depends, no_commands);
+  depends.clear();
+  depends.push_back(relativeObjDeps);
+
+  // Make the target dependency scanning rule include cmake-time-known
+  // dependencies.  The others are handled by the check-build-system
+  // path.
+  std::string depMark = this->GetRelativeTargetDirectory(target);
+  depMark += "/depend.make.mark";
+  this->WriteMakeRule(ruleFileStream, 0,
+                      depMark.c_str(), depends, no_commands);
+
   // Write the rule.
   this->WriteMakeRule(ruleFileStream, 0,
                       relativeObj.c_str(), depends, commands);
@@ -583,7 +626,6 @@ cmLocalUnixMakefileGenerator3
   // corresponding targets.
   std::string objectRequires = relativeObj;
   objectRequires += ".requires";
-  std::vector<std::string> no_commands;
   std::vector<std::string> p_depends;
   // always provide an empty requires target
   this->WriteMakeRule(ruleFileStream, 0,
@@ -2682,7 +2724,21 @@ cmLocalUnixMakefileGenerator3
     return false;
     }
   this->WriteDisclaimer(ruleFileStream);
-  
+
+  // Get the set of generated files.
+  std::vector<std::string> generatedFilesVec;
+  if(haveDirectoryInfo)
+    {
+    if(const char* generated = mf->GetDefinition("CMAKE_GENERATED_FILES"))
+      {
+      cmSystemTools::ExpandListArgument(generated, generatedFilesVec);
+      }
+    }
+
+  // Sort for efficient lookup.
+  std::set<cmStdString> generatedFiles(generatedFilesVec.begin(),
+                                       generatedFilesVec.end());
+
   // for each language we need to scan, scan it 
   const char *langStr = mf->GetSafeDefinition("CMAKE_DEPENDS_LANGUAGES");
   std::vector<std::string> langs;
@@ -2726,15 +2782,16 @@ cmLocalUnixMakefileGenerator3
         includeRegexComplain = complainRegex;
         }
       }
-    
+
     // Create the scanner for this language
     cmDepends *scanner = 0;
     if(lang == "C" || lang == "CXX" || lang == "RC")
       {
       // TODO: Handle RC (resource files) dependencies correctly.
       scanner = new cmDependsC(includes,
-                               includeRegexScan.c_str(), 
-                               includeRegexComplain.c_str());
+                               includeRegexScan.c_str(),
+                               includeRegexComplain.c_str(),
+                               generatedFiles);
       }
 #ifdef CMAKE_BUILD_WITH_CMAKE
     else if(lang == "Fortran")