ENH: reduce the number of files produced still needs a bit more cleanup

This commit is contained in:
Ken Martin 2005-07-27 09:49:37 -04:00
parent 90cefde755
commit f85f919dbc
15 changed files with 435 additions and 517 deletions

View File

@ -32,55 +32,14 @@ cmDepends::~cmDepends()
{ {
} }
void cmDepends::SetTargetFile(const char* dir, const char* targetFile,
const char *markExt, const char *makeExt)
{
m_Directory = dir;
m_TargetFile = targetFile;
// Construct the path to the make and mark files. Append
// appropriate extensions to their names.
m_DependsMarkFile = dir;
m_DependsMakeFile = dir;
m_DependsMakeFile += "/";
m_DependsMarkFile += "/";
m_DependsMakeFile += m_TargetFile;
m_DependsMarkFile += m_TargetFile;
m_DependsMakeFile += makeExt;
m_DependsMarkFile += markExt;
if (!m_CompileDirectory.size())
{
m_CompileDirectory = dir;
}
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool cmDepends::Write() bool cmDepends::Write(const char *src, const char *obj, std::ostream &fout)
{ {
// Dependency generation must always be done in the current working return this->WriteDependencies(src, obj, fout);
// directory.
assert(m_Directory == ".");
// Try to generate dependencies for the target file.
cmGeneratedFileStream fout(m_DependsMakeFile.c_str());
fout << "# Dependencies for " << m_TargetFile.c_str() << std::endl;
if(this->WriteDependencies(fout) && fout)
{
// Dependencies were generated. Touch the mark file.
std::ofstream fmark(m_DependsMarkFile.c_str());
fmark << "Dependencies updated for " << m_TargetFile.c_str() << std::endl;
return true;
}
else
{
return false;
}
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmDepends::Check() void cmDepends::Check(const char *file)
{ {
// Dependency checks must be done in proper working directory. // Dependency checks must be done in proper working directory.
std::string oldcwd = "."; std::string oldcwd = ".";
@ -93,11 +52,11 @@ void cmDepends::Check()
} }
// Check whether dependencies must be regenerated. // Check whether dependencies must be regenerated.
std::ifstream fin(m_DependsMakeFile.c_str()); std::ifstream fin(file);
if(!(fin && this->CheckDependencies(fin))) if(!(fin && this->CheckDependencies(fin)))
{ {
// Clear all dependencies so they will be regenerated. // Clear all dependencies so they will be regenerated.
this->Clear(); this->Clear(file);
} }
// Restore working directory. // Restore working directory.
@ -108,37 +67,26 @@ void cmDepends::Check()
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmDepends::Clear() void cmDepends::Clear(const char *file)
{ {
// Print verbose output. // Print verbose output.
if(m_Verbose) if(m_Verbose)
{ {
cmOStringStream msg; cmOStringStream msg;
msg << "Clearing dependencies for \"" << m_TargetFile << "\"." << std::endl; msg << "Clearing dependencies in \"" << file << "\"." << std::endl;
cmSystemTools::Stdout(msg.str().c_str()); cmSystemTools::Stdout(msg.str().c_str());
} }
// Remove the dependency mark file to be sure dependencies will be // Remove the dependency mark file to be sure dependencies will be
// regenerated. // regenerated.
cmSystemTools::RemoveFile(m_DependsMarkFile.c_str()); std::string markFile = file;
markFile += ".mark";
cmSystemTools::RemoveFile(markFile.c_str());
// Write an empty dependency file. // Write an empty dependency file.
cmGeneratedFileStream depFileStream(m_DependsMakeFile.c_str()); cmGeneratedFileStream depFileStream(file);
depFileStream depFileStream
<< "# Empty dependencies file for " << m_TargetFile.c_str() << ".\n" << "# Empty dependencies file\n"
<< "# This may be replaced when dependencies are built." << std::endl; << "# This may be replaced when dependencies are built." << std::endl;
} }
//----------------------------------------------------------------------------
const char* cmDepends::GetMakeFileName()
{
// Skip over the directory part of the name.
return m_DependsMakeFile.c_str() + m_Directory.length() + 1;
}
//----------------------------------------------------------------------------
const char* cmDepends::GetMarkFileName()
{
// Skip over the directory part of the name.
return m_DependsMarkFile.c_str() + m_Directory.length() + 1;
}

View File

@ -33,10 +33,6 @@ public:
path from the build directory to the target file. */ path from the build directory to the target file. */
cmDepends(); cmDepends();
/** set the name directory and extensions of the target file to scan */
void SetTargetFile(const char* dir, const char* targetFile,
const char *markExt, const char *makeExt);
/** at what level will the compile be done from */ /** at what level will the compile be done from */
void SetCompileDirectory(const char *dir) {m_CompileDirectory = dir;}; void SetCompileDirectory(const char *dir) {m_CompileDirectory = dir;};
@ -47,44 +43,30 @@ public:
virtual ~cmDepends(); virtual ~cmDepends();
/** Write dependencies for the target file. */ /** Write dependencies for the target file. */
bool Write(); bool Write(const char *src, const char *obj, std::ostream &os);
/** Check dependencies for the target file. */ /** Check dependencies for the target file. */
void Check(); void Check(const char *file);
/** Clear dependencies for the target file so they will be regenerated. */ /** Clear dependencies for the target file so they will be regenerated. */
void Clear(); void Clear(const char *file);
/** Get the name of the dependency make file. */
const char* GetMakeFileName();
/** Get the name of the dependency mark file. */
const char* GetMarkFileName();
protected: protected:
// Write dependencies for the target file to the given stream. // Write dependencies for the target file to the given stream.
// Return true for success and false for failure. // Return true for success and false for failure.
virtual bool WriteDependencies(std::ostream& os)=0; virtual bool WriteDependencies(const char *src,
const char* obj, std::ostream& os)=0;
// Check dependencies for the target file in the given stream. // Check dependencies for the target file in the given stream.
// Return false if dependencies must be regenerated and true // Return false if dependencies must be regenerated and true
// otherwise. // otherwise.
virtual bool CheckDependencies(std::istream& is)=0; virtual bool CheckDependencies(std::istream& is) = 0;
// 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 m_Directory; std::string m_Directory;
std::string m_CompileDirectory; std::string m_CompileDirectory;
// The name of the target file for which dependencies are maintained.
std::string m_TargetFile;
// The name of the .depends.make file corresponding to the target.
std::string m_DependsMakeFile;
// The name of the .depends file marking when dependencies were generated.
std::string m_DependsMarkFile;
// Flag for verbose output. // Flag for verbose output.
bool m_Verbose; bool m_Verbose;

View File

@ -27,10 +27,8 @@ cmDependsC::cmDependsC()
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// yummy look at all those constructor arguments // yummy look at all those constructor arguments
cmDependsC::cmDependsC(const char* sourceFile, cmDependsC::cmDependsC(std::vector<std::string> const& includes,
std::vector<std::string> const& includes,
const char* scanRegex, const char* complainRegex): const char* scanRegex, const char* complainRegex):
m_SourceFile(sourceFile),
m_IncludePath(&includes), m_IncludePath(&includes),
m_IncludeRegexLine("^[ \t]*#[ \t]*include[ \t]*[<\"]([^\">]+)([\">])"), m_IncludeRegexLine("^[ \t]*#[ \t]*include[ \t]*[<\"]([^\">]+)([\">])"),
m_IncludeRegexScan(scanRegex), m_IncludeRegexScan(scanRegex),
@ -44,12 +42,18 @@ cmDependsC::~cmDependsC()
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool cmDependsC::WriteDependencies(std::ostream& os) bool cmDependsC::WriteDependencies(const char *src,
const char *obj, std::ostream& os)
{ {
// Make sure this is a scanning instance. // Make sure this is a scanning instance.
if(m_SourceFile == "") if(!src || src[0] == '\0')
{ {
cmSystemTools::Error("Cannot scan dependencies without an source file."); cmSystemTools::Error("Cannot scan dependencies without a source file.");
return false;
}
if(!obj || obj[0] == '\0')
{
cmSystemTools::Error("Cannot scan dependencies without an object file.");
return false; return false;
} }
if(!m_IncludePath) if(!m_IncludePath)
@ -61,10 +65,10 @@ bool cmDependsC::WriteDependencies(std::ostream& os)
// Walk the dependency graph starting with the source file. // Walk the dependency graph starting with the source file.
bool first = true; bool first = true;
UnscannedEntry root; UnscannedEntry root;
root.FileName = m_SourceFile; root.FileName = src;
m_Unscanned.push(root); m_Unscanned.push(root);
m_Encountered.clear(); m_Encountered.clear();
m_Encountered.insert(m_SourceFile); m_Encountered.insert(src);
std::set<cmStdString> dependencies; std::set<cmStdString> dependencies;
std::set<cmStdString> scanned; std::set<cmStdString> scanned;
while(!m_Unscanned.empty()) while(!m_Unscanned.empty())
@ -155,7 +159,7 @@ bool cmDependsC::WriteDependencies(std::ostream& os)
for(std::set<cmStdString>::iterator i=dependencies.begin(); for(std::set<cmStdString>::iterator i=dependencies.begin();
i != dependencies.end(); ++i) i != dependencies.end(); ++i)
{ {
os << m_TargetFile.c_str() << ": " os << obj << ": "
<< cmSystemTools::ConvertToOutputPath(i->c_str()).c_str() << cmSystemTools::ConvertToOutputPath(i->c_str()).c_str()
<< std::endl; << std::endl;
} }
@ -313,8 +317,12 @@ const char* cmDependsC::ParseFileName(const char* in, std::string& name)
bool quoted = false; bool quoted = false;
char* buf = new char[strlen(in)+1]; char* buf = new char[strlen(in)+1];
char* pos = buf; char* pos = buf;
// for every character while we haven't hit the end of the string AND we
// are in a quoted string OR the current character isn't a : or the second
// character AND it isn't a space
for(;*c && (quoted || for(;*c && (quoted ||
((*c != ':' || pos > buf+1) && !isspace(*c))); ++c) ((*c != ':' || pos > buf) && !isspace(*c))); ++c)
{ {
if(*c == '"') if(*c == '"')
{ {

View File

@ -30,14 +30,7 @@ public:
/** Checking instances need to know the build directory name and the /** Checking instances need to know the build directory name and the
relative path from the build directory to the target file. */ relative path from the build directory to the target file. */
cmDependsC(); cmDependsC();
cmDependsC(std::vector<std::string> const& includes,
/** Scanning need to know the build directory name, the relative
path from the build directory to the target file, the source
file from which to start scanning, and the include file search
path. It also uses the include file regular expressions.
This is a good example of why constructors should not take arguments.
*/
cmDependsC(const char* sourceFile, std::vector<std::string> const& includes,
const char* scanRegex, const char* complainRegex); const char* scanRegex, const char* complainRegex);
/** Virtual destructor to cleanup subclasses properly. */ /** Virtual destructor to cleanup subclasses properly. */
@ -45,7 +38,8 @@ public:
protected: protected:
// Implement writing/checking methods required by superclass. // Implement writing/checking methods required by superclass.
virtual bool WriteDependencies(std::ostream& os); virtual bool WriteDependencies(const char *src,
const char *file, std::ostream& os);
virtual bool CheckDependencies(std::istream& is); virtual bool CheckDependencies(std::istream& is);
// Method to scan a single file. // Method to scan a single file.
@ -56,9 +50,6 @@ protected:
std::string& dependee); std::string& dependee);
const char* ParseFileName(const char* in, std::string& name); const char* ParseFileName(const char* in, std::string& name);
// The source file from which to start scanning.
std::string m_SourceFile;
// The include file search path. // The include file search path.
std::vector<std::string> const* m_IncludePath; std::vector<std::string> const* m_IncludePath;

View File

@ -77,15 +77,12 @@ struct cmDependsFortranParser_s
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
cmDependsFortran::cmDependsFortran(): cmDependsFortran::cmDependsFortran():
m_SourceFile(),
m_IncludePath(0) m_IncludePath(0)
{ {
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
cmDependsFortran::cmDependsFortran(const char* sourceFile, cmDependsFortran::cmDependsFortran(std::vector<std::string> const& includes):
std::vector<std::string> const& includes):
m_SourceFile(sourceFile),
m_IncludePath(&includes) m_IncludePath(&includes)
{ {
} }
@ -96,14 +93,20 @@ cmDependsFortran::~cmDependsFortran()
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool cmDependsFortran::WriteDependencies(std::ostream& os) bool cmDependsFortran::WriteDependencies(const char *src,
const char *obj, std::ostream& os)
{ {
// Make sure this is a scanning instance. // Make sure this is a scanning instance.
if(m_SourceFile == "") if(!src || src[0] == '\0')
{ {
cmSystemTools::Error("Cannot scan dependencies without an source file."); cmSystemTools::Error("Cannot scan dependencies without an source file.");
return false; return false;
} }
if(!obj || obj[0] == '\0')
{
cmSystemTools::Error("Cannot scan dependencies without an object file.");
return false;
}
if(!m_IncludePath) if(!m_IncludePath)
{ {
cmSystemTools::Error("Cannot scan dependencies without an include path."); cmSystemTools::Error("Cannot scan dependencies without an include path.");
@ -114,7 +117,7 @@ bool cmDependsFortran::WriteDependencies(std::ostream& os)
cmDependsFortranParser parser(this); cmDependsFortranParser parser(this);
// Push on the starting file. // Push on the starting file.
cmDependsFortranParser_FilePush(&parser, m_SourceFile.c_str()); cmDependsFortranParser_FilePush(&parser, src);
// Parse the translation unit. // Parse the translation unit.
if(cmDependsFortran_yyparse(parser.Scanner) != 0) if(cmDependsFortran_yyparse(parser.Scanner) != 0)
@ -127,7 +130,7 @@ bool cmDependsFortran::WriteDependencies(std::ostream& os)
for(std::set<cmStdString>::const_iterator i = parser.Includes.begin(); for(std::set<cmStdString>::const_iterator i = parser.Includes.begin();
i != parser.Includes.end(); ++i) i != parser.Includes.end(); ++i)
{ {
os << m_TargetFile.c_str() << ": " os << obj << ": "
<< cmSystemTools::ConvertToOutputPath(i->c_str()).c_str() << cmSystemTools::ConvertToOutputPath(i->c_str()).c_str()
<< std::endl; << std::endl;
} }
@ -141,25 +144,8 @@ bool cmDependsFortran::WriteDependencies(std::ostream& os)
if(parser.Provides.find(*i) == parser.Provides.end()) if(parser.Provides.find(*i) == parser.Provides.end())
{ {
// since we require some things add them to our list of requirements // since we require some things add them to our list of requirements
os << m_TargetFile.c_str() << ".requires: " << i->c_str() << ".mod.proxy" os << obj << ".requires: " << i->c_str() << ".mod.proxy"
<< std::endl; << std::endl;
#if 0
// Always use lower case for the mod stamp file name.
std::string m = cmSystemTools::LowerCase(*i);
os << m_TargetFile.c_str() << ": " << m.c_str() << ".mod.stamp"
<< std::endl;
os << i->c_str() << ".mod.proxy:" << std::endl;
std::string stampName = m_Directory;
stampName += "/";
stampName += m;
stampName += ".mod.stamp";
if(!cmSystemTools::FileExists(stampName.c_str()))
{
std::ofstream stamp(stampName.c_str());
stamp << "# Dummy stamp file in case nothing provides it."
<< std::endl;
}
#endif
} }
} }
@ -167,14 +153,14 @@ bool cmDependsFortran::WriteDependencies(std::ostream& os)
for(std::set<cmStdString>::const_iterator i = parser.Provides.begin(); for(std::set<cmStdString>::const_iterator i = parser.Provides.begin();
i != parser.Provides.end(); ++i) i != parser.Provides.end(); ++i)
{ {
os << i->c_str() << ".mod.proxy: " << m_TargetFile.c_str() os << i->c_str() << ".mod.proxy: " << obj
<< ".provides" << std::endl; << ".provides" << std::endl;
} }
// If any modules are provided then they must be converted to stamp files. // If any modules are provided then they must be converted to stamp files.
if(!parser.Provides.empty()) if(!parser.Provides.empty())
{ {
os << m_TargetFile.c_str() << ".provides.build:\n"; os << obj << ".provides.build:\n";
for(std::set<cmStdString>::const_iterator i = parser.Provides.begin(); for(std::set<cmStdString>::const_iterator i = parser.Provides.begin();
i != parser.Provides.end(); ++i) i != parser.Provides.end(); ++i)
{ {
@ -185,20 +171,9 @@ bool cmDependsFortran::WriteDependencies(std::ostream& os)
os << "\t$(CMAKE_COMMAND) -E cmake_copy_f90_mod " os << "\t$(CMAKE_COMMAND) -E cmake_copy_f90_mod "
<< i->c_str() << " " << m.c_str() << ".mod.stamp\n"; << i->c_str() << " " << m.c_str() << ".mod.stamp\n";
} }
os << "\t@touch " << m_TargetFile.c_str() << ".provides.build\n"; os << "\t@touch " << obj << ".provides.build\n";
} }
#if 0
// if it provides something then connect the requires rule to the build rule
if(!parser.Provides.empty())
{
os << m_TargetFile.c_str() << ".requires: " << m_TargetFile.c_str()
<< ".requires.build" << std::endl;
// provide empty build rule for old gen for now, TODO remove later
os << m_TargetFile.c_str() << ".requires.build:" << std::endl;
}
#endif
/* /*
// TODO: // TODO:
What about .mod files provided in another directory and found with a What about .mod files provided in another directory and found with a

View File

@ -33,7 +33,7 @@ public:
path from the build directory to the target file, the source path from the build directory to the target file, the source
file from which to start scanning, and the include file search file from which to start scanning, and the include file search
path. */ path. */
cmDependsFortran(const char* sourceFile, std::vector<std::string> const& includes); cmDependsFortran(std::vector<std::string> const& includes);
/** Virtual destructor to cleanup subclasses properly. */ /** Virtual destructor to cleanup subclasses properly. */
virtual ~cmDependsFortran(); virtual ~cmDependsFortran();
@ -51,7 +51,8 @@ public:
protected: protected:
// Implement writing/checking methods required by superclass. // Implement writing/checking methods required by superclass.
virtual bool WriteDependencies(std::ostream& os); virtual bool WriteDependencies(const char *src,
const char *file, std::ostream& os);
virtual bool CheckDependencies(std::istream& is); virtual bool CheckDependencies(std::istream& is);
// The source file from which to start scanning. // The source file from which to start scanning.

View File

@ -20,14 +20,7 @@
#include "cmSystemTools.h" #include "cmSystemTools.h"
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
cmDependsJava::cmDependsJava(): cmDependsJava::cmDependsJava()
m_SourceFile()
{
}
//----------------------------------------------------------------------------
cmDependsJava::cmDependsJava(const char* sourceFile):
m_SourceFile(sourceFile)
{ {
} }
@ -37,10 +30,11 @@ cmDependsJava::~cmDependsJava()
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool cmDependsJava::WriteDependencies(std::ostream&) bool cmDependsJava::WriteDependencies(const char *src,
const char *file, std::ostream&)
{ {
// Make sure this is a scanning instance. // Make sure this is a scanning instance.
if(m_SourceFile == "") if(!src || src[0] == '\0')
{ {
cmSystemTools::Error("Cannot scan dependencies without an source file."); cmSystemTools::Error("Cannot scan dependencies without an source file.");
return false; return false;

View File

@ -29,22 +29,15 @@ public:
relative path from the build directory to the target file. */ relative path from the build directory to the target file. */
cmDependsJava(); cmDependsJava();
/** Scanning need to know the build directory name, the relative
path from the build directory to the target file and the source
file to scan. */
cmDependsJava(const char* sourceFile);
/** Virtual destructor to cleanup subclasses properly. */ /** Virtual destructor to cleanup subclasses properly. */
virtual ~cmDependsJava(); virtual ~cmDependsJava();
protected: protected:
// Implement writing/checking methods required by superclass. // Implement writing/checking methods required by superclass.
virtual bool WriteDependencies(std::ostream& os); virtual bool WriteDependencies(const char *src,
const char *file, std::ostream& os);
virtual bool CheckDependencies(std::istream& is); virtual bool CheckDependencies(std::istream& is);
// The source file from which to start scanning.
std::string m_SourceFile;
private: private:
cmDependsJava(cmDependsJava const&); // Purposely not implemented. cmDependsJava(cmDependsJava const&); // Purposely not implemented.
void operator=(cmDependsJava const&); // Purposely not implemented. void operator=(cmDependsJava const&); // Purposely not implemented.

View File

@ -328,67 +328,34 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile()
} }
cmakefileStream << " )\n\n"; cmakefileStream << " )\n\n";
this->WriteMainCMakefileLanguageRules(cmakefileStream); this->WriteMainCMakefileLanguageRules(cmakefileStream, m_LocalGenerators);
} }
void cmGlobalUnixMakefileGenerator3 void cmGlobalUnixMakefileGenerator3
::WriteMainCMakefileLanguageRules(cmGeneratedFileStream& cmakefileStream) ::WriteMainCMakefileLanguageRules(cmGeneratedFileStream& cmakefileStream,
std::vector<cmLocalGenerator *> &lGenerators)
{ {
cmLocalUnixMakefileGenerator3 *lg; cmLocalUnixMakefileGenerator3 *lg;
// now write all the language stuff // now list all the target info files
// Set the set of files to check for dependency integrity.
// loop over all of the local generators to collect this
std::set<cmStdString> checkSetLangs;
for (unsigned int i = 0; i < m_LocalGenerators.size(); ++i)
{
lg = static_cast<cmLocalUnixMakefileGenerator3 *>(m_LocalGenerators[i]);
std::map<cmStdString,cmLocalUnixMakefileGenerator3::IntegrityCheckSet>& checkSet =
lg->GetIntegrityCheckSet();
for(std::map<cmStdString,
cmLocalUnixMakefileGenerator3::IntegrityCheckSet>::const_iterator
l = checkSet.begin(); l != checkSet.end(); ++l)
{
checkSetLangs.insert(l->first);
}
}
// list the languages
cmakefileStream cmakefileStream
<< "# The set of files whose dependency integrity should be checked:\n"; << "# The set of files whose dependency integrity should be checked:\n";
cmakefileStream cmakefileStream
<< "SET(CMAKE_DEPENDS_LANGUAGES\n"; << "SET(CMAKE_DEPEND_INFO_FILES\n";
for(std::set<cmStdString>::iterator for (unsigned int i = 0; i < lGenerators.size(); ++i)
l = checkSetLangs.begin(); l != checkSetLangs.end(); ++l)
{ {
cmakefileStream << " \"" << l->c_str() << "\"\n"; lg = static_cast<cmLocalUnixMakefileGenerator3 *>(lGenerators[i]);
} // for all of out targets
cmakefileStream << " )\n"; for (cmTargets::iterator l = lg->GetMakefile()->GetTargets().begin();
l != lg->GetMakefile()->GetTargets().end(); l++)
// now list the files for each language
for(std::set<cmStdString>::iterator
l = checkSetLangs.begin(); l != checkSetLangs.end(); ++l)
{ {
cmakefileStream std::string tname = lg->GetRelativeTargetDirectory(l->second);
<< "SET(CMAKE_DEPENDS_CHECK_" << l->c_str() << "\n"; tname += "/DependInfo.cmake";
// now for each local gen get the checkset cmSystemTools::ConvertToUnixSlashes(tname);
for (unsigned int i = 0; i < m_LocalGenerators.size(); ++i) cmakefileStream << " \"" << tname.c_str() << "\"\n";
{
lg = static_cast<cmLocalUnixMakefileGenerator3 *>(m_LocalGenerators[i]);
// get the check set for this local gen and language
cmLocalUnixMakefileGenerator3::IntegrityCheckSet iCheckSet =
lg->GetIntegrityCheckSet()[*l];
// for each file
for(cmLocalUnixMakefileGenerator3::IntegrityCheckSet::const_iterator csIter =
iCheckSet.begin();
csIter != iCheckSet.end(); ++csIter)
{
cmakefileStream << " \"" <<
lg->Convert(csIter->c_str(),cmLocalGenerator::HOME_OUTPUT).c_str() << "\"\n";
} }
} }
cmakefileStream << " )\n"; cmakefileStream << " )\n";
}
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -768,7 +735,6 @@ cmGlobalUnixMakefileGenerator3
// for each target Generate the rule files for each target. // for each target Generate the rule files for each target.
cmTargets& targets = lg->GetMakefile()->GetTargets(); cmTargets& targets = lg->GetMakefile()->GetTargets();
bool needRequiresStep = this->NeedRequiresStep(lg);
for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t) for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t)
{ {
if (((t->second.GetType() == cmTarget::EXECUTABLE) || if (((t->second.GetType() == cmTarget::EXECUTABLE) ||
@ -779,6 +745,8 @@ cmGlobalUnixMakefileGenerator3
t->second.GetName() && t->second.GetName() &&
strlen(t->second.GetName())) strlen(t->second.GetName()))
{ {
bool needRequiresStep =
this->NeedRequiresStep(lg,t->second.GetName());
// Add a rule to build the target by name. // Add a rule to build the target by name.
localName = lg->GetRelativeTargetDirectory(t->second); localName = lg->GetRelativeTargetDirectory(t->second);
std::string makefileName = localName; std::string makefileName = localName;
@ -1006,10 +974,10 @@ cmGlobalUnixMakefileGenerator3::WriteHelpRule(std::ostream& ruleFileStream)
bool cmGlobalUnixMakefileGenerator3 bool cmGlobalUnixMakefileGenerator3
::NeedRequiresStep(cmLocalUnixMakefileGenerator3 *lg) ::NeedRequiresStep(cmLocalUnixMakefileGenerator3 *lg,const char *name)
{ {
std::map<cmStdString,cmLocalUnixMakefileGenerator3::IntegrityCheckSet>& std::map<cmStdString,cmLocalUnixMakefileGenerator3::IntegrityCheckSet>&
checkSet = lg->GetIntegrityCheckSet(); checkSet = lg->GetIntegrityCheckSet()[name];
for(std::map<cmStdString, for(std::map<cmStdString,
cmLocalUnixMakefileGenerator3::IntegrityCheckSet>::const_iterator cmLocalUnixMakefileGenerator3::IntegrityCheckSet>::const_iterator
l = checkSet.begin(); l != checkSet.end(); ++l) l = checkSet.begin(); l != checkSet.end(); ++l)
@ -1022,6 +990,5 @@ bool cmGlobalUnixMakefileGenerator3
return true; return true;
} }
} }
return false; return false;
} }

View File

@ -84,11 +84,14 @@ public:
*/ */
virtual void Generate(); virtual void Generate();
void WriteMainCMakefileLanguageRules(cmGeneratedFileStream& cmakefileStream,
std::vector<cmLocalGenerator *> &);
protected: protected:
void WriteMainMakefile(); void WriteMainMakefile();
void WriteMainMakefile2(); void WriteMainMakefile2();
void WriteMainCMakefile(); void WriteMainCMakefile();
void WriteMainCMakefileLanguageRules(cmGeneratedFileStream& cmakefileStream);
void WriteAllRules(cmLocalUnixMakefileGenerator3 *lg, void WriteAllRules(cmLocalUnixMakefileGenerator3 *lg,
std::ostream& makefileStream); std::ostream& makefileStream);
void WriteHelpRule(std::ostream& ruleFileStream); void WriteHelpRule(std::ostream& ruleFileStream);
@ -111,7 +114,7 @@ protected:
const char* name, std::set<cmStdString>& emitted); const char* name, std::set<cmStdString>& emitted);
// does this generator need a requires step for any of its targets // does this generator need a requires step for any of its targets
bool NeedRequiresStep(cmLocalUnixMakefileGenerator3 *lg); bool NeedRequiresStep(cmLocalUnixMakefileGenerator3 *lg, const char *);
}; };

View File

@ -62,6 +62,17 @@ void cmLocalGenerator::Configure()
} }
} }
this->SetupPathConversions();
// Check whether relative paths should be used for optionally
// relative paths.
m_UseRelativePaths = m_Makefile->IsOn("CMAKE_USE_RELATIVE_PATHS");
this->Configured = true;
}
void cmLocalGenerator::SetupPathConversions()
{
// Setup the current output directory components for use by // Setup the current output directory components for use by
// Convert // Convert
std::string outdir; std::string outdir;
@ -76,15 +87,10 @@ void cmLocalGenerator::Configure()
cmSystemTools::SplitPath(outdir.c_str(), m_HomeOutputDirectoryComponents); cmSystemTools::SplitPath(outdir.c_str(), m_HomeOutputDirectoryComponents);
outdir = outdir =
cmSystemTools::CollapseFullPath(m_Makefile->GetStartOutputDirectory()); cmSystemTools::CollapseFullPath(m_Makefile->GetStartOutputDirectory());
cmSystemTools::SplitPath(outdir.c_str(), m_StartOutputDirectoryComponents); cmSystemTools::SplitPath(outdir.c_str(), m_StartOutputDirectoryComponents);
// Check whether relative paths should be used for optionally
// relative paths.
m_UseRelativePaths = m_Makefile->IsOn("CMAKE_USE_RELATIVE_PATHS");
this->Configured = true;
} }
void cmLocalGenerator::SetGlobalGenerator(cmGlobalGenerator *gg) void cmLocalGenerator::SetGlobalGenerator(cmGlobalGenerator *gg)
{ {
m_GlobalGenerator = gg; m_GlobalGenerator = gg;

View File

@ -97,6 +97,9 @@ public:
OutputFormat output = UNCHANGED, OutputFormat output = UNCHANGED,
bool optional = false); bool optional = false);
///! Call this prior to using Convert
void SetupPathConversions();
/** /**
* Convert the given path to an output path that is optionally * Convert the given path to an output path that is optionally
* relative based on the cache option CMAKE_USE_RELATIVE_PATHS. The * relative based on the cache option CMAKE_USE_RELATIVE_PATHS. The

View File

@ -18,7 +18,7 @@
#include "cmDepends.h" #include "cmDepends.h"
#include "cmGeneratedFileStream.h" #include "cmGeneratedFileStream.h"
#include "cmGlobalGenerator.h" #include "cmGlobalUnixMakefileGenerator3.h"
#include "cmMakefile.h" #include "cmMakefile.h"
#include "cmSourceFile.h" #include "cmSourceFile.h"
#include "cmake.h" #include "cmake.h"
@ -174,23 +174,18 @@ void cmLocalUnixMakefileGenerator3
// Generate the rule files for each custom command. // Generate the rule files for each custom command.
// get the classes from the source lists then add them to the groups // get the classes from the source lists then add them to the groups
const std::vector<cmSourceFile*> &classes = target.GetSourceFiles(); const std::vector<cmSourceFile*> &classes = target.GetSourceFiles();
std::string objTarget;
for(std::vector<cmSourceFile*>::const_iterator i = classes.begin(); for(std::vector<cmSourceFile*>::const_iterator i = classes.begin();
i != classes.end(); i++) i != classes.end(); i++)
{ {
if(cmCustomCommand* cc = (*i)->GetCustomCommand()) if(cmCustomCommand* cc = (*i)->GetCustomCommand())
{ {
cc->Used(); cc->Used();
objTarget = this->GenerateCustomRuleFile(*cc,tgtDir.c_str()); this->GenerateCustomRuleFile(*cc,tgtDir.c_str(),ruleFileStream);
if (clean) if (clean)
{ {
cleanFiles.push_back cleanFiles.push_back
(this->Convert(cc->GetOutput(),HOME_OUTPUT,SHELL)); (this->Convert(cc->GetOutput(),HOME_OUTPUT,SHELL));
} }
ruleFileStream
<< m_IncludeDirective << " "
<< this->ConvertToOutputForExisting(objTarget.c_str()).c_str()
<< "\n";
} }
} }
} }
@ -309,30 +304,6 @@ cmLocalUnixMakefileGenerator3
std::string dir = this->GetTargetDirectory(target); std::string dir = this->GetTargetDirectory(target);
cmSystemTools::MakeDirectory(this->ConvertToFullPath(dir).c_str()); cmSystemTools::MakeDirectory(this->ConvertToFullPath(dir).c_str());
// First generate the object rule files. Save a list of all object
// files for this target.
std::vector<std::string> objects;
std::vector<std::string> external_objects;
const std::vector<cmSourceFile*>& sources = target.GetSourceFiles();
for(std::vector<cmSourceFile*>::const_iterator source = sources.begin();
source != sources.end(); ++source)
{
if(!(*source)->GetPropertyAsBool("HEADER_FILE_ONLY") &&
!(*source)->GetCustomCommand())
{
if(!m_GlobalGenerator->IgnoreFile((*source)->GetSourceExtension().c_str()))
{
// Generate this object file's rule file.
this->WriteObjectRuleFiles(target, *(*source), objects);
}
else if((*source)->GetPropertyAsBool("EXTERNAL_OBJECT"))
{
// This is an external object file. Just add it.
external_objects.push_back((*source)->GetFullPath());
}
}
}
// Generate the build-time dependencies file for this target. // Generate the build-time dependencies file for this target.
std::string depBase = dir; std::string depBase = dir;
depBase += "/"; depBase += "/";
@ -355,6 +326,52 @@ cmLocalUnixMakefileGenerator3
this->WriteMakeVariables(ruleFileStream, HOME_OUTPUT); this->WriteMakeVariables(ruleFileStream, HOME_OUTPUT);
// Include the dependencies for the target.
std::string depPath = dir;
depPath += "/depend.make";
depPath = this->ConvertToFullPath(depPath.c_str());
depPath = this->Convert(depPath.c_str(),HOME_OUTPUT,MAKEFILE);
ruleFileStream
<< "# Include any dependencies generated for this target.\n"
<< m_IncludeDirective << " "
<< depPath
<< "\n\n";
// make sure the depend file exists
if (!cmSystemTools::FileExists(depPath.c_str()))
{
// Write an empty dependency file.
cmGeneratedFileStream depFileStream(depPath.c_str());
depFileStream
<< "# Empty dependencies file for " << target.GetName() << ".\n"
<< "# This may be replaced when dependencies are built." << std::endl;
}
// First generate the object rule files. Save a list of all object
// files for this target.
std::vector<std::string> objects;
std::vector<std::string> external_objects;
const std::vector<cmSourceFile*>& sources = target.GetSourceFiles();
for(std::vector<cmSourceFile*>::const_iterator source = sources.begin();
source != sources.end(); ++source)
{
if(!(*source)->GetPropertyAsBool("HEADER_FILE_ONLY") &&
!(*source)->GetCustomCommand())
{
if(!m_GlobalGenerator->IgnoreFile((*source)->GetSourceExtension().c_str()))
{
// Generate this object file's rule file.
this->WriteObjectRuleFiles(target, *(*source), objects,
ruleFileStream);
}
else if((*source)->GetPropertyAsBool("EXTERNAL_OBJECT"))
{
// This is an external object file. Just add it.
external_objects.push_back((*source)->GetFullPath());
}
}
}
// write the custom commands for this target // write the custom commands for this target
std::vector<std::string> cleanFiles; std::vector<std::string> cleanFiles;
// Look for files registered for cleaning in this directory. // Look for files registered for cleaning in this directory.
@ -368,24 +385,6 @@ cmLocalUnixMakefileGenerator3
// Include the rule file for each object. // Include the rule file for each object.
std::string relPath = this->GetHomeRelativeOutputPath(); std::string relPath = this->GetHomeRelativeOutputPath();
std::string objTarget; std::string objTarget;
if(!objects.empty())
{
ruleFileStream
<< "# Include make rules for object files.\n";
for(std::vector<std::string>::const_iterator obj = objects.begin();
obj != objects.end(); ++obj)
{
objTarget = relPath;
objTarget += *obj;
objTarget += ".build.make";
ruleFileStream
<< m_IncludeDirective << " "
<< this->ConvertToOutputForExisting(objTarget.c_str()).c_str()
<< "\n";
}
ruleFileStream
<< "\n";
}
// Write the rule for this target type. // Write the rule for this target type.
switch(target.GetType()) switch(target.GetType())
@ -427,20 +426,10 @@ cmLocalUnixMakefileGenerator3
::WriteObjectDependRules(std::ostream& ruleFileStream, ::WriteObjectDependRules(std::ostream& ruleFileStream,
std::string &obj, std::string &obj,
const char * lang, const char * lang,
const cmSourceFile& source, cmSourceFile& source,
std::vector<std::string>& depends, std::vector<std::string>& depends,
std::string& depMakeFile) std::string& depMakeFile)
{ {
// Generate the build-time dependencies file for this object file.
std::string depMarkFile;
if(!this->GenerateDependsMakeFile(lang, obj.c_str(),
depMakeFile, depMarkFile))
{
cmSystemTools::Error("No dependency checker available for language \"",
lang, "\".");
return;
}
// Create the list of dependencies known at cmake time. These are // Create the list of dependencies known at cmake time. These are
// shared between the object file and dependency scanning rule. // shared between the object file and dependency scanning rule.
depends.push_back(source.GetFullPath()); depends.push_back(source.GetFullPath());
@ -454,40 +443,6 @@ cmLocalUnixMakefileGenerator3
depends.push_back(i->c_str()); depends.push_back(i->c_str());
} }
} }
// Write the dependency generation rule.
std::string relativeObj = this->GetHomeRelativeOutputPath();
relativeObj += obj;
std::vector<std::string> commands;
std::string depEcho = "Scanning ";
depEcho += lang;
depEcho += " dependencies of ";
depEcho += this->Convert(relativeObj.c_str(),NONE,SHELL);
this->AppendEcho(commands, depEcho.c_str());
// Add a command to call CMake to scan dependencies. CMake will
// touch the corresponding depends file after scanning dependencies.
cmOStringStream depCmd;
// TODO: Account for source file properties and directory-level
// definitions when scanning for dependencies.
depCmd << "$(CMAKE_COMMAND) -E cmake_depends "
<< " \""
<< m_GlobalGenerator->GetName() << "\" "
<< this->Convert(m_Makefile->GetHomeOutputDirectory(),FULL,SHELL)
<< " "
<< this->Convert(m_Makefile->GetStartOutputDirectory(),FULL,SHELL)
<< " "
<< lang << " "
<< relativeObj.c_str() << " "
<< this->Convert(source.GetFullPath().c_str(),HOME_OUTPUT,SHELL);
commands.push_back(depCmd.str());
// compute the target
std::string relPath = this->GetHomeRelativeOutputPath();
relPath += depMarkFile;
// Write the rule.
this->WriteMakeRule(ruleFileStream, 0,
relPath.c_str(), depends, commands);
} }
@ -497,24 +452,16 @@ cmLocalUnixMakefileGenerator3
::WriteObjectBuildFile(std::string &obj, ::WriteObjectBuildFile(std::string &obj,
const char *lang, const char *lang,
cmTarget& target, cmTarget& target,
const cmSourceFile& source, cmSourceFile& source,
std::vector<std::string>& depends, std::vector<std::string>& depends,
std::string &depMakeFile) std::string &depMakeFile,
std::ostream &ruleFileStream)
{ {
// Open the rule file for writing. This should be copy-if-different // Open the rule file for writing. This should be copy-if-different
// because the rules may depend on this file itself. // because the rules may depend on this file itself.
std::string ruleFileName = obj; std::string ruleFileName = this->GetTargetDirectory(target);
ruleFileName += ".build.make"; ruleFileName += "/build.make";
std::string ruleFileNameFull = this->ConvertToFullPath(ruleFileName); std::string ruleFileNameFull = this->ConvertToFullPath(ruleFileName);
cmGeneratedFileStream ruleFileStream(ruleFileNameFull.c_str());
ruleFileStream.SetCopyIfDifferent(true);
if(!ruleFileStream)
{
return;
}
this->WriteDisclaimer(ruleFileStream);
ruleFileStream
<< "# Rule file for object file " << obj.c_str() << ".\n\n";
// generate the depend scanning rule // generate the depend scanning rule
this->WriteObjectDependRules(ruleFileStream, obj, lang, source, this->WriteObjectDependRules(ruleFileStream, obj, lang, source,
@ -522,16 +469,6 @@ cmLocalUnixMakefileGenerator3
this->AppendRuleDepend(depends, ruleFileNameFull.c_str()); this->AppendRuleDepend(depends, ruleFileNameFull.c_str());
// Include the dependencies for the target.
std::string depPath = this->GetHomeRelativeOutputPath();
depPath += depMakeFile;
depMakeFile = this->Convert(depPath.c_str(),HOME_OUTPUT,MAKEFILE);
ruleFileStream
<< "# Include any dependencies generated for this rule.\n"
<< m_IncludeDirective << " "
<< depMakeFile
<< "\n\n";
// Write the build rule. // Write the build rule.
// Build the set of compiler flags. // Build the set of compiler flags.
std::string flags; std::string flags;
@ -649,8 +586,9 @@ cmLocalUnixMakefileGenerator3
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void void
cmLocalUnixMakefileGenerator3 cmLocalUnixMakefileGenerator3
::WriteObjectRuleFiles(cmTarget& target, const cmSourceFile& source, ::WriteObjectRuleFiles(cmTarget& target, cmSourceFile& source,
std::vector<std::string>& objects) std::vector<std::string>& objects,
std::ostream &ruleFileStream)
{ {
// Identify the language of the source file. // Identify the language of the source file.
const char* lang = this->GetSourceFileLanguage(source); const char* lang = this->GetSourceFileLanguage(source);
@ -698,50 +636,25 @@ cmLocalUnixMakefileGenerator3
std::string depMakeFile; std::string depMakeFile;
// generate the build rule file // generate the build rule file
this->WriteObjectBuildFile(obj, lang, target, source, depends, depMakeFile); this->WriteObjectBuildFile(obj, lang, target, source, depends, depMakeFile,
ruleFileStream);
// The object file should be checked for dependency integrity. // The object file should be checked for dependency integrity.
m_CheckDependFiles[lang].insert(relativeObj); m_CheckDependFiles[target.GetName()][lang].insert(&source);
// add this to the list of objects for this local generator // add this to the list of objects for this local generator
m_LocalObjectFiles[cmSystemTools::GetFilenameName(obj)].push_back(&target); m_LocalObjectFiles[cmSystemTools::GetFilenameName(obj)].push_back(&target);
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
std::string void
cmLocalUnixMakefileGenerator3 cmLocalUnixMakefileGenerator3
::GenerateCustomRuleFile(const cmCustomCommand& cc, const char *dir) ::GenerateCustomRuleFile(const cmCustomCommand& cc, const char *dir,
std::ostream &ruleFileStream)
{ {
// Convert the output name to a relative path if possible. // Convert the output name to a relative path if possible.
std::string output = this->Convert(cc.GetOutput(),START_OUTPUT); std::string output = this->Convert(cc.GetOutput(),START_OUTPUT);
// Construct the name of the rule file by transforming the output
// name to a valid file name. Since the output is already a file
// everything but the path characters is valid.
std::string customName = output;
cmSystemTools::ReplaceString(customName, "../", "___");
cmSystemTools::ReplaceString(customName, "/", "_");
cmSystemTools::ReplaceString(customName, ":", "_");
std::string ruleFileName = dir;
ruleFileName += "/";
ruleFileName += customName;
ruleFileName += ".build.make";
// what is the relative path to the rule file
std::string relRuleFile = this->Convert(ruleFileName.c_str(),HOME_OUTPUT);
// Open the rule file. This should be copy-if-different because the
// rules may depend on this file itself.
cmGeneratedFileStream ruleFileStream(ruleFileName.c_str());
ruleFileStream.SetCopyIfDifferent(true);
if(!ruleFileStream)
{
return relRuleFile;
}
this->WriteDisclaimer(ruleFileStream);
ruleFileStream
<< "# Custom command rule file for " << output.c_str() << ".\n\n";
// Collect the commands. // Collect the commands.
std::vector<std::string> commands; std::vector<std::string> commands;
std::string preEcho = "Generating "; std::string preEcho = "Generating ";
@ -753,9 +666,6 @@ cmLocalUnixMakefileGenerator3
std::vector<std::string> depends; std::vector<std::string> depends;
this->AppendCustomDepend(depends, cc); this->AppendCustomDepend(depends, cc);
// Add a dependency on the rule file itself.
this->AppendRuleDepend(depends, relRuleFile.c_str());
// Write the rule. // Write the rule.
const char* comment = 0; const char* comment = 0;
if(cc.GetComment() && *cc.GetComment()) if(cc.GetComment() && *cc.GetComment())
@ -764,8 +674,6 @@ cmLocalUnixMakefileGenerator3
} }
this->WriteMakeRule(ruleFileStream, comment, this->WriteMakeRule(ruleFileStream, comment,
cc.GetOutput(), depends, commands); cc.GetOutput(), depends, commands);
return relRuleFile;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -850,19 +758,17 @@ cmLocalUnixMakefileGenerator3
{ {
// Construct a checker for the given language. // Construct a checker for the given language.
std::auto_ptr<cmDepends> std::auto_ptr<cmDepends>
checker(this->GetDependsChecker(lang, checker(this->GetDependsChecker(lang,false));
m_Makefile->GetStartOutputDirectory(),
objFile, false));
if(checker.get()) if(checker.get())
{ {
// Save the make and mark file names.
depMakeFile = checker->GetMakeFileName();
depMarkFile = checker->GetMarkFileName();
// Check the dependencies. Ths is required because we need at least an // Check the dependencies. Ths is required because we need at least an
// empty foo.obj.depends.make for make to include, so at cmake time the // empty foo.obj.depends.make for make to include, so at cmake time the
// ::Check() method will generate that if it does not exist // ::Check() method will generate that if it does not exist
checker->Check();
// Todo: could just make sure that file exists,
// use different method not check
checker->Check(objFile);
return true; return true;
} }
@ -1885,13 +1791,62 @@ cmLocalUnixMakefileGenerator3
cmTarget& target, cmTarget& target,
const std::vector<std::string>& objects) const std::vector<std::string>& objects)
{ {
// must write the targets depend info file
std::string dir = this->GetTargetDirectory(target);
std::string infoFileName = dir;
infoFileName += "/DependInfo.cmake";
std::string ruleFileNameFull = this->ConvertToFullPath(infoFileName);
cmGeneratedFileStream infoFileStream(ruleFileNameFull.c_str());
infoFileStream.SetCopyIfDifferent(true);
if(!infoFileStream)
{
return;
}
cmGlobalUnixMakefileGenerator3 *gg =
static_cast<cmGlobalUnixMakefileGenerator3 *>(m_GlobalGenerator);
this->WriteDependLanguageInfo(infoFileStream,target);
// and now write the rule to use it
std::vector<std::string> depends; std::vector<std::string> depends;
std::vector<std::string> no_commands; std::vector<std::string> commands;
// Construct the name of the dependency generation target. // Construct the name of the dependency generation target.
std::string depTarget = this->GetRelativeTargetDirectory(target); std::string depTarget = this->GetRelativeTargetDirectory(target);
depTarget += "/depend"; depTarget += "/depend";
std::string depMark = depTarget;
depMark += ".make.mark";
depends.push_back(depMark);
this->WriteMakeRule(ruleFileStream, 0,
depTarget.c_str(), depends, commands);
depends.clear();
// Write the dependency generation rule.
std::string depEcho = "Scanning dependencies of target ";
depEcho += target.GetName();
this->AppendEcho(commands, depEcho.c_str());
// Add a command to call CMake to scan dependencies. CMake will
// touch the corresponding depends file after scanning dependencies.
cmOStringStream depCmd;
// TODO: Account for source file properties and directory-level
// definitions when scanning for dependencies.
depCmd << "$(CMAKE_COMMAND) -E cmake_depends "
<< " \""
<< m_GlobalGenerator->GetName() << "\" "
<< this->Convert(m_Makefile->GetHomeOutputDirectory(),FULL,SHELL)
<< " "
<< this->Convert(m_Makefile->GetStartOutputDirectory(),FULL,SHELL)
<< " "
<< this->Convert(ruleFileNameFull.c_str(),FULL,SHELL);
commands.push_back(depCmd.str());
// Write the rule.
this->WriteMakeRule(ruleFileStream, 0,
depMark.c_str(), depends, commands);
#if 0
// This target drives dependency generation for all object files. // This target drives dependency generation for all object files.
std::string relPath = this->GetHomeRelativeOutputPath(); std::string relPath = this->GetHomeRelativeOutputPath();
std::string objTarget; std::string objTarget;
@ -1903,10 +1858,7 @@ cmLocalUnixMakefileGenerator3
objTarget += ".depend"; objTarget += ".depend";
depends.push_back(objTarget); depends.push_back(objTarget);
} }
#endif
// Write the rule.
this->WriteMakeRule(ruleFileStream, 0,
depTarget.c_str(), depends, no_commands);
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -2632,8 +2584,6 @@ cmLocalUnixMakefileGenerator3
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
cmDepends* cmDepends*
cmLocalUnixMakefileGenerator3::GetDependsChecker(const std::string& lang, cmLocalUnixMakefileGenerator3::GetDependsChecker(const std::string& lang,
const char* dir,
const char* objFile,
bool verbose) bool verbose)
{ {
cmDepends *ret = 0; cmDepends *ret = 0;
@ -2653,8 +2603,6 @@ cmLocalUnixMakefileGenerator3::GetDependsChecker(const std::string& lang,
#endif #endif
if (ret) if (ret)
{ {
ret->SetTargetFile(dir, objFile, ".depend",".build.depend.make");
ret->SetCompileDirectory(m_Makefile->GetHomeOutputDirectory());
ret->SetVerbose(verbose); ret->SetVerbose(verbose);
} }
return ret; return ret;
@ -2666,17 +2614,11 @@ cmLocalUnixMakefileGenerator3
::ScanDependencies(std::vector<std::string> const& args) ::ScanDependencies(std::vector<std::string> const& args)
{ {
// Format of arguments is: // Format of arguments is:
// $(CMAKE_COMMAND), cmake_depends, home_output_dir, start_output_dir, GeneratorName, <lang>, <obj>, <src> // $(CMAKE_COMMAND), cmake_depends, GeneratorName, home_output_dir, start_output_dir, info file
// The caller has ensured that all required arguments exist. // The caller has ensured that all required arguments exist.
// The language for which we are scanning dependencies. // The info file for this target
std::string const& lang = args[5]; std::string const& infoFile = args[5];
// The file to which to write dependencies.
const char* objFile = args[6].c_str();
// The source file at which to start the scan.
const char* srcFile = args[7].c_str();
// Read the directory information file. // Read the directory information file.
cmake cm; cmake cm;
@ -2687,6 +2629,8 @@ cmLocalUnixMakefileGenerator3
cmMakefile* mf = lg->GetMakefile(); cmMakefile* mf = lg->GetMakefile();
mf->SetHomeOutputDirectory(args[3].c_str()); mf->SetHomeOutputDirectory(args[3].c_str());
mf->SetStartOutputDirectory(args[4].c_str()); mf->SetStartOutputDirectory(args[4].c_str());
lg->SetupPathConversions();
bool haveDirectoryInfo = false; bool haveDirectoryInfo = false;
std::string dirInfoFile = args[4]; std::string dirInfoFile = args[4];
dirInfoFile += "/CMakeDirectoryInformation.cmake"; dirInfoFile += "/CMakeDirectoryInformation.cmake";
@ -2696,6 +2640,13 @@ cmLocalUnixMakefileGenerator3
haveDirectoryInfo = true; haveDirectoryInfo = true;
} }
// read in the target info file
if(!mf->ReadListFile(0, infoFile.c_str()) ||
cmSystemTools::GetErrorOccuredFlag())
{
cmSystemTools::Error("Target DependInfo.cmake file not found");
}
// Test whether we need to force Unix paths. // Test whether we need to force Unix paths.
if(haveDirectoryInfo) if(haveDirectoryInfo)
{ {
@ -2712,6 +2663,30 @@ cmLocalUnixMakefileGenerator3
cmSystemTools::Error("Directory Information file not found"); cmSystemTools::Error("Directory Information file not found");
} }
// create the file stream for the depends file
std::string dir = cmSystemTools::GetFilenamePath(infoFile);
dir += "/depend.make";
// Open the rule file. This should be copy-if-different because the
// rules may depend on this file itself.
std::string ruleFileNameFull = dir;
cmGeneratedFileStream ruleFileStream(ruleFileNameFull.c_str());
ruleFileStream.SetCopyIfDifferent(true);
if(!ruleFileStream)
{
return false;
}
this->WriteDisclaimer(ruleFileStream);
// for each language we need to scan, scan it
const char *langStr = mf->GetSafeDefinition("CMAKE_DEPENDS_LANGUAGES");
std::vector<std::string> langs;
cmSystemTools::ExpandListArgument(langStr, langs);
for (std::vector<std::string>::iterator li =
langs.begin(); li != langs.end(); ++li)
{
// construct the checker
std::string lang = li->c_str();
// Get the set of include directories. // Get the set of include directories.
std::vector<std::string> includes; std::vector<std::string> includes;
@ -2747,30 +2722,56 @@ cmLocalUnixMakefileGenerator3
} }
} }
// Dispatch the scan for each language. // Create the scanner for this language
cmDepends *scanner = 0;
if(lang == "C" || lang == "CXX" || lang == "RC") if(lang == "C" || lang == "CXX" || lang == "RC")
{ {
// TODO: Handle RC (resource files) dependencies correctly. // TODO: Handle RC (resource files) dependencies correctly.
cmDependsC scanner(srcFile, includes, scanner = new cmDependsC(includes,
includeRegexScan.c_str(), includeRegexComplain.c_str()); includeRegexScan.c_str(),
scanner.SetTargetFile(".",objFile,".depend",".build.depend.make"); includeRegexComplain.c_str());
return scanner.Write();
} }
#ifdef CMAKE_BUILD_WITH_CMAKE #ifdef CMAKE_BUILD_WITH_CMAKE
else if(lang == "Fortran") else if(lang == "Fortran")
{ {
cmDependsFortran scanner(srcFile, includes); scanner = new cmDependsFortran(includes);
scanner.SetTargetFile(".",objFile,".depend",".build.depend.make");
return scanner.Write();
} }
else if(lang == "Java") else if(lang == "Java")
{ {
cmDependsJava scanner(srcFile); scanner = new cmDependsJava();
scanner.SetTargetFile(".",objFile,".depend",".build.depend.make");
return scanner.Write();
} }
#endif #endif
return false;
// for each file we need to scan
std::string srcLang = "CMAKE_DEPENDS_CHECK_";
srcLang += lang;
const char *srcStr = mf->GetSafeDefinition(srcLang.c_str());
std::vector<std::string> srcs;
cmSystemTools::ExpandListArgument(srcStr, srcs);
for (std::vector<std::string>::iterator si =
srcs.begin(); si != srcs.end(); ++si)
{
std::string &src = *si;
++si;
// make sure the object file is relative to home output
std::string obj = *si;
obj = lg->Convert(obj.c_str(),HOME_OUTPUT,MAKEFILE);
scanner->Write(src.c_str(),obj.c_str(),ruleFileStream);
}
// free the scanner for this language
if (scanner)
{
delete scanner;
}
}
// dependencies were generated, so touch the mark file
dir += ".mark";
std::ofstream fmark(dir.c_str());
fmark << "Dependencies updated>" << std::endl;
return true;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -2942,45 +2943,31 @@ void cmLocalUnixMakefileGenerator3::CheckDependencies(cmMakefile* mf,
bool verbose, bool verbose,
bool clear) bool clear)
{ {
// Get the list of languages that may have sources to check. // Get the list of target files to check
const char* langDef = mf->GetDefinition("CMAKE_DEPENDS_LANGUAGES"); const char* infoDef = mf->GetDefinition("CMAKE_DEPEND_INFO_FILES");
if(!langDef) if(!infoDef)
{ {
return; return;
} }
std::vector<std::string> languages;
cmSystemTools::ExpandListArgument(langDef, languages);
// For each language get the set of files to check.
for(std::vector<std::string>::iterator l = languages.begin();
l != languages.end(); ++l)
{
std::string depCheck = "CMAKE_DEPENDS_CHECK_";
depCheck += *l;
if(const char* fileDef = mf->GetDefinition(depCheck.c_str()))
{
// Check each file. The current working directory is already
// correct.
std::vector<std::string> files; std::vector<std::string> files;
cmSystemTools::ExpandListArgument(fileDef, files); cmSystemTools::ExpandListArgument(infoDef, files);
for(std::vector<std::string>::iterator f = files.begin();
f != files.end(); ++f) // For each info file run the check
{ cmDependsC checker;
// Construct a checker for the given language. checker.SetVerbose(verbose);
std::auto_ptr<cmDepends> for(std::vector<std::string>::iterator l = files.begin();
checker(this->GetDependsChecker(*l, ".", f->c_str(), verbose)); l != files.end(); ++l)
if(checker.get())
{ {
// either clear or check the files
std::string dependFile = cmSystemTools::GetFilenamePath(l->c_str());
dependFile += "/depend.make";
if (clear) if (clear)
{ {
checker->Clear(); checker.Clear(dependFile.c_str());
} }
else else
{ {
checker->Check(); checker.Check(dependFile.c_str());
}
}
}
} }
} }
} }
@ -3063,3 +3050,58 @@ cmLocalUnixMakefileGenerator3::WriteHelpRule(std::ostream& ruleFileStream)
no_depends, commands); no_depends, commands);
ruleFileStream << "\n\n"; ruleFileStream << "\n\n";
} }
void cmLocalUnixMakefileGenerator3
::WriteDependLanguageInfo(std::ostream& cmakefileStream, cmTarget &target)
{
// now write all the language stuff
// Set the set of files to check for dependency integrity.
std::set<cmStdString> checkSetLangs;
std::map<cmStdString,cmLocalUnixMakefileGenerator3::IntegrityCheckSet>&
checkSet = this->GetIntegrityCheckSet()[target.GetName()];
for(std::map<cmStdString,
cmLocalUnixMakefileGenerator3::IntegrityCheckSet>::const_iterator
l = checkSet.begin(); l != checkSet.end(); ++l)
{
checkSetLangs.insert(l->first);
}
// list the languages
cmakefileStream
<< "# The set of files whose dependency integrity should be checked:\n";
cmakefileStream
<< "SET(CMAKE_DEPENDS_LANGUAGES\n";
for(std::set<cmStdString>::iterator
l = checkSetLangs.begin(); l != checkSetLangs.end(); ++l)
{
cmakefileStream << " \"" << l->c_str() << "\"\n";
}
cmakefileStream << " )\n";
// now list the files for each language
for(std::set<cmStdString>::iterator
l = checkSetLangs.begin(); l != checkSetLangs.end(); ++l)
{
cmakefileStream
<< "SET(CMAKE_DEPENDS_CHECK_" << l->c_str() << "\n";
// get the check set for this local gen and language
cmLocalUnixMakefileGenerator3::IntegrityCheckSet iCheckSet =
checkSet[*l];
// for each file
for(cmLocalUnixMakefileGenerator3::IntegrityCheckSet::const_iterator
csIter = iCheckSet.begin();
csIter != iCheckSet.end(); ++csIter)
{
cmakefileStream << " \"" << (*csIter)->GetFullPath() << "\"\n";
// Get the full path name of the object file.
std::string obj = this->GetObjectFileName(target, **csIter);
cmakefileStream << " \"" <<
this->Convert(obj.c_str(),
cmLocalGenerator::FULL).c_str() << "\"\n";
}
cmakefileStream << " )\n";
}
}

View File

@ -140,8 +140,9 @@ public:
// List the files for which to check dependency integrity. Each // List the files for which to check dependency integrity. Each
// language has its own list because integrity may be checked // language has its own list because integrity may be checked
// differently. // differently.
struct IntegrityCheckSet: public std::set<cmStdString> {}; struct IntegrityCheckSet: public std::set<cmSourceFile *> {};
std::map<cmStdString, IntegrityCheckSet> &GetIntegrityCheckSet() struct IntegrityCheckSetMap: public std::map<cmStdString, IntegrityCheckSet> {};
std::map<cmStdString, IntegrityCheckSetMap> &GetIntegrityCheckSet()
{ return m_CheckDependFiles;} { return m_CheckDependFiles;}
void AppendTargetDepends(std::vector<std::string>& depends, void AppendTargetDepends(std::vector<std::string>& depends,
@ -155,6 +156,9 @@ public:
protected: protected:
// write the depend info
void WriteDependLanguageInfo(std::ostream& cmakefileStream, cmTarget &tgt);
// write the target rules for the local Makefile into the stream // write the target rules for the local Makefile into the stream
void WriteLocalMakefileTargets(std::ostream& ruleFileStream); void WriteLocalMakefileTargets(std::ostream& ruleFileStream);
@ -195,22 +199,24 @@ protected:
// create the rule files for an object // create the rule files for an object
void WriteObjectRuleFiles(cmTarget& target, void WriteObjectRuleFiles(cmTarget& target,
const cmSourceFile& source, cmSourceFile& source,
std::vector<std::string>& objects); std::vector<std::string>& objects,
std::ostream &filestr);
// write the build rule for an object // write the build rule for an object
void WriteObjectBuildFile(std::string &obj, void WriteObjectBuildFile(std::string &obj,
const char *lang, const char *lang,
cmTarget& target, cmTarget& target,
const cmSourceFile& source, cmSourceFile& source,
std::vector<std::string>& depends, std::vector<std::string>& depends,
std::string &depMakeFile); std::string &depMakeFile,
std::ostream &filestr);
// write the depend.make file for an object // write the depend.make file for an object
void WriteObjectDependRules(std::ostream& ruleFileStream, void WriteObjectDependRules(std::ostream& ruleFileStream,
std::string& obj, std::string& obj,
const char *lang, const char *lang,
const cmSourceFile& source, cmSourceFile& source,
std::vector<std::string>& depends, std::vector<std::string>& depends,
std::string& depMarkFile); std::string& depMarkFile);
@ -222,13 +228,12 @@ protected:
// return the appropriate depends checker // return the appropriate depends checker
cmDepends* GetDependsChecker(const std::string& lang, cmDepends* GetDependsChecker(const std::string& lang,
const char* dir,
const char* objFile,
bool verbose); bool verbose);
std::string GenerateCustomRuleFile(const cmCustomCommand& cc, void GenerateCustomRuleFile(const cmCustomCommand& cc,
const char *dir); const char *dir,
std::ostream &ruleStream);
// these three make some simple changes and then call WriteLibraryRule // these three make some simple changes and then call WriteLibraryRule
void WriteStaticLibraryRule(std::ostream& ruleFileStream, void WriteStaticLibraryRule(std::ostream& ruleFileStream,
@ -327,7 +332,7 @@ protected:
void ComputeHomeRelativeOutputPath(); void ComputeHomeRelativeOutputPath();
private: private:
std::map<cmStdString, IntegrityCheckSet> m_CheckDependFiles; std::map<cmStdString, IntegrityCheckSetMap> m_CheckDependFiles;
//========================================================================== //==========================================================================
// Configuration settings. // Configuration settings.

View File

@ -887,7 +887,7 @@ int cmake::CMakeCommand(std::vector<std::string>& args)
} }
// Internal CMake dependency scanning support. // Internal CMake dependency scanning support.
else if (args[1] == "cmake_depends" && args.size() >= 8) else if (args[1] == "cmake_depends" && args.size() >= 6)
{ {
cmake cm; cmake cm;
cmGlobalGenerator *ggd = cm.CreateGlobalGenerator(args[2].c_str()); cmGlobalGenerator *ggd = cm.CreateGlobalGenerator(args[2].c_str());