From 2c1c1f74ea69d2bdd984b5d5764db08ee77f1e6f Mon Sep 17 00:00:00 2001 From: Martin Smith Date: Tue, 4 Jun 2019 13:12:17 +0200 Subject: qdoc: Build artificial module header This update lets qdoc build an artificial module header whenever it can't find the project's module header. The artificial module header contains a #include "/absolute/path/header.h" for each header found using the project's headerdirs and headers variables in the qdocconf file. header files with names ending in _p.h are not included in the artificial module header. The ordering of the includes in the artificial module header is not controlled, so the includes must not be order-dependent. Task-number: QTBUG-76005 Change-Id: I9d0975c571b29e0c3c5972a4e1f78427c595d52d Reviewed-by: Paul Wicking --- src/qdoc/clangcodeparser.cpp | 83 +++++++++++++++++++++++++------------------- 1 file changed, 48 insertions(+), 35 deletions(-) diff --git a/src/qdoc/clangcodeparser.cpp b/src/qdoc/clangcodeparser.cpp index be7bde02f..4eaab69d7 100644 --- a/src/qdoc/clangcodeparser.cpp +++ b/src/qdoc/clangcodeparser.cpp @@ -1259,56 +1259,69 @@ void ClangCodeParser::buildPCH() header = candidate; } if (header.isEmpty()) { - qWarning() << "(qdoc) Could not find the module header in the include path for module" + qWarning() << "(qdoc) Could not find the module header in include paths for module" << module << " (include paths: "<< includePaths_ << ")"; - } else { - args_.push_back("-xc++"); - CXTranslationUnit tu; - QString tmpHeader = pchFileDir_->path() + "/" + module; - QFile tmpHeaderFile(tmpHeader); - if (tmpHeaderFile.open(QIODevice::Text | QIODevice::WriteOnly)) { + qWarning() << " Artificial module header built from header dirs in qdocconf file"; + } + args_.push_back("-xc++"); + CXTranslationUnit tu; + QString tmpHeader = pchFileDir_->path() + "/" + module; + QFile tmpHeaderFile(tmpHeader); + if (tmpHeaderFile.open(QIODevice::Text | QIODevice::WriteOnly)) { + QTextStream out(&tmpHeaderFile); + if (header.isEmpty()) { + QList keys = allHeaders_.keys(); + QList values = allHeaders_.values(); + for (int i = 0; i < keys.size(); i++) { + if (!keys.at(i).endsWith(QLatin1String("_p.h")) && + !keys.at(i).startsWith(QLatin1String("moc_"))) { + QString line = QLatin1String("#include \"") + values.at(i) + + QLatin1String("/") + keys.at(i) + QLatin1String("\""); + out << line << "\n"; + } + } + } else { QFile headerFile(header); if (!headerFile.open(QFile::ReadOnly)) { qWarning() << "Could not read module header file" << header; return; } QTextStream in(&headerFile); - QTextStream out(&tmpHeaderFile); while (!in.atEnd()) { QString line = in.readLine().simplified(); if (line.startsWith(QLatin1String("#include"))) out << line << "\n"; } } - 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(args_.size()), nullptr, 0, - flags_ | CXTranslationUnit_ForSerialization, &tu); - qCDebug(lcQdoc) << __FUNCTION__ << "clang_parseTranslationUnit2(" - << tmpHeader << args_ << ") returns" << err; - if (!err && tu) { - pchName_ = pchFileDir_->path().toUtf8() + "/" + module + ".pch"; - auto error = clang_saveTranslationUnit(tu, pchName_.constData(), clang_defaultSaveOptions(tu)); - if (error) { - Location::logToStdErrAlways("Could not save PCH file for " + moduleHeader()); - pchName_.clear(); - } - 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(); - Location::logToStdErrAlways("Could not create PCH file for " + moduleHeader()); + } + 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(args_.size()), nullptr, 0, + flags_ | CXTranslationUnit_ForSerialization, &tu); + qCDebug(lcQdoc) << __FUNCTION__ << "clang_parseTranslationUnit2(" + << tmpHeader << args_ << ") returns" << err; + if (!err && tu) { + pchName_ = pchFileDir_->path().toUtf8() + "/" + module + ".pch"; + auto error = clang_saveTranslationUnit(tu, pchName_.constData(), clang_defaultSaveOptions(tu)); + if (error) { + Location::logToStdErrAlways("Could not save PCH file for " + moduleHeader()); + pchName_.clear(); } - args_.pop_back(); // remove the "-xc++"; + 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(); + Location::logToStdErrAlways("Could not create PCH file for " + moduleHeader()); } + args_.pop_back(); // remove the "-xc++"; } } } -- cgit v1.2.1