moc: Cache header lookups to reduce number of file stat's
This improves moc performance on Windows where file-stat'ing is slow and where the number of project include paths to search is often high because project third-party headers are installed in separate directories rather than a shared include path such as /usr/include. In a real project of non-trivial size it reduces the total from-scratch build time of an optimized build using CMake+ninja with 32 cores by 11% from ~11m35s to ~10m15s. Change-Id: Ieed59646927ed75c55ed9efa97600c328b2fed2c Reviewed-by: Olivier Goffart (Woboq GmbH) <ogoffart@woboq.com>bb10
parent
36d3f24d6a
commit
4df5003ee7
|
|
@ -1005,22 +1005,20 @@ static void mergeStringLiterals(Symbols *_symbols)
|
|||
}
|
||||
}
|
||||
|
||||
QByteArray Preprocessor::resolveInclude(const QByteArray &include, const QByteArray &relativeTo)
|
||||
static QByteArray searchIncludePaths(const QList<Parser::IncludePath> &includepaths,
|
||||
const QByteArray &include)
|
||||
{
|
||||
// #### stringery
|
||||
QFileInfo fi;
|
||||
if (!relativeTo.isEmpty())
|
||||
fi.setFile(QFileInfo(QString::fromLocal8Bit(relativeTo.constData())).dir(), QString::fromLocal8Bit(include.constData()));
|
||||
for (int j = 0; j < Preprocessor::includes.size() && !fi.exists(); ++j) {
|
||||
const IncludePath &p = Preprocessor::includes.at(j);
|
||||
for (int j = 0; j < includepaths.size() && !fi.exists(); ++j) {
|
||||
const Parser::IncludePath &p = includepaths.at(j);
|
||||
if (p.isFrameworkPath) {
|
||||
const int slashPos = include.indexOf('/');
|
||||
if (slashPos == -1)
|
||||
continue;
|
||||
fi.setFile(QString::fromLocal8Bit(p.path + '/' + include.left(slashPos) + ".framework/Headers/"),
|
||||
QString::fromLocal8Bit(include.mid(slashPos + 1).constData()));
|
||||
QString::fromLocal8Bit(include.mid(slashPos + 1)));
|
||||
} else {
|
||||
fi.setFile(QString::fromLocal8Bit(p.path.constData()), QString::fromLocal8Bit(include.constData()));
|
||||
fi.setFile(QString::fromLocal8Bit(p.path), QString::fromLocal8Bit(include));
|
||||
}
|
||||
// try again, maybe there's a file later in the include paths with the same name
|
||||
// (186067)
|
||||
|
|
@ -1035,6 +1033,21 @@ QByteArray Preprocessor::resolveInclude(const QByteArray &include, const QByteAr
|
|||
return fi.canonicalFilePath().toLocal8Bit();
|
||||
}
|
||||
|
||||
QByteArray Preprocessor::resolveInclude(const QByteArray &include, const QByteArray &relativeTo)
|
||||
{
|
||||
if (!relativeTo.isEmpty()) {
|
||||
QFileInfo fi;
|
||||
fi.setFile(QFileInfo(QString::fromLocal8Bit(relativeTo)).dir(), QString::fromLocal8Bit(include));
|
||||
if (fi.exists() && !fi.isDir())
|
||||
return fi.canonicalFilePath().toLocal8Bit();
|
||||
}
|
||||
|
||||
auto it = nonlocalIncludePathResolutionCache.find(include);
|
||||
if (it == nonlocalIncludePathResolutionCache.end())
|
||||
it = nonlocalIncludePathResolutionCache.insert(include, searchIncludePaths(includes, include));
|
||||
return it.value();
|
||||
}
|
||||
|
||||
void Preprocessor::preprocess(const QByteArray &filename, Symbols &preprocessed)
|
||||
{
|
||||
currentFilenames.push(filename);
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ public:
|
|||
static bool preprocessOnly;
|
||||
QList<QByteArray> frameworks;
|
||||
QSet<QByteArray> preprocessedIncludes;
|
||||
QHash<QByteArray, QByteArray> nonlocalIncludePathResolutionCache;
|
||||
Macros macros;
|
||||
QByteArray resolveInclude(const QByteArray &filename, const QByteArray &relativeTo);
|
||||
Symbols preprocessed(const QByteArray &filename, QFile *device);
|
||||
|
|
|
|||
Loading…
Reference in New Issue