Просмотр исходного кода

BUG: Fixes to VS8/VS9 project regeneration rules

  - ZERO_CHECK should check all stamps in case
    of parallel build (fixes complex test failure)
  - ZERO_CHECK should not appear when
    CMAKE_SUPPRESS_REGENERATION is on (fixes bug 6490)
Brad King 18 лет назад
Родитель
Сommit
fdf169be3a
3 измененных файлов с 139 добавлено и 62 удалено
  1. 90 60
      Source/cmGlobalVisualStudio8Generator.cxx
  2. 48 2
      Source/cmake.cxx
  3. 1 0
      Source/cmake.h

+ 90 - 60
Source/cmGlobalVisualStudio8Generator.cxx

@@ -19,6 +19,7 @@
 #include "cmLocalVisualStudio7Generator.h"
 #include "cmMakefile.h"
 #include "cmake.h"
+#include "cmGeneratedFileStream.h"
 
 //----------------------------------------------------------------------------
 cmGlobalVisualStudio8Generator::cmGlobalVisualStudio8Generator()
@@ -131,6 +132,13 @@ void cmGlobalVisualStudio8Generator::Generate()
       cmLocalVisualStudio7Generator* lg =
         static_cast<cmLocalVisualStudio7Generator*>(generators[0]);
       cmMakefile* mf = lg->GetMakefile();
+
+      // Skip the target if no regeneration is to be done.
+      if(mf->IsOn("CMAKE_SUPPRESS_REGENERATION"))
+        {
+        continue;
+        }
+
       std::string cmake_command = mf->GetRequiredDefinition("CMAKE_COMMAND");
       cmCustomCommandLines noCommandLines;
       mf->AddUtilityCommand(CMAKE_CHECK_BUILD_SYSTEM_TARGET, false,
@@ -144,71 +152,93 @@ void cmGlobalVisualStudio8Generator::Generate()
         continue;
         }
 
+      // Create a list of all stamp files for this project.
+      std::vector<std::string> stamps;
+      std::string stampList = cmake::GetCMakeFilesDirectoryPostSlash();
+      stampList += "generate.stamp.list";
+      {
+      std::string stampListFile =
+        generators[0]->GetMakefile()->GetCurrentOutputDirectory();
+      stampListFile += "/";
+      stampListFile += stampList;
+      std::string stampFile;
+      cmGeneratedFileStream fout(stampList.c_str());
+      for(std::vector<cmLocalGenerator*>::const_iterator
+            gi = generators.begin(); gi != generators.end(); ++gi)
+        {
+        stampFile = (*gi)->GetMakefile()->GetCurrentOutputDirectory();
+        stampFile += "/";
+        stampFile += cmake::GetCMakeFilesDirectoryPostSlash();
+        stampFile += "generate.stamp";
+        stampFile = generators[0]->Convert(stampFile.c_str(),
+                                           cmLocalGenerator::START_OUTPUT);
+        fout << stampFile << "\n";
+        stamps.push_back(stampFile);
+        }
+      }
+
       // Add a custom rule to re-run CMake if any input files changed.
