[Cmake-commits] [cmake-commits] king committed cmGlobalGenerator.cxx 1.230 1.231 cmGlobalGenerator.h 1.109 1.110 cmMakefileTargetGenerator.cxx 1.101 1.102
cmake-commits at cmake.org
cmake-commits at cmake.org
Mon Jun 2 16:45:00 EDT 2008
Update of /cvsroot/CMake/CMake/Source
In directory public:/mounts/ram/cvs-serv1133/Source
Modified Files:
cmGlobalGenerator.cxx cmGlobalGenerator.h
cmMakefileTargetGenerator.cxx
Log Message:
ENH: Introduce "rule hashes" to help rebuild files when rules change.
- In CMake 2.4 custom commands would not rebuild when rules changed.
- In CMake 2.6.0 custom commands have a dependency on build.make
which causes them to rebuild when changed, but also when any
source is added or removed. This is too often.
- We cannot have a per-rule file because Windows filesystems
do not deal well with lots of small files.
- Instead we add a persistent CMakeFiles/CMakeRuleHashes.txt file
at the top of the build tree that is updated during each
CMake Generate step. It records a hash of the build rule for
each file to be built. When the hash changes the file is
removed so that it will be rebuilt.
Index: cmGlobalGenerator.h
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmGlobalGenerator.h,v
retrieving revision 1.109
retrieving revision 1.110
diff -C 2 -d -r1.109 -r1.110
*** cmGlobalGenerator.h 27 May 2008 15:18:01 -0000 1.109
--- cmGlobalGenerator.h 2 Jun 2008 20:44:58 -0000 1.110
***************
*** 246,249 ****
--- 246,253 ----
void GetFilesReplacedDuringGenerate(std::vector<std::string>& filenames);
+ void AddRuleHash(const std::vector<std::string>& outputs,
+ const std::vector<std::string>& depends,
+ const std::vector<std::string>& commands);
+
protected:
// for a project collect all its targets by following depend
***************
*** 314,317 ****
--- 318,326 ----
std::map<cmStdString,cmTarget *> TotalTargets;
+ // Record hashes for rules and outputs.
+ struct RuleHash { char Data[32]; };
+ std::map<cmStdString, RuleHash> RuleHashes;
+ void CheckRuleHashes();
+
cmExternalMakefileProjectGenerator* ExtraGenerator;
Index: cmGlobalGenerator.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmGlobalGenerator.cxx,v
retrieving revision 1.230
retrieving revision 1.231
diff -C 2 -d -r1.230 -r1.231
*** cmGlobalGenerator.cxx 27 May 2008 15:18:00 -0000 1.230
--- cmGlobalGenerator.cxx 2 Jun 2008 20:44:57 -0000 1.231
***************
*** 28,34 ****
--- 28,39 ----
#include "cmExportInstallFileGenerator.h"
#include "cmComputeTargetDepends.h"
+ #include "cmGeneratedFileStream.h"
#include <cmsys/Directory.hxx>
+ #if defined(CMAKE_BUILD_WITH_CMAKE)
+ # include <cmsys/MD5.h>
+ #endif
+
#include <stdlib.h> // required for atof
***************
*** 687,690 ****
--- 692,696 ----
this->LocalGeneratorToTargetMap.clear();
this->ProjectMap.clear();
+ this->RuleHashes.clear();
// start with this directory
***************
*** 841,844 ****
--- 847,853 ----
this->SetCurrentLocalGenerator(0);
+ // Update rule hashes.
+ this->CheckRuleHashes();
+
if (this->ExtraGenerator != 0)
{
***************
*** 1932,1933 ****
--- 1941,2082 ----
}
+ //----------------------------------------------------------------------------
+ void
+ cmGlobalGenerator::AddRuleHash(const std::vector<std::string>& outputs,
+ const std::vector<std::string>& depends,
+ const std::vector<std::string>& commands)
+ {
+ #if defined(CMAKE_BUILD_WITH_CMAKE)
+ // Ignore if there are no outputs.
+ if(outputs.empty())
+ {
+ return;
+ }
+
+ // Compute a hash of the rule.
+ RuleHash hash;
+ {
+ unsigned char const* data;
+ int length;
+ cmsysMD5* sum = cmsysMD5_New();
+ cmsysMD5_Initialize(sum);
+ for(std::vector<std::string>::const_iterator i = outputs.begin();
+ i != outputs.end(); ++i)
+ {
+ data = reinterpret_cast<unsigned char const*>(i->c_str());
+ length = static_cast<int>(i->length());
+ cmsysMD5_Append(sum, data, length);
+ }
+ for(std::vector<std::string>::const_iterator i = depends.begin();
+ i != depends.end(); ++i)
+ {
+ data = reinterpret_cast<unsigned char const*>(i->c_str());
+ length = static_cast<int>(i->length());
+ cmsysMD5_Append(sum, data, length);
+ }
+ for(std::vector<std::string>::const_iterator i = commands.begin();
+ i != commands.end(); ++i)
+ {
+ data = reinterpret_cast<unsigned char const*>(i->c_str());
+ length = static_cast<int>(i->length());
+ cmsysMD5_Append(sum, data, length);
+ }
+ cmsysMD5_FinalizeHex(sum, hash.Data);
+ cmsysMD5_Delete(sum);
+ }
+
+ // Shorten the output name (in expected use case).
+ cmLocalGenerator* lg = this->GetLocalGenerators()[0];
+ std::string fname = lg->Convert(outputs[0].c_str(),
+ cmLocalGenerator::HOME_OUTPUT);
+
+ // Associate the hash with this output.
+ this->RuleHashes[fname] = hash;
+ #else
+ (void)outputs;
+ (void)depends;
+ (void)commands;
+ #endif
+ }
+
+ //----------------------------------------------------------------------------
+ void cmGlobalGenerator::CheckRuleHashes()
+ {
+ #if defined(CMAKE_BUILD_WITH_CMAKE)
+ std::string home = this->GetCMakeInstance()->GetHomeOutputDirectory();
+ std::string pfile = home;
+ pfile += this->GetCMakeInstance()->GetCMakeFilesDirectory();
+ pfile += "/CMakeRuleHashes.txt";
+
+ #if defined(_WIN32) || defined(__CYGWIN__)
+ std::ifstream fin(pfile.c_str(), std::ios::in | std::ios::binary);
+ #else
+ std::ifstream fin(pfile.c_str(), std::ios::in);
+ #endif
+ std::string line;
+ std::string fname;
+ while(cmSystemTools::GetLineFromStream(fin, line))
+ {
+ // Line format is a 32-byte hex string followed by a space
+ // followed by a file name (with no escaping).
+
+ // Skip blank and comment lines.
+ if(line.size() < 34 || line[0] == '#')
+ {
+ continue;
+ }
+
+ // Get the filename.
+ fname = line.substr(33, line.npos);
+
+ // Look for a hash for this file's rule.
+ std::map<cmStdString, RuleHash>::const_iterator rhi =
+ this->RuleHashes.find(fname);
+ if(rhi != this->RuleHashes.end())
+ {
+ // Compare the rule hash in the file to that we were given.
+ if(strncmp(line.c_str(), rhi->second.Data, 32) != 0)
+ {
+ // The rule has changed. Delete the output so it will be
+ // built again.
+ fname = cmSystemTools::CollapseFullPath(fname.c_str(), home.c_str());
+ cmSystemTools::RemoveFile(fname.c_str());
+ }
+ }
+ else
+ {
+ // We have no hash for a rule previously listed. This may be a
+ // case where a user has turned off a build option and might
+ // want to turn it back on later, so do not delete the file.
+ // Instead, we keep the rule hash as long as the file exists so
+ // that if the feature is turned back on and the rule has
+ // changed the file is still rebuilt.
+ std::string fpath =
+ cmSystemTools::CollapseFullPath(fname.c_str(), home.c_str());
+ if(cmSystemTools::FileExists(fpath.c_str()))
+ {
+ RuleHash hash;
+ strncpy(hash.Data, line.c_str(), 32);
+ this->RuleHashes[fname] = hash;
+ }
+ }
+ }
+
+ // Now generate a new persistence file with the current hashes.
+ if(this->RuleHashes.empty())
+ {
+ cmSystemTools::RemoveFile(pfile.c_str());
+ }
+ else
+ {
+ cmGeneratedFileStream fout(pfile.c_str());
+ fout << "# Hashes of file build rules.\n";
+ for(std::map<cmStdString, RuleHash>::const_iterator
+ rhi = this->RuleHashes.begin(); rhi != this->RuleHashes.end(); ++rhi)
+ {
+ fout.write(rhi->second.Data, 32);
+ fout << " " << rhi->first << "\n";
+ }
+ }
+ #endif
+ }
Index: cmMakefileTargetGenerator.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmMakefileTargetGenerator.cxx,v
retrieving revision 1.101
retrieving revision 1.102
diff -C 2 -d -r1.101 -r1.102
*** cmMakefileTargetGenerator.cxx 21 May 2008 23:57:35 -0000 1.101
--- cmMakefileTargetGenerator.cxx 2 Jun 2008 20:44:58 -0000 1.102
***************
*** 1123,1133 ****
this->LocalGenerator->AppendCustomDepend(depends, cc);
- // Add a dependency on the rule file itself.
- if(!cc.GetSkipRuleDepends())
- {
- this->LocalGenerator->AppendRuleDepend(depends,
- this->BuildFileNameFull.c_str());
- }
-
// Check whether we need to bother checking for a symbolic output.
bool need_symbolic = this->GlobalGenerator->GetNeedSymbolicMark();
--- 1123,1126 ----
***************
*** 1148,1151 ****
--- 1141,1150 ----
o->c_str(), depends, commands,
symbolic);
+
+ // If the rule has changed make sure the output is rebuilt.
+ if(!symbolic)
+ {
+ this->GlobalGenerator->AddRuleHash(cc.GetOutputs(), depends, commands);
+ }
}
More information about the Cmake-commits
mailing list