PERF: apply patch for bug 2575 speeds up depend scanning
This commit is contained in:
parent
3a3ffea532
commit
92b6c8e742
@ -17,6 +17,7 @@
|
|||||||
#include "cmDependsC.h"
|
#include "cmDependsC.h"
|
||||||
|
|
||||||
#include "cmSystemTools.h"
|
#include "cmSystemTools.h"
|
||||||
|
#include "cmFileTimeComparison.h"
|
||||||
|
|
||||||
#include <ctype.h> // isspace
|
#include <ctype.h> // isspace
|
||||||
|
|
||||||
@ -30,18 +31,28 @@ cmDependsC::cmDependsC():
|
|||||||
// yummy look at all those constructor arguments
|
// yummy look at all those constructor arguments
|
||||||
cmDependsC::cmDependsC(std::vector<std::string> const& includes,
|
cmDependsC::cmDependsC(std::vector<std::string> const& includes,
|
||||||
const char* scanRegex, const char* complainRegex,
|
const char* scanRegex, const char* complainRegex,
|
||||||
std::set<cmStdString> const& generatedFiles):
|
std::set<cmStdString> const& generatedFiles,
|
||||||
|
const cmStdString& cacheFileName):
|
||||||
m_IncludePath(&includes),
|
m_IncludePath(&includes),
|
||||||
m_IncludeRegexLine("^[ \t]*#[ \t]*include[ \t]*[<\"]([^\">]+)([\">])"),
|
m_IncludeRegexLine("^[ \t]*#[ \t]*include[ \t]*[<\"]([^\">]+)([\">])"),
|
||||||
m_IncludeRegexScan(scanRegex),
|
m_IncludeRegexScan(scanRegex),
|
||||||
m_IncludeRegexComplain(complainRegex),
|
m_IncludeRegexComplain(complainRegex),
|
||||||
m_GeneratedFiles(&generatedFiles)
|
m_GeneratedFiles(&generatedFiles),
|
||||||
|
m_cacheFileName(cacheFileName)
|
||||||
{
|
{
|
||||||
|
this->ReadCacheFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
cmDependsC::~cmDependsC()
|
cmDependsC::~cmDependsC()
|
||||||
{
|
{
|
||||||
|
this->WriteCacheFile();
|
||||||
|
|
||||||
|
for (std::map<cmStdString, cmIncludeLines*>::iterator it=m_fileCache.begin();
|
||||||
|
it!=m_fileCache.end(); ++it)
|
||||||
|
{
|
||||||
|
delete it->second;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
@ -142,42 +153,159 @@ bool cmDependsC::WriteDependencies(const char *src, const char *obj,
|
|||||||
// Record scanned files.
|
// Record scanned files.
|
||||||
scanned.insert(fullName);
|
scanned.insert(fullName);
|
||||||
|
|
||||||
// Try to scan the file. Just leave it out if we cannot find
|
// Check whether this file is already in the cache
|
||||||
// it.
|
std::map<cmStdString, cmIncludeLines*>::iterator fileIt=m_fileCache.find(fullName);
|
||||||
std::ifstream fin(fullName.c_str());
|
if (fileIt!=m_fileCache.end())
|
||||||
if(fin)
|
|
||||||
{
|
{
|
||||||
// Add this file as a dependency.
|
fileIt->second->used=true;
|
||||||
dependencies.insert(fullName);
|
dependencies.insert(fullName);
|
||||||
|
for (std::list<UnscannedEntry>::const_iterator incIt=
|
||||||
// Scan this file for new dependencies. Pass the directory
|
fileIt->second->list.begin(); incIt!=fileIt->second->list.end(); ++incIt)
|
||||||
// containing the file to handle double-quote includes.
|
{
|
||||||
std::string dir = cmSystemTools::GetFilenamePath(fullName);
|
if (m_Encountered.find(incIt->FileName) == m_Encountered.end())
|
||||||
this->Scan(fin, dir.c_str());
|
{
|
||||||
|
m_Encountered.insert(incIt->FileName);
|
||||||
|
m_Unscanned.push(*incIt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
// Try to scan the file. Just leave it out if we cannot find
|
||||||
|
// it.
|
||||||
|
std::ifstream fin(fullName.c_str());
|
||||||
|
if(fin)
|
||||||
|
{
|
||||||
|
// Add this file as a dependency.
|
||||||
|
dependencies.insert(fullName);
|
||||||
|
|
||||||
|
// Scan this file for new dependencies. Pass the directory
|
||||||
|
// containing the file to handle double-quote includes.
|
||||||
|
std::string dir = cmSystemTools::GetFilenamePath(fullName);
|
||||||
|
this->Scan(fin, dir.c_str(), fullName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write the dependencies to the output stream.
|
// Write the dependencies to the output stream.
|
||||||
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()
|
<< cmSystemTools::ConvertToOutputPath(i->c_str()).c_str()
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
internalDepends << " " << i->c_str() << std::endl;
|
internalDepends << " " << i->c_str() << std::endl;
|
||||||
}
|
}
|
||||||
makeDepends << std::endl;
|
makeDepends << std::endl;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
void cmDependsC::Scan(std::istream& is, const char* directory)
|
void cmDependsC::ReadCacheFile()
|
||||||
{
|
{
|
||||||
|
if(m_cacheFileName.size() == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
std::ifstream fin(m_cacheFileName.c_str());
|
||||||
|
if(!fin)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string line;
|
||||||
|
cmIncludeLines* cacheEntry=0;
|
||||||
|
bool haveFileName=false;
|
||||||
|
|
||||||
|
while(cmSystemTools::GetLineFromStream(fin, line))
|
||||||
|
{
|
||||||
|
if (line.empty())
|
||||||
|
{
|
||||||
|
cacheEntry=0;
|
||||||
|
haveFileName=false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
//the first line after an empty line is the name of the parsed file
|
||||||
|
if (haveFileName==false)
|
||||||
|
{
|
||||||
|
haveFileName=true;
|
||||||
|
int newer=0;
|
||||||
|
cmFileTimeComparison comp;
|
||||||
|
bool res=comp.FileTimeCompare(m_cacheFileName.c_str(), line.c_str(), &newer);
|
||||||
|
|
||||||
|
if ((res==true) && (newer==1)) //cache is newer than the parsed file
|
||||||
|
{
|
||||||
|
cacheEntry=new cmIncludeLines;
|
||||||
|
m_fileCache[line]=cacheEntry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (cacheEntry!=0)
|
||||||
|
{
|
||||||
|
UnscannedEntry entry;
|
||||||
|
entry.FileName = line;
|
||||||
|
if (cmSystemTools::GetLineFromStream(fin, line))
|
||||||
|
{
|
||||||
|
if (line!="-")
|
||||||
|
{
|
||||||
|
entry.QuotedLocation=line;
|
||||||
|
}
|
||||||
|
cacheEntry->list.push_back(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
void cmDependsC::WriteCacheFile() const
|
||||||
|
{
|
||||||
|
if(m_cacheFileName.size() == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
std::ofstream cacheOut(m_cacheFileName.c_str());
|
||||||
|
if(!cacheOut)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (std::map<cmStdString, cmIncludeLines*>::const_iterator fileIt=m_fileCache.begin();
|
||||||
|
fileIt!=m_fileCache.end(); ++fileIt)
|
||||||
|
{
|
||||||
|
if (fileIt->second->used)
|
||||||
|
{
|
||||||
|
cacheOut<<fileIt->first.c_str()<<std::endl;
|
||||||
|
|
||||||
|
for (std::list<UnscannedEntry>::const_iterator incIt=fileIt->second->list.begin();
|
||||||
|
incIt!=fileIt->second->list.end(); ++incIt)
|
||||||
|
{
|
||||||
|
cacheOut<<incIt->FileName.c_str()<<std::endl;
|
||||||
|
if (incIt->QuotedLocation.empty())
|
||||||
|
{
|
||||||
|
cacheOut<<"-"<<std::endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cacheOut<<incIt->QuotedLocation.c_str()<<std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cacheOut<<std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
void cmDependsC::Scan(std::istream& is, const char* directory, const cmStdString& fullName)
|
||||||
|
{
|
||||||
|
cmIncludeLines* newCacheEntry=new cmIncludeLines;
|
||||||
|
newCacheEntry->used=true;
|
||||||
|
m_fileCache[fullName]=newCacheEntry;
|
||||||
|
|
||||||
// Read one line at a time.
|
// Read one line at a time.
|
||||||
std::string line;
|
std::string line;
|
||||||
while(cmSystemTools::GetLineFromStream(is, line))
|
while(cmSystemTools::GetLineFromStream(is, line))
|
||||||
@ -204,11 +332,14 @@ void cmDependsC::Scan(std::istream& is, const char* directory)
|
|||||||
// is included by double-quotes and the other by angle brackets.
|
// is included by double-quotes and the other by angle brackets.
|
||||||
// This kind of problem will be fixed when a more
|
// This kind of problem will be fixed when a more
|
||||||
// preprocessor-like implementation of this scanner is created.
|
// preprocessor-like implementation of this scanner is created.
|
||||||
if(m_Encountered.find(entry.FileName) == m_Encountered.end() &&
|
if (m_IncludeRegexScan.find(entry.FileName.c_str()))
|
||||||
m_IncludeRegexScan.find(entry.FileName.c_str()))
|
|
||||||
{
|
{
|
||||||
m_Encountered.insert(entry.FileName);
|
newCacheEntry->list.push_back(entry);
|
||||||
m_Unscanned.push(entry);
|
if(m_Encountered.find(entry.FileName) == m_Encountered.end())
|
||||||
|
{
|
||||||
|
m_Encountered.insert(entry.FileName);
|
||||||
|
m_Unscanned.push(entry);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ public:
|
|||||||
cmDependsC();
|
cmDependsC();
|
||||||
cmDependsC(std::vector<std::string> const& includes,
|
cmDependsC(std::vector<std::string> const& includes,
|
||||||
const char* scanRegex, const char* complainRegex,
|
const char* scanRegex, const char* complainRegex,
|
||||||
std::set<cmStdString> const& generatedFiles);
|
std::set<cmStdString> const& generatedFiles, const cmStdString& cachFileName);
|
||||||
|
|
||||||
/** Virtual destructor to cleanup subclasses properly. */
|
/** Virtual destructor to cleanup subclasses properly. */
|
||||||
virtual ~cmDependsC();
|
virtual ~cmDependsC();
|
||||||
@ -47,7 +47,7 @@ protected:
|
|||||||
std::ostream& internalDepends);
|
std::ostream& internalDepends);
|
||||||
|
|
||||||
// Method to scan a single file.
|
// Method to scan a single file.
|
||||||
void Scan(std::istream& is, const char* directory);
|
void Scan(std::istream& is, const char* directory, const cmStdString& fullName);
|
||||||
|
|
||||||
// Method to test for the existence of a file.
|
// Method to test for the existence of a file.
|
||||||
bool FileExistsOrIsGenerated(const std::string& fname,
|
bool FileExistsOrIsGenerated(const std::string& fname,
|
||||||
@ -74,10 +74,24 @@ protected:
|
|||||||
cmStdString FileName;
|
cmStdString FileName;
|
||||||
cmStdString QuotedLocation;
|
cmStdString QuotedLocation;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct cmIncludeLines
|
||||||
|
{
|
||||||
|
cmIncludeLines():used(false) {}
|
||||||
|
std::list<UnscannedEntry> list;
|
||||||
|
bool used;
|
||||||
|
};
|
||||||
|
|
||||||
std::set<cmStdString> m_Encountered;
|
std::set<cmStdString> m_Encountered;
|
||||||
std::queue<UnscannedEntry> m_Unscanned;
|
std::queue<UnscannedEntry> m_Unscanned;
|
||||||
t_CharBuffer m_Buffer;
|
t_CharBuffer m_Buffer;
|
||||||
|
|
||||||
|
std::map<cmStdString, cmIncludeLines *> m_fileCache;
|
||||||
|
|
||||||
|
cmStdString m_cacheFileName;
|
||||||
|
|
||||||
|
void WriteCacheFile() const;
|
||||||
|
void ReadCacheFile();
|
||||||
private:
|
private:
|
||||||
cmDependsC(cmDependsC const&); // Purposely not implemented.
|
cmDependsC(cmDependsC const&); // Purposely not implemented.
|
||||||
void operator=(cmDependsC const&); // Purposely not implemented.
|
void operator=(cmDependsC const&); // Purposely not implemented.
|
||||||
|
@ -2790,11 +2790,15 @@ cmLocalUnixMakefileGenerator3
|
|||||||
cmDepends *scanner = 0;
|
cmDepends *scanner = 0;
|
||||||
if(lang == "C" || lang == "CXX" || lang == "RC")
|
if(lang == "C" || lang == "CXX" || lang == "RC")
|
||||||
{
|
{
|
||||||
|
std::string includeCacheFileName = dir;
|
||||||
|
includeCacheFileName += "/includecache.";
|
||||||
|
includeCacheFileName += lang;
|
||||||
|
|
||||||
// TODO: Handle RC (resource files) dependencies correctly.
|
// TODO: Handle RC (resource files) dependencies correctly.
|
||||||
scanner = new cmDependsC(includes,
|
scanner = new cmDependsC(includes,
|
||||||
includeRegexScan.c_str(),
|
includeRegexScan.c_str(),
|
||||||
includeRegexComplain.c_str(),
|
includeRegexComplain.c_str(),
|
||||||
generatedFiles);
|
generatedFiles, includeCacheFileName);
|
||||||
}
|
}
|
||||||
#ifdef CMAKE_BUILD_WITH_CMAKE
|
#ifdef CMAKE_BUILD_WITH_CMAKE
|
||||||
else if(lang == "Fortran")
|
else if(lang == "Fortran")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user