-      const char* suppRegenRule =
-        mf->GetDefinition("CMAKE_SUPPRESS_REGENERATION");
-      if(!cmSystemTools::IsOn(suppRegenRule))
+      {
+      // Collect the input files used to generate all targets in this
+      // project.
+      std::vector<std::string> listFiles;
+      for(unsigned int j = 0; j < generators.size(); ++j)
         {
-        // Collect the input files used to generate all targets in this
-        // project.
-        std::vector<std::string> listFiles;
-        for(unsigned int j = 0; j < generators.size(); ++j)
-          {
-          cmMakefile* lmf = generators[j]->GetMakefile();
-          listFiles.insert(listFiles.end(), lmf->GetListFiles().begin(),
-                           lmf->GetListFiles().end());
-          }
-        // Sort the list of input files and remove duplicates.
-        std::sort(listFiles.begin(), listFiles.end(), 
-                  std::less<std::string>());
-        std::vector<std::string>::iterator new_end =
-          std::unique(listFiles.begin(), listFiles.end());
-        listFiles.erase(new_end, listFiles.end());
+        cmMakefile* lmf = generators[j]->GetMakefile();
+        listFiles.insert(listFiles.end(), lmf->GetListFiles().begin(),
+                         lmf->GetListFiles().end());
+        }
+      // Sort the list of input files and remove duplicates.
+      std::sort(listFiles.begin(), listFiles.end(),
+                std::less<std::string>());
+      std::vector<std::string>::iterator new_end =
+        std::unique(listFiles.begin(), listFiles.end());
+      listFiles.erase(new_end, listFiles.end());
 
-        // Create a rule to re-run CMake.
-        std::string stampName = cmake::GetCMakeFilesDirectoryPostSlash();
-        stampName += "generate.stamp";
-        const char* dsprule = mf->GetRequiredDefinition("CMAKE_COMMAND");
-        cmCustomCommandLine commandLine;
-        commandLine.push_back(dsprule);
-        std::string argH = "-H";
-        argH += lg->Convert(mf->GetHomeDirectory(),
-                            cmLocalGenerator::START_OUTPUT,
-                            cmLocalGenerator::UNCHANGED, true);
-        commandLine.push_back(argH);
-        std::string argB = "-B";
-        argB += lg->Convert(mf->GetHomeOutputDirectory(),
-                            cmLocalGenerator::START_OUTPUT,
-                            cmLocalGenerator::UNCHANGED, true);
-        commandLine.push_back(argB);
-        commandLine.push_back("--check-stamp-file");
-        commandLine.push_back(stampName.c_str());
-        commandLine.push_back("--vs-solution-file");
-        commandLine.push_back("\"$(SolutionPath)\"");
-        cmCustomCommandLines commandLines;
-        commandLines.push_back(commandLine);
+      // Create a rule to re-run CMake.
+      std::string stampName = cmake::GetCMakeFilesDirectoryPostSlash();
+      stampName += "generate.stamp";
+      const char* dsprule = mf->GetRequiredDefinition("CMAKE_COMMAND");
+      cmCustomCommandLine commandLine;
+      commandLine.push_back(dsprule);
+      std::string argH = "-H";
+      argH += lg->Convert(mf->GetHomeDirectory(),
+                          cmLocalGenerator::START_OUTPUT,
+                          cmLocalGenerator::UNCHANGED, true);
+      commandLine.push_back(argH);
+      std::string argB = "-B";
+      argB += lg->Convert(mf->GetHomeOutputDirectory(),
+                          cmLocalGenerator::START_OUTPUT,
+                          cmLocalGenerator::UNCHANGED, true);
+      commandLine.push_back(argB);
+      commandLine.push_back("--check-stamp-list");
+      commandLine.push_back(stampList.c_str());
+      commandLine.push_back("--vs-solution-file");
+      commandLine.push_back("\"$(SolutionPath)\"");
+      cmCustomCommandLines commandLines;
+      commandLines.push_back(commandLine);
 
-        // Add the rule.  Note that we cannot use the CMakeLists.txt
-        // file as the main dependency because it would get
-        // overwritten by the CreateVCProjBuildRule.
-        // (this could be avoided with per-target source files)
-        const char* no_main_dependency = 0;
-        const char* no_working_directory = 0;
-        mf->AddCustomCommandToOutput(
-          stampName.c_str(), listFiles,
-          no_main_dependency, commandLines, "Checking Build System",
-          no_working_directory, true);
-        std::string ruleName = stampName;
-        ruleName += ".rule";
-        if(cmSourceFile* file = mf->GetSource(ruleName.c_str()))
-          {
-          tgt->AddSourceFile(file);
-          }
-        else
-          {
-          cmSystemTools::Error("Error adding rule for ", stampName.c_str());
-          }
+      // Add the rule.  Note that we cannot use the CMakeLists.txt
+      // file as the main dependency because it would get
+      // overwritten by the CreateVCProjBuildRule.
+      // (this could be avoided with per-target source files)
+      const char* no_main_dependency = 0;
+      const char* no_working_directory = 0;
+      mf->AddCustomCommandToOutput(
+        stamps, listFiles,
+        no_main_dependency, commandLines, "Checking Build System",
+        no_working_directory, true);
+      std::string ruleName = stamps[0];
+      ruleName += ".rule";
+      if(cmSourceFile* file = mf->GetSource(ruleName.c_str()))
+        {
+        tgt->AddSourceFile(file);
         }
+      else
+        {
+        cmSystemTools::Error("Error adding rule for ", stamps[0].c_str());
+        }
+      }
       }
     }
 

