From 34c882a9f8b45350ba8d56d79a94e1602694ef8f Mon Sep 17 00:00:00 2001 From: Brad King Date: Sat, 10 Nov 2007 08:15:13 -0500 Subject: ENH: Allow VS 7 project Rebuild and Solution Rebuild to work without re-running CMake for every project during the rebuild. --- Source/cmGlobalVisualStudio8Generator.cxx | 6 ++- Source/cmLocalVisualStudio7Generator.cxx | 31 ++++++++++-- Source/cmake.cxx | 78 +++++++++++++++++++++++++++++++ Source/cmake.h | 1 + 4 files changed, 111 insertions(+), 5 deletions(-) diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx index c7c5fff..f83c76f 100644 --- a/Source/cmGlobalVisualStudio8Generator.cxx +++ b/Source/cmGlobalVisualStudio8Generator.cxx @@ -124,6 +124,8 @@ void cmGlobalVisualStudio8Generator::Generate() listFiles.erase(new_end, listFiles.end()); // Create a rule to re-run CMake. + std::string stampName = cmake::GetCMakeFilesDirectoryPostSlash(); + stampName += CMAKE_CHECK_BUILD_SYSTEM_TARGET ".vcproj.stamp"; const char* dsprule = mf->GetRequiredDefinition("CMAKE_COMMAND"); cmCustomCommandLine commandLine; commandLine.push_back(dsprule); @@ -137,6 +139,8 @@ void cmGlobalVisualStudio8Generator::Generate() cmLocalGenerator::START_OUTPUT, cmLocalGenerator::UNCHANGED, true); commandLine.push_back(argB); + commandLine.push_back("--check-stamp-file"); + commandLine.push_back(stampName.c_str()); cmCustomCommandLines commandLines; commandLines.push_back(commandLine); @@ -146,8 +150,6 @@ void cmGlobalVisualStudio8Generator::Generate() // target. const char* no_main_dependency = 0; const char* no_working_directory = 0; - std::string stampName = cmake::GetCMakeFilesDirectoryPostSlash(); - stampName += CMAKE_CHECK_BUILD_SYSTEM_TARGET ".vcproj.stamp"; mf->AddCustomCommandToOutput( stampName.c_str(), listFiles, no_main_dependency, commandLines, "Checking Build System", diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index 1e1321a..63404a2 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -164,17 +164,40 @@ void cmLocalVisualStudio7Generator this->WriteVCProjFile(fout,lname,target); } + // Create a helper file so CMake can determine when it is run + // through the rule created by AddVCProjBuildRule whether it really + // needs to regenerate the project. This file lists its own + // dependencies. If any file listed in it is newer than itself then + // CMake must rerun. Otherwise the project file is up to date and + // the stamp file can just be touched. + { + std::string depName = this->Makefile->GetStartOutputDirectory(); + depName += cmake::GetCMakeFilesDirectory(); + depName += "/"; + depName += lname; + depName += ".vcproj.stamp.depend"; + std::ofstream depFile(depName.c_str()); + depFile << "# CMake dependency list for corresponding VS project.\n"; + std::vector const& listFiles = this->Makefile->GetListFiles(); + for(std::vector::const_iterator lf = listFiles.begin(); + lf != listFiles.end(); ++lf) + { + depFile << *lf << std::endl; + } + } + // Touch a timestamp file used to determine when the project file is // out of date. - std::string stampName; - stampName = this->Makefile->GetStartOutputDirectory(); + { + std::string stampName = this->Makefile->GetStartOutputDirectory(); stampName += cmake::GetCMakeFilesDirectory(); cmSystemTools::MakeDirectory(stampName.c_str()); stampName += "/"; stampName += lname; stampName += ".vcproj.stamp"; std::ofstream stamp(stampName.c_str()); - stamp << "# CMake timestamp for " << lname << ".vcproj" << std::endl; + stamp << "# CMake timestamp file for corresponding VS project.\n"; + } } @@ -203,6 +226,8 @@ void cmLocalVisualStudio7Generator::AddVCProjBuildRule(cmTarget& tgt) this->Convert(this->Makefile->GetHomeOutputDirectory(), START_OUTPUT, UNCHANGED, true); commandLine.push_back(args); + commandLine.push_back("--check-stamp-file"); + commandLine.push_back(stampName.c_str()); std::vector const& listFiles = this->Makefile->GetListFiles(); diff --git a/Source/cmake.cxx b/Source/cmake.cxx index de06383..166e71a 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -104,6 +104,8 @@ #include // auto_ptr +static bool cmakeCheckStampFile(const char* stampName); + void cmNeedBackwardsCompatibility(const std::string& variable, int access_type, void*, const char*, const cmMakefile*) { @@ -520,6 +522,10 @@ void cmake::SetArgs(const std::vector& args) this->CheckBuildSystemArgument = args[++i]; this->ClearBuildSystem = (atoi(args[++i].c_str()) > 0); } + else if((i < args.size()-1) && (arg.find("--check-stamp-file",0) == 0)) + { + this->CheckStampFile = args[++i]; + } else if(arg.find("-V",0) == 0) { this->Verbose = true; @@ -1994,6 +2000,13 @@ int cmake::Run(const std::vector& args, bool noconfigure) return -1; } + // If we are given a stamp file check if it is really out of date. + if(!this->CheckStampFile.empty() && + cmakeCheckStampFile(this->CheckStampFile.c_str())) + { + return 0; + } + // set the cmake command this->CMakeCommand = args[0]; @@ -3406,3 +3419,68 @@ int cmake::GetSystemInformation(std::vector& args) cmSystemTools::RemoveADirectory(destPath.c_str()); return 0; } + +//---------------------------------------------------------------------------- +static bool cmakeCheckStampFile(const char* stampName) +{ + // If the stamp file still exists then it must really be out of + // date. + if(cmSystemTools::FileExists(stampName)) + { + return false; + } + + // The stamp file does not exist. Use the stamp dependencies to + // determine whether it is really out of date. This works in + // conjunction with cmLocalVisualStudio7Generator to avoid + // repeatedly re-running CMake when the user rebuilds the entire + // solution. + std::string stampDepends = stampName; + stampDepends += ".depend"; +#if defined(_WIN32) || defined(__CYGWIN__) + std::ifstream fin(stampDepends.c_str(), std::ios::in | std::ios::binary); +#else + std::ifstream fin(stampDepends.c_str(), std::ios::in); +#endif + if(!fin) + { + // The stamp dependencies file cannot be read. Just assume the + // build system is really out of date. + return false; + } + + // Compare the stamp dependencies against the dependency file itself. + cmFileTimeComparison ftc; + std::string dep; + while(cmSystemTools::GetLineFromStream(fin, dep)) + { + int result; + if(dep.length() >= 1 && dep[0] != '#' && + (!ftc.FileTimeCompare(stampDepends.c_str(), dep.c_str(), &result) + || result < 0)) + { + // The stamp depends file is older than this dependency. The + // build system is really out of date. + return false; + } + } + + // The build system is up to date. The stamp file has been removed + // by the VS IDE due to a "rebuild" request. Just restore it. + std::ofstream stamp(stampName); + stamp << "# CMake timestamp file for corresponding VS project.\n"; + if(stamp) + { + // 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 " + << "project timestamp is up-to-date.\n"; + return true; + } + else + { + cmSystemTools::Error("Cannot restore timestamp ", stampName); + return false; + } +} diff --git a/Source/cmake.h b/Source/cmake.h index da20fef..aa0ff28 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -401,6 +401,7 @@ private: std::string CXXEnvironment; std::string CCEnvironment; std::string CheckBuildSystemArgument; + std::string CheckStampFile; std::string CTestCommand; std::string CPackCommand; bool ClearBuildSystem; -- cgit v0.12