|
|
@@ -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,42 +153,159 @@ 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);
|
|
|
-
|
|
|
- // 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());
|
|
|
+ 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
|
|
|
+ {
|
|
|
+
|
|
|
+ // 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;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
// Write the dependencies to the output stream.
|
|
|
internalDepends << obj << std::endl;
|
|
|
for(std::set<cmStdString>::iterator i=dependencies.begin();
|
|
|
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;
|
|
|
-
|
|
|
+
|
|
|
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.
|
|
|
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);
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|