+ 48 - 2
Source/cmake.cxx

@@ -111,6 +111,7 @@
 #include <memory> // auto_ptr
 
 static bool cmakeCheckStampFile(const char* stampName);
+static bool cmakeCheckStampList(const char* stampName);
 
 void cmNeedBackwardsCompatibility(const std::string& variable,
   int access_type, void*, const char*, const cmMakefile*)
@@ -553,6 +554,10 @@ void cmake::SetArgs(const std::vector<std::string>& args)
       {
       this->CheckStampFile = args[++i];
       }
+    else if((i < args.size()-1) && (arg.find("--check-stamp-list",0) == 0))
+      {
+      this->CheckStampList = args[++i];
+      }
 #if defined(CMAKE_HAVE_VS_GENERATORS)
     else if((i < args.size()-1) && (arg.find("--vs-solution-file",0) == 0))
       {
@@ -2150,6 +2155,13 @@ int cmake::Run(const std::vector<std::string>& args, bool noconfigure)
     return -1;
     }
 
+  // If we are given a stamp list file check if it is really out of date.
+  if(!this->CheckStampList.empty() &&
+     cmakeCheckStampList(this->CheckStampList.c_str()))
+    {
+    return 0;
+    }
+
   // If we are given a stamp file check if it is really out of date.
   if(!this->CheckStampFile.empty() &&
      cmakeCheckStampFile(this->CheckStampFile.c_str()))
@@ -3697,6 +3709,10 @@ static bool cmakeCheckStampFile(const char* stampName)
   // date.
   if(cmSystemTools::FileExists(stampName))
     {
+    // Notify the user why CMake is re-running.  It is safe to
+    // just print to stdout here because this code is only reachable
+    // through an undocumented flag used by the VS generator.
+    std::cout << "CMake is re-running due to explicit user request.\n";
     return false;
     }
 
@@ -3744,8 +3760,8 @@ static bool cmakeCheckStampFile(const char* stampName)
     // Notify the user why CMake is not re-running.  It is safe to
     // just print to stdout here because this code is only reachable
     // through an undocumented flag used by the VS generator.
-    std::cout << "CMake does not need to re-run because the "
-              << "generation timestamp is up-to-date.\n";
+    std::cout << "CMake does not need to re-run because "
+              << stampName << " is up-to-date.\n";
     return true;
     }
   else
@@ -3755,6 +3771,36 @@ static bool cmakeCheckStampFile(const char* stampName)
     }
 }
 
+//----------------------------------------------------------------------------
+static bool cmakeCheckStampList(const char* stampList)
+{
+  // If the stamp list does not exist CMake must rerun to generate it.
+  if(!cmSystemTools::FileExists(stampList))
+    {
+    std::cout << "CMake is re-running because generate.stamp.list "
+              << "is missing.\n";
+    return false;
+    }
+  std::ifstream fin(stampList);
+  if(!fin)
+    {
+    std::cout << "CMake is re-running because generate.stamp.list "
+              << "could not be read.\n";
+    return false;
+    }
+
+  // Check each stamp.
+  std::string stampName;
+  while(cmSystemTools::GetLineFromStream(fin, stampName))
+    {
+    if(!cmakeCheckStampFile(stampName.c_str()))
+      {
+      return false;
+      }
+    }
+  return true;
+}
+
 // For visual studio 2005 and newer manifest files need to be embeded into
 // exe and dll's.  This code does that in such a way that incremental linking
 // still works.

+ 1 - 0
Source/cmake.h

@@ -435,6 +435,7 @@ private:
   std::string CCEnvironment;
   std::string CheckBuildSystemArgument;
   std::string CheckStampFile;
+  std::string CheckStampList;
   std::string VSSolutionFile;
   std::string CTestCommand;
   std::string CPackCommand;