BUG: Updated Makefile dependency scanning to provide a full local generator to the dependency scanner to do proper path conversions. This allows the rules written into the depend.make files to use the same relative path conversion as those written into the build.make files. Several previous changes added more and more information for use by the dependency scanner and it was converging to having the full local generator anyway.

This commit is contained in:
Brad King 2006-05-25 09:47:30 -04:00
parent 12456165f1
commit ec2104cd31
10 changed files with 127 additions and 56 deletions

View File

@ -22,7 +22,11 @@
#include <string.h> #include <string.h>
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
cmDepends::cmDepends(): Verbose(false), FileComparison(0), cmDepends::cmDepends():
CompileDirectory(),
LocalGenerator(0),
Verbose(false),
FileComparison(0),
MaxPath(cmSystemTools::GetMaximumFilePathLength()), MaxPath(cmSystemTools::GetMaximumFilePathLength()),
Dependee(new char[MaxPath]), Dependee(new char[MaxPath]),
Depender(new char[MaxPath]) Depender(new char[MaxPath])

View File

@ -20,6 +20,7 @@
#include "cmStandardIncludes.h" #include "cmStandardIncludes.h"
class cmFileTimeComparison; class cmFileTimeComparison;
class cmLocalGenerator;
/** \class cmDepends /** \class cmDepends
* \brief Dependency scanner superclass. * \brief Dependency scanner superclass.
@ -38,11 +39,11 @@ public:
/** at what level will the compile be done from */ /** at what level will the compile be done from */
void SetCompileDirectory(const char *dir) {this->CompileDirectory = dir;}; void SetCompileDirectory(const char *dir) {this->CompileDirectory = dir;};
/** Set the full path to the top of the build tree. This is /** Set the local generator for the directory in which we are
the base path from which dependencies are referenced as scanning dependencies. This is not a full local generator; it
relative paths. */ has been setup to do relative path conversions for the current
void SetHomeOutputDirectory(const char *dir) { directory. */
this->HomeOutputDirectory = dir;}; void SetLocalGenerator(cmLocalGenerator* lg) { this->LocalGenerator = lg; }
/** should this be verbose in its output */ /** should this be verbose in its output */
void SetVerbose(bool verb) { this->Verbose = verb; } void SetVerbose(bool verb) { this->Verbose = verb; }
@ -79,8 +80,8 @@ protected:
// The directory in which the build rule for the target file is executed. // The directory in which the build rule for the target file is executed.
std::string CompileDirectory; std::string CompileDirectory;
// The full path to the top of the build tree. // The local generator.
std::string HomeOutputDirectory; cmLocalGenerator* LocalGenerator;
// Flag for verbose output. // Flag for verbose output.
bool Verbose; bool Verbose;

View File

