Commit f85f919d authored by Ken Martin's avatar Ken Martin
Browse files

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

parent 90cefde7
......@@ -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
// 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;
}
return this->WriteDependencies(src, obj, fout);
}
//----------------------------------------------------------------------------
void cmDepends::Check()
void cmDepends::Check(const char *file)
{
// Dependency checks must be done in proper working directory.
std::string oldcwd = ".";
......@@ -93,11 +52,11 @@ void cmDepends::Check()
}
// Check whether dependencies must be regenerated.
std::ifstream fin(m_DependsMakeFile.c_str());
std::ifstream fin(file);
if(!(fin && this->CheckDependencies(fin)))
{
// Clear all dependencies so they will be regenerated.
this->Clear();
this->Clear(file);
}
// Restore working directory.
......@@ -108,37 +67,26 @@ void cmDepends::Check()
}
//----------------------------------------------------------------------------
void cmDepends::Clear()
void cmDepends::Clear(const char *file)
{
// Print verbose output.
if(m_Verbose)
{
cmOStringStream msg;
msg << "Clearing dependencies for \"" << m_TargetFile << "\"." << std::endl;
msg << "Clearing dependencies in \"" << file << "\"." << std::endl;
cmSystemTools::Stdout(msg.str().c_str());
}
// Remove the dependency mark file to be sure dependencies will be
// regenerated.
cmSystemTools::RemoveFile(m_DependsMarkFile.c_str());
std::string markFile = file;
markFile += ".mark";
cmSystemTools::RemoveFile(markFile.c_str());
// Write an empty dependency file.
cmGeneratedFileStream depFileStream(m_DependsMakeFile.c_str());
cmGeneratedFileStream depFileStream(file);
depFileStream
<< "# Empty dependencies file for " << m_TargetFile.c_str() << ".\n"
<< "# Empty dependencies file\n"
<< "# 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;
}
......@@ -33,10 +33,6 @@ public:
path from the build directory to the target file. */
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 */
void SetCompileDirectory(const char *dir) {m_CompileDirectory = dir;};
......@@ -47,44 +43,30 @@ public:
virtual ~cmDepends();
/** 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. */
void Check();
void Check(const char *file);
/** Clear dependencies for the target file so they will be regenerated. */
void Clear();
/** Get the name of the dependency make file. */
const char* GetMakeFileName();
/** Get the name of the dependency mark file. */
const char* GetMarkFileName();
void Clear(const char *file);
protected:
// Write dependencies for the target file to the given stream.
// 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.
// Return false if dependencies must be regenerated and true
// 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.
std::string m_Directory;
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.
bool m_Verbose;
......
......@@ -27,10 +27,8 @@ cmDependsC::cmDependsC()
//----------------------------------------------------------------------------
// yummy look at all those constructor arguments
cmDependsC::cmDependsC(const char* sourceFile,
std::vector<std::string> const& includes,
cmDependsC::cmDependsC(std::vector<std::string> const& includes,
const char* scanRegex, const char* complainRegex):
m_SourceFile(sourceFile),
m_IncludePath(&includes),
m_IncludeRegexLine("^[ \t]*#[ \t]*include[ \t]*[<\"]([^\">]+)([\">])"),
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.
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;
}
if(!m_IncludePath)
......@@ -61,10 +65,10 @@ bool cmDependsC::WriteDependencies(std::ostream& os)
// Walk the dependency graph starting with the source file.
bool first = true;
UnscannedEntry root;
root.FileName = m_SourceFile;
root.FileName = src;
m_Unscanned.push(root);
m_Encountered.clear();
m_Encountered.insert(m_SourceFile);
m_Encountered.insert(src);
std::set<cmStdString> dependencies;
std::set<cmStdString> scanned;
while(!m_Unscanned.empty())
......@@ -155,7 +159,7 @@ bool cmDependsC::WriteDependencies(std::ostream& os)
for(std::set<cmStdString>::iterator i=dependencies.begin();
i != dependencies.end(); ++i)
{
os << m_TargetFile.c_str() << ": "
os << obj << ": "
<< cmSystemTools::ConvertToOutputPath(i->c_str()).c_str()
<< std::endl;
}
......@@ -313,8 +317,12 @@ const char* cmDependsC::ParseFileName(const char* in, std::string& name)
bool quoted = false;
char* buf = new char[strlen(in)+1];
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 ||
((*c != ':' || pos > buf+1) && !isspace(*c))); ++c)
((*c != ':' || pos > buf) && !isspace(*c))); ++c)
{
if(*c == '"')
{
......
......@@ -30,22 +30,16 @@ public:
/** Checking instances need to know the build directory name and the
relative path from the build directory to the target file. */
cmDependsC();
/** 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,
cmDependsC(std::vector<std::string> const& includes,
const char* scanRegex, const char* complainRegex);
/** Virtual destructor to cleanup subclasses properly. */
virtual ~cmDependsC();
protected:
// 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);
// Method to scan a single file.
......@@ -56,9 +50,6 @@ protected:
std::string& dependee);
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.
std::vector<std::string> const* m_IncludePath;
......@@ -69,7 +60,7 @@ protected:
// recursively and which to complain about not finding.
cmsys::RegularExpression m_IncludeRegexScan;
cmsys::RegularExpression m_IncludeRegexComplain;
// Data structures for dependency graph walk.
struct UnscannedEntry
{
......
......@@ -77,15 +77,12 @@ struct cmDependsFortranParser_s
//----------------------------------------------------------------------------
cmDependsFortran::cmDependsFortran():
m_SourceFile(),
m_IncludePath(0)
{
}
//----------------------------------------------------------------------------
cmDependsFortran::cmDependsFortran(const char* sourceFile,
std::vector<std::string> const& includes):
m_SourceFile(sourceFile),
cmDependsFortran::cmDependsFortran(std::vector<std::string> const& 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.
if(m_SourceFile == "")
if(!src || src[0] == '\0')
{
cmSystemTools::Error("Cannot scan dependencies without an source file.");
return false;
}
if(!obj || obj[0] == '\0')
{
cmSystemTools::Error("Cannot scan dependencies without an object file.");
return false;
}
if(!m_IncludePath)
{
cmSystemTools::Error("Cannot scan dependencies without an include path.");
......@@ -114,7 +117,7 @@ bool cmDependsFortran::WriteDependencies(std::ostream& os)
cmDependsFortranParser parser(this);
// Push on the starting file.
cmDependsFortranParser_FilePush(&parser, m_SourceFile.c_str());
cmDependsFortranParser_FilePush(&parser, src);
// Parse the translation unit.
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();
i != parser.Includes.end(); ++i)
{
os << m_TargetFile.c_str() << ": "
os << obj << ": "
<< cmSystemTools::ConvertToOutputPath(i->c_str()).c_str()
<< std::endl;
}
......@@ -141,25 +144,8 @@ bool cmDependsFortran::WriteDependencies(std::ostream& os)
if(parser.Provides.find(*i) == parser.Provides.end())
{
// 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;
#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();
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;
}
// If any modules are provided then they must be converted to stamp files.
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();
i != parser.Provides.end(); ++i)
{
......@@ -185,20 +171,9 @@ bool cmDependsFortran::WriteDependencies(std::ostream& os)
os << "\t$(CMAKE_COMMAND) -E cmake_copy_f90_mod "
<< 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:
What about .mod files provided in another directory and found with a
......
......@@ -33,7 +33,7 @@ public:
path from the build directory to the target file, the source
file from which to start scanning, and the include file search
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 ~cmDependsFortran();
......@@ -51,7 +51,8 @@ public:
protected:
// 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);
// The source file from which to start scanning.
......
......@@ -20,14 +20,7 @@
#include "cmSystemTools.h"
//----------------------------------------------------------------------------
cmDependsJava::cmDependsJava():
m_SourceFile()
{
}
//----------------------------------------------------------------------------
cmDependsJava::cmDependsJava(const char* sourceFile):
m_SourceFile(sourceFile)
cmDependsJava::cmDependsJava()
{
}
......@@ -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.
if(m_SourceFile == "")
if(!src || src[0] == '\0')
{
cmSystemTools::Error("Cannot scan dependencies without an source file.");
return false;
......
......@@ -29,22 +29,15 @@ public:
relative path from the build directory to the target file. */
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 ~cmDependsJava();
protected:
// 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);
// The source file from which to start scanning.
std::string m_SourceFile;
private:
cmDependsJava(cmDependsJava const&); // Purposely not implemented.
void operator=(cmDependsJava const&); // Purposely not implemented.
......
......@@ -328,67 +328,34 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile()
}
cmakefileStream << " )\n\n";
this->WriteMainCMakefileLanguageRules(cmakefileStream);
this->WriteMainCMakefileLanguageRules(cmakefileStream, m_LocalGenerators);
}
void cmGlobalUnixMakefileGenerator3
::WriteMainCMakefileLanguageRules(cmGeneratedFileStream& cmakefileStream)
::WriteMainCMakefileLanguageRules(cmGeneratedFileStream& cmakefileStream,
std::vector<cmLocalGenerator *> &lGenerators)
{
cmLocalUnixMakefileGenerator3 *lg;
// now write all the language stuff
// 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
// now list all the target info files
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)
<< "SET(CMAKE_DEPEND_INFO_FILES\n";
for (unsigned int i = 0; i < lGenerators.size(); ++i)
{
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";
// now for each local gen get the checkset
for (unsigned int i = 0; i < m_LocalGenerators.size(); ++i)
lg = static_cast<cmLocalUnixMakefileGenerator3 *>(lGenerators[i]);
// for all of out targets
for (cmTargets::iterator l = lg->GetMakefile()->GetTargets().begin();
l != lg->GetMakefile()->GetTargets().end(); l++)
{
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";
}
std::string tname = lg->GetRelativeTargetDirectory(l->second);
tname += "/DependInfo.cmake";
cmSystemTools::ConvertToUnixSlashes(tname);
cmakefileStream << " \"" << tname.c_str() << "\"\n";
}
cmakefileStream << " )\n";
}
cmakefileStream << " )\n";
}
//----------------------------------------------------------------------------
......@@ -768,7 +735,6 @@ cmGlobalUnixMakefileGenerator3
// for each target Generate the rule files for each target.
cmTargets& targets = lg->GetMakefile()->GetTargets();
bool needRequiresStep = this->NeedRequiresStep(lg);
for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t)
{
if (((t->second.GetType() == cmTarget::EXECUTABLE) ||
......@@ -779,6 +745,8 @@ cmGlobalUnixMakefileGenerator3
t->second.GetName() &&
strlen(t->second.GetName()))
{
bool needRequiresStep =
this->NeedRequiresStep(lg,t->second.GetName());
// Add a rule to build the target by name.
localName = lg->GetRelativeTargetDirectory(t->second);
std::string makefileName = localName;
......@@ -1006,10 +974,10 @@ cmGlobalUnixMakefileGenerator3::WriteHelpRule(std::ostream& ruleFileStream)
bool cmGlobalUnixMakefileGenerator3
::NeedRequiresStep(cmLocalUnixMakefileGenerator3 *lg)
::NeedRequiresStep(cmLocalUnixMakefileGenerator3 *lg,const char *name)
{
std::map<cmStdString,cmLocalUnixMakefileGenerator3::IntegrityCheckSet>&
checkSet = lg->GetIntegrityCheckSet();
checkSet = lg->GetIntegrityCheckSet()[name];
for(std::map<cmStdString,
cmLocalUnixMakefileGenerator3::IntegrityCheckSet>::const_iterator
l = checkSet.begin(); l != checkSet.end(); ++l)
......@@ -1022,6 +990,5 @@ bool cmGlobalUnixMakefileGenerator3
return true;
}
}
return false;
}