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)
This commit is contained in:
Brad King 2008-03-11 17:25:49 -04:00
parent b5cebc00f7
commit fdf169be3a
3 changed files with 142 additions and 65 deletions

View File

@ -19,6 +19,7 @@
#include "cmLocalVisualStudio7Generator.h" #include "cmLocalVisualStudio7Generator.h"
#include "cmMakefile.h" #include "cmMakefile.h"
#include "cmake.h" #include "cmake.h"
#include "cmGeneratedFileStream.h"
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
cmGlobalVisualStudio8Generator::cmGlobalVisualStudio8Generator() cmGlobalVisualStudio8Generator::cmGlobalVisualStudio8Generator()
@ -131,6 +132,13 @@ void cmGlobalVisualStudio8Generator::Generate()
cmLocalVisualStudio7Generator* lg = cmLocalVisualStudio7Generator* lg =
static_cast<cmLocalVisualStudio7Generator*>(generators[0]); static_cast<cmLocalVisualStudio7Generator*>(generators[0]);
cmMakefile* mf = lg->GetMakefile(); 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"); std::string cmake_command = mf->GetRequiredDefinition("CMAKE_COMMAND");
cmCustomCommandLines noCommandLines; cmCustomCommandLines noCommandLines;
mf->AddUtilityCommand(CMAKE_CHECK_BUILD_SYSTEM_TARGET, false, mf->AddUtilityCommand(CMAKE_CHECK_BUILD_SYSTEM_TARGET, false,
@ -144,72 +152,94 @@ void cmGlobalVisualStudio8Generator::Generate()
continue; continue;
} }
// Add a custom rule to re-run CMake if any input files changed. // Create a list of all stamp files for this project.
const char* suppRegenRule = std::vector<std::string> stamps;
mf->GetDefinition("CMAKE_SUPPRESS_REGENERATION"); std::string stampList = cmake::GetCMakeFilesDirectoryPostSlash();
if(!cmSystemTools::IsOn(suppRegenRule)) 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)
{ {
// Collect the input files used to generate all targets in this stampFile = (*gi)->GetMakefile()->GetCurrentOutputDirectory();
// project. stampFile += "/";
std::vector<std::string> listFiles; stampFile += cmake::GetCMakeFilesDirectoryPostSlash();
for(unsigned int j = 0; j < generators.size(); ++j) stampFile += "generate.stamp";
{ stampFile = generators[0]->Convert(stampFile.c_str(),
cmMakefile* lmf = generators[j]->GetMakefile(); cmLocalGenerator::START_OUTPUT);
listFiles.insert(listFiles.end(), lmf->GetListFiles().begin(), fout << stampFile << "\n";
lmf->GetListFiles().end()); stamps.push_back(stampFile);
}
// 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);
// 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 a custom rule to re-run CMake if any input files changed.
{
// 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());
// 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(
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());
}
}
}
} }
// Now perform the main generation. // Now perform the main generation.

View File

@ -111,6 +111,7 @@
#include <memory> // auto_ptr #include <memory> // auto_ptr
static bool cmakeCheckStampFile(const char* stampName); static bool cmakeCheckStampFile(const char* stampName);
static bool cmakeCheckStampList(const char* stampName);
void cmNeedBackwardsCompatibility(const std::string& variable, void cmNeedBackwardsCompatibility(const std::string& variable,
int access_type, void*, const char*, const cmMakefile*) 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]; 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) #if defined(CMAKE_HAVE_VS_GENERATORS)
else if((i < args.size()-1) && (arg.find("--vs-solution-file",0) == 0)) 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; 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 we are given a stamp file check if it is really out of date.
if(!this->CheckStampFile.empty() && if(!this->CheckStampFile.empty() &&
cmakeCheckStampFile(this->CheckStampFile.c_str())) cmakeCheckStampFile(this->CheckStampFile.c_str()))
@ -3697,6 +3709,10 @@ static bool cmakeCheckStampFile(const char* stampName)
// date. // date.
if(cmSystemTools::FileExists(stampName)) 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; 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 // Notify the user why CMake is not re-running. It is safe to
// just print to stdout here because this code is only reachable // just print to stdout here because this code is only reachable
// through an undocumented flag used by the VS generator. // through an undocumented flag used by the VS generator.
std::cout << "CMake does not need to re-run because the " std::cout << "CMake does not need to re-run because "
<< "generation timestamp is up-to-date.\n"; << stampName << " is up-to-date.\n";
return true; return true;
} }
else 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 // 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 // exe and dll's. This code does that in such a way that incremental linking
// still works. // still works.

View File

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