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 "cmSystemTools.h"
|
||||
#include "cmFileTimeComparison.h"
|
||||
|
||||
#include <ctype.h> // isspace
|
||||
|
||||
|
@ -30,18 +31,28 @@ cmDependsC::cmDependsC():
|
|||
// yummy look at all those constructor arguments
|
||||
cmDependsC::cmDependsC(std::vector<std::string> const& includes,
|
||||
const char* scanRegex, const char* complainRegex,
|
||||
std::set<cmStdString> const& generatedFiles):
|
||||
std::set<cmStdString> const& generatedFiles,
|
||||
const cmStdString& cacheFileName):
|
||||
m_IncludePath(&includes),
|
||||
m_IncludeRegexLine("^[ \t]*#[ \t]*include[ \t]*[<\"]([^\">]+)([\">])"),
|
||||
m_IncludeRegexScan(scanRegex),
|
||||
m_IncludeRegexComplain(complainRegex),
|
||||
m_GeneratedFiles(&generatedFiles)
|
||||
m_GeneratedFiles(&generatedFiles),
|
||||
m_cacheFileName(cacheFileName)
|
||||
{
|
||||
this->ReadCacheFile();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
cmDependsC::~cmDependsC()
|
||||
{
|
||||
this->WriteCacheFile();
|
||||
|
||||
for (std::map<cmStdString, cmIncludeLines*>::iterator it=m_fileCache.begin();
|
||||
it!=m_fileCache.end(); ++it)
|
||||
{
|
||||
delete it->second;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
@ -142,18 +153,38 @@ bool cmDependsC::WriteDependencies(const char *src, const char *obj,
|
|||
// Record scanned files.
|
||||
scanned.insert(fullName);
|
||||
|
||||
// Try to scan the file. Just leave it out if we cannot find
|
||||
// it.
|
||||
std::ifstream fin(fullName.c_str());
|
||||
if(fin)
|
||||
// Check whether this file is already in the cache
|
||||
std::map<cmStdString, cmIncludeLines*>::iterator fileIt=m_fileCache.find(fullName);
|
||||
if (fileIt!=m_fileCache.end())
|
||||
{
|
||||
// Add this file as a dependency.
|
||||
fileIt->second->used=true;
|
||||
dependencies.insert(fullName);
|
||||
for (std::list<UnscannedEntry>::const_iterator incIt=
|
||||
fileIt->second->list.begin(); incIt!=fileIt->second->list.end(); ++incIt)
|
||||
{
|
||||
if (m_Encountered.find(incIt->FileName) == m_Encountered.end())
|
||||
{
|
||||
m_Encountered.insert(incIt->FileName);
|
||||
m_Unscanned.push(*incIt);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// 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());
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -166,8 +197,8 @@ bool cmDependsC::WriteDependencies(const char *src, const char *obj,
|
|||
i != dependencies.end(); ++i)
|
||||
{
|
||||
makeDepends << obj << ": "
|
||||
<< cmSystemTools::ConvertToOutputPath(i->c_str()).c_str()
|
||||
<< std::endl;
|
||||
<< cmSystemTools::ConvertToOutputPath(i->c_str()).c_str()
|
||||
<< std::endl;
|
||||
internalDepends << " " << i->c_str() << std::endl;
|
||||
}
|
||||
makeDepends << std::endl;
|
||||
|
@ -176,8 +207,105 @@ bool cmDependsC::WriteDependencies(const char *src, const char *obj,
|
|||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
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.
|
||||
std::string 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.
|
||||
// This kind of problem will be fixed when a more
|
||||
// preprocessor-like implementation of this scanner is created.
|
||||
if(m_Encountered.find(entry.FileName) == m_Encountered.end() &&
|
||||
m_IncludeRegexScan.find(entry.FileName.c_str()))
|
||||
if (m_IncludeRegexScan.find(entry.FileName.c_str()))
|
||||
{
|
||||
m_Encountered.insert(entry.FileName);
|
||||
m_Unscanned.push(entry);
|
||||
newCacheEntry->list.push_back(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(std::vector<std::string> const& includes,
|
||||
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 ~cmDependsC();
|
||||
|
@ -47,7 +47,7 @@ protected:
|
|||
std::ostream& internalDepends);
|
||||
|
||||
// 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.
|
||||
bool FileExistsOrIsGenerated(const std::string& fname,
|
||||
|
@ -74,10 +74,24 @@ protected:
|
|||
cmStdString FileName;
|
||||
cmStdString QuotedLocation;
|
||||
};
|
||||
|
||||
struct cmIncludeLines
|
||||
{
|
||||
cmIncludeLines():used(false) {}
|
||||
std::list<UnscannedEntry> list;
|
||||
bool used;
|
||||
};
|
||||
|
||||
std::set<cmStdString> m_Encountered;
|
||||
std::queue<UnscannedEntry> m_Unscanned;
|
||||
t_CharBuffer m_Buffer;
|
||||
|
||||
std::map<cmStdString, cmIncludeLines *> m_fileCache;
|
||||
|
||||
cmStdString m_cacheFileName;
|
||||
|
||||
void WriteCacheFile() const;
|
||||
void ReadCacheFile();
|
||||
private:
|
||||
cmDependsC(cmDependsC const&); // Purposely not implemented.
|
||||
void operator=(cmDependsC const&); // Purposely not implemented.
|
||||
|
|
|
@ -2790,11 +2790,15 @@ cmLocalUnixMakefileGenerator3
|
|||
cmDepends *scanner = 0;
|
||||
if(lang == "C" || lang == "CXX" || lang == "RC")
|
||||
{
|
||||
std::string includeCacheFileName = dir;
|
||||
includeCacheFileName += "/includecache.";
|
||||
includeCacheFileName += lang;
|
||||
|
||||
// TODO: Handle RC (resource files) dependencies correctly.
|
||||
scanner = new cmDependsC(includes,
|
||||
includeRegexScan.c_str(),
|
||||
includeRegexComplain.c_str(),
|
||||
generatedFiles);
|
||||
generatedFiles, includeCacheFileName);
|
||||
}
|
||||
#ifdef CMAKE_BUILD_WITH_CMAKE
|
||||
else if(lang == "Fortran")
|
||||
|
|
Loading…
Reference in New Issue