@ -16,8 +16,9 @@
=========================================================================*/ =========================================================================*/
#include "cmDependsC.h" #include "cmDependsC.h"
#include "cmSystemTools.h"
#include "cmFileTimeComparison.h" #include "cmFileTimeComparison.h"
#include "cmLocalGenerator.h"
#include "cmSystemTools.h"
#include <ctype.h> // isspace #include <ctype.h> // isspace
@ -194,13 +195,18 @@ bool cmDependsC::WriteDependencies(const char *src, const char *obj,
first = false; first = false;
} }
// Write the dependencies to the output stream. // Write the dependencies to the output stream. Makefile rules
// written by the original local generator for this directory
// convert the dependencies to paths relative to the home output
// directory. We must do the same here.
internalDepends << obj << std::endl; internalDepends << obj << std::endl;
for(std::set<cmStdString>::iterator i=dependencies.begin(); for(std::set<cmStdString>::iterator i=dependencies.begin();
i != dependencies.end(); ++i) i != dependencies.end(); ++i)
{ {
makeDepends << obj << ": " makeDepends << obj << ": "
<< cmSystemTools::ConvertToOutputPath(i->c_str()).c_str() << this->LocalGenerator->Convert(i->c_str(),
cmLocalGenerator::HOME_OUTPUT,
cmLocalGenerator::MAKEFILE)
<< std::endl; << std::endl;
internalDepends << " " << i->c_str() << std::endl; internalDepends << " " << i->c_str() << std::endl;
} }
@ -370,8 +376,9 @@ bool cmDependsC::FileExistsOrIsGenerated(const std::string& fname,
// Note that CMAKE_GENERATED_FILES is written with a conversion // Note that CMAKE_GENERATED_FILES is written with a conversion
// relative to the home output directory. // relative to the home output directory.
std::string rname = std::string rname =
cmSystemTools::RelativePath(this->HomeOutputDirectory.c_str(), this->LocalGenerator->Convert(fname.c_str(),
fname.c_str()); cmLocalGenerator::HOME_OUTPUT,
cmLocalGenerator::UNCHANGED);
if(this->FileIsGenerated(rname, scanned, dependencies)) if(this->FileIsGenerated(rname, scanned, dependencies))
{ {
return true; return true;

View File

@ -589,8 +589,6 @@ void cmGlobalGenerator::Configure()
} }
this->LocalGenerators.clear(); this->LocalGenerators.clear();
// Setup relative path generation.
this->ConfigureRelativePaths();
this->TotalTargets.clear(); this->TotalTargets.clear();
// start with this directory // start with this directory
@ -1219,6 +1217,15 @@ inline std::string removeQuotes(const std::string& s)
return s; return s;
} }
void cmGlobalGenerator::SetCMakeInstance(cmake* cm)
{
// Store a pointer to the cmake object instance.
this->CMakeInstance = cm;
// Setup relative path conversion for the instance.
this->ConfigureRelativePaths();
}
void cmGlobalGenerator::SetupTests() void cmGlobalGenerator::SetupTests()
{ {
std::string ctest = this->LocalGenerators[0]->GetMakefile()-> std::string ctest = this->LocalGenerators[0]->GetMakefile()->

View File

@ -109,7 +109,7 @@ public:
///! Set the CMake instance ///! Set the CMake instance
void SetCMakeInstance(cmake *cm) { this->CMakeInstance = cm; }; void SetCMakeInstance(cmake *cm);
///! Get the CMake instance ///! Get the CMake instance
cmake *GetCMakeInstance() { return this->CMakeInstance; }; cmake *GetCMakeInstance() { return this->CMakeInstance; };

View File

@ -160,8 +160,7 @@ public:
bool /* clear */) {}; bool /* clear */) {};
/** Called from command-line hook to scan dependencies. */ /** Called from command-line hook to scan dependencies. */
virtual bool ScanDependencies(std::vector<std::string> const& /* args */) virtual bool ScanDependencies(const char* /* tgtInfo */) { return true; }
{return true;};
/** Compute the list of link libraries and directories for the given /** Compute the list of link libraries and directories for the given
target and configuration. */ target and configuration. */

View File

