summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Smith <martin.smith@qt.io>2018-10-01 10:59:48 +0200
committerMartin Smith <martin.smith@qt.io>2018-10-23 14:15:29 +0000
commitc4d02e5cea9f8657bd74f1f724d048de5c0142b1 (patch)
tree704477c141bfe18b25233a065f871701e099b5e6
parentfcdb57ed07d36b0b72f41da974550f505a162077 (diff)
qdoc: Let qdoc print better log messages
This change enables qdoc to print better log messages. A new logging function is added to Location, where the qdoc error and warning functions are located. The new function is logToStdErrAlways(msg). It always formats msg for output to stderr by prepending the current time and the word LOG. Several LOG messages are now sent to stderr. Also, qdoc now always tells clang to output its parsing errors to stderr during the building of the precompiled header in the prepare phase. These clang parser errors are easily identified in the new LOG. When no include paths are passed to qdoc on the command line, which is the case for QtPlatformHeaders, qdoc guesses some reasonable include paths from the information available and passes them to clang. It works ok for the QtPlatformHeaders module. However, clang gets lost in some NSOpenGL headers and prints quite a lot of useless parse errors, so we arbitrarily turn off clang's parse errors whenever qdoc has to guess the include paths. The guessed include paths are printed in the LOG, and a warning that clang does not print parse errors when the include paths are guessed is also printed in LOG. Change-Id: I8e5bd0cc5b27463c4c85c9cdcc01b030ac03a1c1 Reviewed-by: Martin Smith <martin.smith@qt.io> Reviewed-by: Paul Wicking <paul.wicking@qt.io>
-rw-r--r--src/qdoc/clangcodeparser.cpp41
-rw-r--r--src/qdoc/clangcodeparser.h1
-rw-r--r--src/qdoc/location.cpp12
-rw-r--r--src/qdoc/location.h1
-rw-r--r--src/qdoc/main.cpp20
5 files changed, 49 insertions, 26 deletions
diff --git a/src/qdoc/clangcodeparser.cpp b/src/qdoc/clangcodeparser.cpp
index 19b6ea553..fdf56d073 100644
--- a/src/qdoc/clangcodeparser.cpp
+++ b/src/qdoc/clangcodeparser.cpp
@@ -1009,6 +1009,7 @@ ClangCodeParser::~ClangCodeParser()
*/
void ClangCodeParser::initializeParser(const Config &config)
{
+ printParsingErrors_ = 1;
const auto args = config.getStringList(CONFIG_INCLUDEPATHS);
includePaths_.resize(args.size());
std::transform(args.begin(), args.end(), includePaths_.begin(),
@@ -1096,6 +1097,7 @@ static const char *defaultArgs_[] = {
#endif
"-fno-exceptions", // Workaround for clang bug http://reviews.llvm.org/D17988
"-DQ_QDOC",
+ "-DQ_CLANG_QDOC",
"-DQT_DISABLE_DEPRECATED_BEFORE=0",
"-DQT_ANNOTATE_CLASS(type,...)=static_assert(sizeof(#__VA_ARGS__), #type);",
"-DQT_ANNOTATE_CLASS2(type,a1,a2)=static_assert(sizeof(#a1, #a2), #type);",
@@ -1143,6 +1145,8 @@ static QVector<QByteArray> includePathsFromHeaders(const QHash<QString, QString>
void ClangCodeParser::getMoreArgs()
{
if (includePaths_.isEmpty()) {
+ Location::logToStdErrAlways("No include paths passed to qdoc");
+ Location::logToStdErrAlways("Guess reasonable include paths:");
/*
The include paths provided are inadequate. Make a list
of reasonable places to look for include files and use
@@ -1150,22 +1154,22 @@ void ClangCodeParser::getMoreArgs()
*/
auto forest = qdb_->searchOrder();
+ printParsingErrors_ = 0;
QByteArray version = qdb_->version().toUtf8();
QString basicIncludeDir = QDir::cleanPath(QString(Config::installDir + "/../include"));
moreArgs_ += "-I" + basicIncludeDir.toLatin1();
moreArgs_ += includePathsFromHeaders(allHeaders_);
+ for (const auto p : moreArgs_) {
+ Location::logToStdErrAlways(p);
+ }
+#if 0
for (const auto &s : forest) {
QString module = basicIncludeDir +"/" + s->camelCaseModuleName();
moreArgs_ += QString("-I" + module).toLatin1();
moreArgs_ += QString("-I" + module + "/" + qdb_->version()).toLatin1();
moreArgs_ += QString("-I" + module + "/" + qdb_->version() + "/" + module).toLatin1();
}
- for (int i=0; i<includePaths_.size(); ++i) {
- if (!includePaths_.at(i).startsWith("-"))
- moreArgs_ += "-I" + includePaths_.at(i);
- else
- moreArgs_ += includePaths_.at(i);
- }
+#endif
}
else {
moreArgs_ = includePaths_;
@@ -1195,6 +1199,7 @@ void ClangCodeParser::buildPCH()
const QByteArray module = moduleHeader().toUtf8();
QByteArray header;
QByteArray privateHeaderDir;
+ Location::logToStdErrAlways("Build & visit PCH for " + moduleHeader());
// Find the path to the module's header (e.g. QtGui/QtGui) to be used
// as pre-compiled header
for (const auto &p : qAsConst(includePaths_)) {
@@ -1259,6 +1264,8 @@ void ClangCodeParser::buildPCH()
}
}
}
+ if (printParsingErrors_ == 0)
+ Location::logToStdErrAlways("clang not printing errors; include paths were guessed");
CXErrorCode err = clang_parseTranslationUnit2(index_,
tmpHeader.toLatin1().data(),
args_.data(), static_cast<int>(args_.size()), nullptr, 0,
@@ -1269,20 +1276,20 @@ void ClangCodeParser::buildPCH()
pchName_ = pchFileDir_->path().toUtf8() + "/" + module + ".pch";
auto error = clang_saveTranslationUnit(tu, pchName_.constData(), clang_defaultSaveOptions(tu));
if (error) {
- qWarning() << "(qdoc) Could not save PCH file for " << module << error;
+ Location::logToStdErrAlways("Could not save PCH file for " + moduleHeader());
pchName_.clear();
}
- // Visit the header now, as token from pre-compiled header won't be visited later
- CXCursor cur = clang_getTranslationUnitCursor(tu);
- ClangVisitor visitor(qdb_, allHeaders_);
- visitor.visitChildren(cur);
-
+ else {
+ // Visit the header now, as token from pre-compiled header won't be visited later
+ CXCursor cur = clang_getTranslationUnitCursor(tu);
+ ClangVisitor visitor(qdb_, allHeaders_);
+ visitor.visitChildren(cur);
+ Location::logToStdErrAlways("PCH built & visited for " + moduleHeader());
+ }
clang_disposeTranslationUnit(tu);
} else {
pchFileDir_->remove();
- qWarning() << "(qdoc) Could not create PCH file for "
- << tmpHeader
- << " error code:" << err;
+ Location::logToStdErrAlways("Could not create PCH file for " + moduleHeader());
}
args_.pop_back(); // remove the "-xc++";
}
@@ -1301,8 +1308,8 @@ void ClangCodeParser::precompileHeaders()
args_.push_back(p.constData());
flags_ = static_cast<CXTranslationUnit_Flags>(CXTranslationUnit_Incomplete | CXTranslationUnit_SkipFunctionBodies | CXTranslationUnit_KeepGoing);
- // Change 2nd parameter to 1 to make clang report errors.
- index_ = clang_createIndex(1, Generator::debugging() ? 1 : 0);
+ // 1 as 2nd parameter tells clang to report parser errors.
+ index_ = clang_createIndex(1, printParsingErrors_);
buildPCH();
clang_disposeIndex(index_);
}
diff --git a/src/qdoc/clangcodeparser.h b/src/qdoc/clangcodeparser.h
index b70fcc0e8..b3497608d 100644
--- a/src/qdoc/clangcodeparser.h
+++ b/src/qdoc/clangcodeparser.h
@@ -69,6 +69,7 @@ public:
void buildPCH();
private:
+ int printParsingErrors_;
QHash<QString, QString> allHeaders_; // file name->path
QVector<QByteArray> includePaths_;
QScopedPointer<QTemporaryDir> pchFileDir_;
diff --git a/src/qdoc/location.cpp b/src/qdoc/location.cpp
index cb12e6ea4..68e2a262a 100644
--- a/src/qdoc/location.cpp
+++ b/src/qdoc/location.cpp
@@ -32,6 +32,7 @@
#include "generator.h"
#include <qdir.h>
#include <qregexp.h>
+#include <QTime>
#include <stdlib.h>
#include <limits.h>
@@ -378,6 +379,17 @@ void Location::logToStdErr(const QString& message)
}
/*!
+ Always prints the current time and \a message to \c stderr
+ followed by a \c{'\n'}.
+ */
+void Location::logToStdErrAlways(const QString& message)
+{
+ QTime t = QTime::currentTime();
+ fprintf(stderr, "%s LOG: %s\n", t.toString().toLatin1().data(), message.toLatin1().data());
+ fflush(stderr);
+}
+
+/*!
Report a program bug, including the \a hint.
*/
void Location::internalError(const QString& hint)
diff --git a/src/qdoc/location.h b/src/qdoc/location.h
index 5c2c90f2d..16188bde1 100644
--- a/src/qdoc/location.h
+++ b/src/qdoc/location.h
@@ -87,6 +87,7 @@ public:
static void information(const QString& message);
static void internalError(const QString& hint);
static void logToStdErr(const QString& message);
+ static void logToStdErrAlways(const QString& message);
static void startLoggingProgress() { logProgress_ = true; }
static void stopLoggingProgress() { logProgress_ = false; }
static QString canonicalRelativePath(const QString &path);
diff --git a/src/qdoc/main.cpp b/src/qdoc/main.cpp
index a2ba37499..ea9dc6ed7 100644
--- a/src/qdoc/main.cpp
+++ b/src/qdoc/main.cpp
@@ -255,18 +255,18 @@ static void processQdocconfFile(const QString &fileName)
if (!qdocGlobals.currentDir().isEmpty())
QDir::setCurrent(qdocGlobals.currentDir());
- QString phase = " in -";
+ QString phase = " in ";
if (Generator::singleExec())
- phase += "single exec mode, ";
+ phase += "single process mode, ";
else
- phase += "separate exec mode, ";
+ phase += "dual process mode, ";
if (Generator::preparing())
- phase += "prepare phase ";
+ phase += "(prepare phase)";
else if (Generator::generating())
- phase += "generate phase ";
+ phase += "(generate phase)";
- QString msg = "Running qdoc for " + config.getString(CONFIG_PROJECT) + phase;
- Location::logToStdErr(msg);
+ QString msg = "Start qdoc for " + config.getString(CONFIG_PROJECT) + phase;
+ Location::logToStdErrAlways(msg);
/*
Initialize all the classes and data structures with the
@@ -461,7 +461,7 @@ static void processQdocconfFile(const QString &fileName)
add it to the big tree.
*/
parsed = 0;
- qCDebug(lcQdoc, "Parsing source files");
+ Location::logToStdErrAlways("Parse source files for " + project);
QMap<QString,QString>::ConstIterator s = sources.constBegin();
while (s != sources.constEnd()) {
CodeParser *codeParser = CodeParser::parserForSourceFile(s.key());
@@ -472,7 +472,7 @@ static void processQdocconfFile(const QString &fileName)
}
++s;
}
- qCDebug(lcQdoc, "Parsing done.");
+ Location::logToStdErrAlways("Source files parsed for " + project);
/*
Now the primary tree has been built from all the header and
@@ -515,6 +515,8 @@ static void processQdocconfFile(const QString &fileName)
if (Generator::debugging())
Generator::stopDebugging(project);
+ msg = "End qdoc for " + config.getString(CONFIG_PROJECT) + phase;
+ Location::logToStdErrAlways(msg);
QDocDatabase::qdocDB()->setVersion(QString());
Generator::terminate();
CodeParser::terminate();