moc: Add --debug-includes option to moc

Because moc silently ignores missing headers, or sometimes includes
the wrong header, it is useful to have a facility to print which
header paths were considered and found.

Add a new --debug-includes option that does that.

Task-number: QTBUG-101775
Change-Id: I72b294ae53d6e47252c7d8afe0f2245da78bfadb
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
bb10
Alexandru Croitor 2022-03-29 19:40:23 +02:00
parent 7db6aa4395
commit da97bc5f53
3 changed files with 56 additions and 4 deletions

View File

@ -306,6 +306,10 @@ int runMoc(int argc, char **argv)
jsonOption.setDescription(QStringLiteral("In addition to generating C++ code, create a machine-readable JSON file in a file that matches the output file and an extra .json extension."));
parser.addOption(jsonOption);
QCommandLineOption debugIncludesOption(QStringLiteral("debug-includes"));
debugIncludesOption.setDescription(QStringLiteral("Display debug messages of each considered include path."));
parser.addOption(debugIncludesOption);
QCommandLineOption collectOption(QStringLiteral("collect-json"));
collectOption.setDescription(QStringLiteral("Instead of processing C++ code, collect previously generated JSON output into a single file."));
parser.addOption(collectOption);
@ -358,6 +362,7 @@ int runMoc(int argc, char **argv)
const bool ignoreConflictingOptions = parser.isSet(ignoreConflictsOption);
pp.preprocessOnly = parser.isSet(preprocessOption);
pp.setDebugIncludes(parser.isSet(debugIncludesOption));
if (parser.isSet(noIncludeOption)) {
moc.noInclude = true;
autoInclude = false;
@ -499,6 +504,17 @@ int runMoc(int argc, char **argv)
moc.currentFilenames.push(filename.toLocal8Bit());
moc.includes = pp.includes;
if (Q_UNLIKELY(parser.isSet(debugIncludesOption))) {
fprintf(stderr, "debug-includes: include search list:\n");
for (auto &includePath : pp.includes) {
fprintf(stderr, "debug-includes: '%s' framework: %d \n",
includePath.path.constData(),
includePath.isFrameworkPath);
}
fprintf(stderr, "debug-includes: end of search list.\n");
}
// 1. preprocess
const auto includeFiles = parser.values(includeOption);
QStringList validIncludesFiles;

View File

@ -1016,9 +1016,15 @@ static void mergeStringLiterals(Symbols *_symbols)
}
static QByteArray searchIncludePaths(const QList<Parser::IncludePath> &includepaths,
const QByteArray &include)
const QByteArray &include,
const bool debugIncludes)
{
QFileInfo fi;
if (Q_UNLIKELY(debugIncludes)) {
fprintf(stderr, "debug-includes: searching for '%s'\n", include.constData());
}
for (int j = 0; j < includepaths.size() && !fi.exists(); ++j) {
const Parser::IncludePath &p = includepaths.at(j);
if (p.isFrameworkPath) {
@ -1030,6 +1036,12 @@ static QByteArray searchIncludePaths(const QList<Parser::IncludePath> &includepa
} else {
fi.setFile(QString::fromLocal8Bit(p.path), QString::fromLocal8Bit(include));
}
if (Q_UNLIKELY(debugIncludes)) {
const auto candidate = fi.filePath().toLocal8Bit();
fprintf(stderr, "debug-includes: considering '%s'\n", candidate.constData());
}
// try again, maybe there's a file later in the include paths with the same name
// (186067)
if (fi.isDir()) {
@ -1038,9 +1050,20 @@ static QByteArray searchIncludePaths(const QList<Parser::IncludePath> &includepa
}
}
if (!fi.exists() || fi.isDir())
if (!fi.exists() || fi.isDir()) {
if (Q_UNLIKELY(debugIncludes)) {
fprintf(stderr, "debug-includes: can't find '%s'\n", include.constData());
}
return QByteArray();
return fi.canonicalFilePath().toLocal8Bit();
}
const auto result = fi.canonicalFilePath().toLocal8Bit();
if (Q_UNLIKELY(debugIncludes)) {
fprintf(stderr, "debug-includes: found '%s'\n", result.constData());
}
return result;
}
QByteArray Preprocessor::resolveInclude(const QByteArray &include, const QByteArray &relativeTo)
@ -1054,7 +1077,11 @@ QByteArray Preprocessor::resolveInclude(const QByteArray &include, const QByteAr
auto it = nonlocalIncludePathResolutionCache.find(include);
if (it == nonlocalIncludePathResolutionCache.end())
it = nonlocalIncludePathResolutionCache.insert(include, searchIncludePaths(includes, include));
it = nonlocalIncludePathResolutionCache.insert(include,
searchIncludePaths(
includes,
include,
debugIncludes));
return it.value();
}
@ -1319,4 +1346,10 @@ void Preprocessor::until(Token t)
;
}
void Preprocessor::setDebugIncludes(bool value)
{
debugIncludes = value;
}
QT_END_NAMESPACE

View File

@ -81,10 +81,13 @@ public:
enum TokenizeMode { TokenizeCpp, TokenizePreprocessor, PreparePreprocessorStatement, TokenizePreprocessorStatement, TokenizeInclude, PrepareDefine, TokenizeDefine };
static Symbols tokenize(const QByteArray &input, int lineNum = 1, TokenizeMode mode = TokenizeCpp);
void setDebugIncludes(bool value);
private:
void until(Token);
void preprocess(const QByteArray &filename, Symbols &preprocessed);
bool debugIncludes = false;
};
QT_END_NAMESPACE