@ -1127,30 +1127,15 @@ cmLocalUnixMakefileGenerator3
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool cmLocalUnixMakefileGenerator3::ScanDependencies(const char* tgtInfo)
cmLocalUnixMakefileGenerator3
::ScanDependencies(std::vector<std::string> const& args)
{ {
// Format of arguments is: $(CMAKE_COMMAND), cmake_depends,
// GeneratorName, home_output_dir, start_output_dir, info file The
// caller has ensured that all required arguments exist.
// The info file for this target // The info file for this target
std::string const& infoFile = args[5]; std::string const& infoFile = tgtInfo;
// Read the directory information file. // Read the directory information file.
cmake cm; cmMakefile* mf = this->Makefile;
cmGlobalGenerator gg;
gg.SetCMakeInstance(&cm);
std::auto_ptr<cmLocalGenerator> lg(gg.CreateLocalGenerator());
lg->SetGlobalGenerator(&gg);
cmMakefile* mf = lg->GetMakefile();
mf->SetHomeOutputDirectory(args[3].c_str());
mf->SetStartOutputDirectory(args[4].c_str());
lg->SetupPathConversions();
bool haveDirectoryInfo = false; bool haveDirectoryInfo = false;
std::string dirInfoFile = args[4]; std::string dirInfoFile = this->Makefile->GetStartOutputDirectory();
dirInfoFile += "/CMakeFiles/CMakeDirectoryInformation.cmake"; dirInfoFile += "/CMakeFiles/CMakeDirectoryInformation.cmake";
if(mf->ReadListFile(0, dirInfoFile.c_str()) && if(mf->ReadListFile(0, dirInfoFile.c_str()) &&
!cmSystemTools::GetErrorOccuredFlag()) !cmSystemTools::GetErrorOccuredFlag())
@ -1283,7 +1268,7 @@ cmLocalUnixMakefileGenerator3
includeRegexScan.c_str(), includeRegexScan.c_str(),
includeRegexComplain.c_str(), includeRegexComplain.c_str(),
generatedFiles, includeCacheFileName); generatedFiles, includeCacheFileName);
scanner->SetHomeOutputDirectory(mf->GetHomeOutputDirectory()); scanner->SetLocalGenerator(this);
} }
#ifdef CMAKE_BUILD_WITH_CMAKE #ifdef CMAKE_BUILD_WITH_CMAKE
else if(lang == "Fortran") else if(lang == "Fortran")
@ -1313,7 +1298,7 @@ cmLocalUnixMakefileGenerator3
++si; ++si;
// make sure the object file is relative to home output // make sure the object file is relative to home output
std::string obj = *si; std::string obj = *si;
obj = lg->Convert(obj.c_str(),HOME_OUTPUT,MAKEFILE); obj = this->Convert(obj.c_str(),HOME_OUTPUT,MAKEFILE);
scanner->Write(src.c_str(),obj.c_str(), scanner->Write(src.c_str(),obj.c_str(),
ruleFileStream, internalRuleFileStream); ruleFileStream, internalRuleFileStream);
} }

View File

@ -178,7 +178,7 @@ public:
/** Called from command-line hook to scan dependencies. */ /** Called from command-line hook to scan dependencies. */
virtual bool ScanDependencies(std::vector<std::string> const& args); virtual bool ScanDependencies(const char* tgtInfo);
/** Called from command-line hook to check dependencies. */ /** Called from command-line hook to check dependencies. */
virtual void CheckDependencies(cmMakefile* mf, bool verbose, virtual void CheckDependencies(cmMakefile* mf, bool verbose,

View File

@ -600,20 +600,31 @@ void cmMakefileTargetGenerator::WriteTargetDependRules()
cmLocalGenerator::FULL, cmLocalGenerator::SHELL)) cmLocalGenerator::FULL, cmLocalGenerator::SHELL))
<< " && "; << " && ";
#endif #endif
depCmd << "$(CMAKE_COMMAND) -E cmake_depends " // Generate a call this signature:
<< " \"" //
// cmake -E cmake_depends <generator>
// <home-src-dir> <start-src-dir>
// <home-out-dir> <start-out-dir>
// <dep-info>
//
// This gives the dependency scanner enough information to recreate
// the state of our local generator sufficiently for its needs.
depCmd << "$(CMAKE_COMMAND) -E cmake_depends \""
<< this->GlobalGenerator->GetName() << "\" " << this->GlobalGenerator->GetName() << "\" "
<< this->LocalGenerator->Convert << this->Convert(this->Makefile->GetHomeDirectory(),
(this->Makefile->GetHomeOutputDirectory(), cmLocalGenerator::FULL, cmLocalGenerator::SHELL)
cmLocalGenerator::FULL,cmLocalGenerator::SHELL)
<< " " << " "
<< this->LocalGenerator->Convert << this->Convert(this->Makefile->GetStartDirectory(),
(this->Makefile->GetStartOutputDirectory(), cmLocalGenerator::FULL, cmLocalGenerator::SHELL)
cmLocalGenerator::FULL,cmLocalGenerator::SHELL) << " "
<< this->Convert(this->Makefile->GetHomeOutputDirectory(),
cmLocalGenerator::FULL, cmLocalGenerator::SHELL)
<< " "
<< this->Convert(this->Makefile->GetStartOutputDirectory(),
cmLocalGenerator::FULL, cmLocalGenerator::SHELL)
<< " " << " "
<< this->Convert(this->InfoFileNameFull.c_str(), << this->Convert(this->InfoFileNameFull.c_str(),
cmLocalGenerator::FULL, cmLocalGenerator::FULL, cmLocalGenerator::SHELL);
cmLocalGenerator::SHELL);
commands.push_back(depCmd.str()); commands.push_back(depCmd.str());
// Write the rule. // Write the rule.

