From da97bc5f53f433d68fa1a020f56fb5484d7cf519 Mon Sep 17 00:00:00 2001 From: Alexandru Croitor Date: Tue, 29 Mar 2022 19:40:23 +0200 Subject: [PATCH] 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 --- src/tools/moc/main.cpp | 16 +++++++++++++ src/tools/moc/preprocessor.cpp | 41 ++++++++++++++++++++++++++++++---- src/tools/moc/preprocessor.h | 3 +++ 3 files changed, 56 insertions(+), 4 deletions(-) diff --git a/src/tools/moc/main.cpp b/src/tools/moc/main.cpp index 3e98fbf2b8..45ed85edf3 100644 --- a/src/tools/moc/main.cpp +++ b/src/tools/moc/main.cpp @@ -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; diff --git a/src/tools/moc/preprocessor.cpp b/src/tools/moc/preprocessor.cpp index f6d738aa56..45a7f72751 100644 --- a/src/tools/moc/preprocessor.cpp +++ b/src/tools/moc/preprocessor.cpp @@ -1016,9 +1016,15 @@ static void mergeStringLiterals(Symbols *_symbols) } static QByteArray searchIncludePaths(const QList &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 &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 &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 diff --git a/src/tools/moc/preprocessor.h b/src/tools/moc/preprocessor.h index 39f56d6e92..28bb82f77b 100644 --- a/src/tools/moc/preprocessor.h +++ b/src/tools/moc/preprocessor.h @@ -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