View File

@ -1102,14 +1102,71 @@ int cmake::ExecuteCMakeCommand(std::vector<std::string>& args)
// Internal CMake dependency scanning support. // Internal CMake dependency scanning support.
else if (args[1] == "cmake_depends" && args.size() >= 6) else if (args[1] == "cmake_depends" && args.size() >= 6)
{ {
// Create a cmake object instance to process dependencies.
cmake cm; cmake cm;
cmGlobalGenerator *ggd = cm.CreateGlobalGenerator(args[2].c_str()); std::string gen;
if (ggd) std::string homeDir;
std::string startDir;
std::string homeOutDir;
std::string startOutDir;
std::string depInfo;
if(args.size() >= 8)
{ {
ggd->SetCMakeInstance(&cm); // Full signature:
//
// -E cmake_depends <generator>
// <home-src-dir> <start-src-dir>
// <home-out-dir> <start-out-dir>
// <dep-info>
//
// All paths are provided.
gen = args[2];
homeDir = args[3];
startDir = args[4];
homeOutDir = args[5];
startOutDir = args[6];
depInfo = args[7];
}
else
{
// Support older signature for existing makefiles:
//
// -E cmake_depends <generator>
// <home-out-dir> <start-out-dir>
// <dep-info>
//
// Just pretend the source directories are the same as the
// binary directories so at least scanning will work.
gen = args[2];
homeDir = args[3];
startDir = args[4];
homeOutDir = args[3];
startOutDir = args[3];
depInfo = args[5];
}
// Create a local generator configured for the directory in
// which dependencies will be scanned.
homeDir = cmSystemTools::CollapseFullPath(homeDir.c_str());
startDir = cmSystemTools::CollapseFullPath(startDir.c_str());
homeOutDir = cmSystemTools::CollapseFullPath(homeOutDir.c_str());
startOutDir = cmSystemTools::CollapseFullPath(startOutDir.c_str());
cm.SetHomeDirectory(homeDir.c_str());
cm.SetStartDirectory(startDir.c_str());
cm.SetHomeOutputDirectory(homeOutDir.c_str());
cm.SetStartOutputDirectory(startOutDir.c_str());
if(cmGlobalGenerator* ggd = cm.CreateGlobalGenerator(gen.c_str()))
{
cm.SetGlobalGenerator(ggd);
std::auto_ptr<cmLocalGenerator> lgd(ggd->CreateLocalGenerator()); std::auto_ptr<cmLocalGenerator> lgd(ggd->CreateLocalGenerator());
lgd->SetGlobalGenerator(ggd); lgd->SetGlobalGenerator(ggd);
return lgd->ScanDependencies(args)? 0 : 2; lgd->GetMakefile()->SetStartDirectory(startDir.c_str());
lgd->GetMakefile()->SetStartOutputDirectory(startOutDir.c_str());
lgd->GetMakefile()->MakeStartDirectoriesCurrent();
lgd->SetupPathConversions();
// Actually scan dependencies.
return lgd->ScanDependencies(depInfo.c_str())? 0 : 2;
} }
return 1; return 1;
} }