diff options
Diffstat (limited to 'src/tools')
-rw-r--r-- | src/tools/qdoc/generator.cpp | 22 | ||||
-rw-r--r-- | src/tools/qdoc/location.cpp | 30 | ||||
-rw-r--r-- | src/tools/qdoc/location.h | 4 | ||||
-rw-r--r-- | src/tools/qdoc/main.cpp | 198 | ||||
-rw-r--r-- | src/tools/qdoc/node.cpp | 2 | ||||
-rw-r--r-- | src/tools/qdoc/node.h | 4 | ||||
-rw-r--r-- | src/tools/qdoc/qdocdatabase.cpp | 32 | ||||
-rw-r--r-- | src/tools/qdoc/qdocindexfiles.cpp | 27 | ||||
-rw-r--r-- | src/tools/tools.pro | 6 |
9 files changed, 185 insertions, 140 deletions
diff --git a/src/tools/qdoc/generator.cpp b/src/tools/qdoc/generator.cpp index c6db340f74..0384765157 100644 --- a/src/tools/qdoc/generator.cpp +++ b/src/tools/qdoc/generator.cpp @@ -1484,22 +1484,24 @@ void Generator::initialize(const Config &config) QDir dirInfo; if (dirInfo.exists(outDir_)) { - if (!Config::removeDirContents(outDir_)) - config.lastLocation().error(tr("Cannot empty output directory '%1'").arg(outDir_)); + if (!runGenerateOnly()) { + if (!Config::removeDirContents(outDir_)) + config.lastLocation().error(tr("Cannot empty output directory '%1'").arg(outDir_)); + } } else { if (!dirInfo.mkpath(outDir_)) config.lastLocation().fatal(tr("Cannot create output directory '%1'").arg(outDir_)); } - if (!dirInfo.mkdir(outDir_ + "/images")) - config.lastLocation().fatal(tr("Cannot create output directory '%1'").arg(outDir_ + "/images")); - if (!dirInfo.mkdir(outDir_ + "/images/used-in-examples")) - config.lastLocation().fatal(tr("Cannot create output directory '%1'").arg(outDir_ + "/images/used-in-examples")); - if (!dirInfo.mkdir(outDir_ + "/scripts")) - config.lastLocation().fatal(tr("Cannot create output directory '%1'").arg(outDir_ + "/scripts")); - if (!dirInfo.mkdir(outDir_ + "/style")) - config.lastLocation().fatal(tr("Cannot create output directory '%1'").arg(outDir_ + "/style")); + if (!dirInfo.exists(outDir_ + "/images") && !dirInfo.mkdir(outDir_ + "/images")) + config.lastLocation().fatal(tr("Cannot create images directory '%1'").arg(outDir_ + "/images")); + if (!dirInfo.exists(outDir_ + "/images/used-in-examples") && !dirInfo.mkdir(outDir_ + "/images/used-in-examples")) + config.lastLocation().fatal(tr("Cannot create images used in examples directory '%1'").arg(outDir_ + "/images/used-in-examples")); + if (!dirInfo.exists(outDir_ + "/scripts") && !dirInfo.mkdir(outDir_ + "/scripts")) + config.lastLocation().fatal(tr("Cannot create scripts directory '%1'").arg(outDir_ + "/scripts")); + if (!dirInfo.exists(outDir_ + "/style") && !dirInfo.mkdir(outDir_ + "/style")) + config.lastLocation().fatal(tr("Cannot create style directory '%1'").arg(outDir_ + "/style")); } imageFiles = config.getCleanPathList(CONFIG_IMAGES); diff --git a/src/tools/qdoc/location.cpp b/src/tools/qdoc/location.cpp index ceb5709aae..ca6521c002 100644 --- a/src/tools/qdoc/location.cpp +++ b/src/tools/qdoc/location.cpp @@ -42,7 +42,7 @@ #include <qdebug.h> #include "config.h" #include "location.h" - +#include "generator.h" #include <qdir.h> #include <qregexp.h> #include <stdlib.h> @@ -57,6 +57,7 @@ QT_STATIC_CONST_IMPL Location Location::null; int Location::tabSize; QString Location::programName; QRegExp *Location::spuriousRegExp = 0; +bool Location::logProgress_ = false; /*! \class Location @@ -260,25 +261,30 @@ QString Location::canonicalRelativePath(const QString &path) const /*! Writes \a message and \a detals to stderr as a formatted - warning message. + warning message. Does not write the message if qdoc is in + the Prepare phase. */ void Location::warning(const QString& message, const QString& details) const { - emitMessage(Warning, message, details); + if (!Generator::runPrepareOnly()) + emitMessage(Warning, message, details); } /*! Writes \a message and \a detals to stderr as a formatted - error message. + error message. Does not write the message if qdoc is in + the Prepare phase. */ void Location::error(const QString& message, const QString& details) const { - emitMessage(Error, message, details); + if (!Generator::runPrepareOnly()) + emitMessage(Error, message, details); } /*! Writes \a message and \a detals to stderr as a formatted - error message and then exits the program. + error message and then exits the program. qdoc prints fatal + errors in either phase (Prepare or Generate). */ void Location::fatal(const QString& message, const QString& details) const { @@ -331,6 +337,18 @@ void Location::information(const QString& message) } /*! + Prints \a message to \c stderr followed by a \c{'\n'}, + but only if the -log-progress option is set. + */ +void Location::logToStdErr(const QString& message) +{ + if (logProgress_) { + fprintf(stderr, "LOG: %s\n", message.toLatin1().data()); + fflush(stderr); + } +} + +/*! Report a program bug, including the \a hint. */ void Location::internalError(const QString& hint) diff --git a/src/tools/qdoc/location.h b/src/tools/qdoc/location.h index d2c9487968..0d22e94b46 100644 --- a/src/tools/qdoc/location.h +++ b/src/tools/qdoc/location.h @@ -96,6 +96,9 @@ public: static void terminate(); static void information(const QString& message); static void internalError(const QString& hint); + static void logToStdErr(const QString& message); + static void startLoggingProgress() { logProgress_ = true; } + static void stopLoggingProgress() { logProgress_ = false; } private: enum MessageType { Warning, Error }; @@ -123,6 +126,7 @@ private: static int tabSize; static QString programName; static QRegExp *spuriousRegExp; + static bool logProgress_; }; QT_END_NAMESPACE diff --git a/src/tools/qdoc/main.cpp b/src/tools/qdoc/main.cpp index 5fbc01f1f0..c70160f6ec 100644 --- a/src/tools/qdoc/main.cpp +++ b/src/tools/qdoc/main.cpp @@ -101,6 +101,9 @@ static bool obsoleteLinks = false; static QStringList defines; static QStringList dependModules; static QStringList indexDirs; +static QString currentDir; +static QString prevCurrentDir; +static QString documentationPath; /*! Print the help message to \c stdout. @@ -118,7 +121,7 @@ static void printHelp() " -highlighting " "Turn on syntax highlighting (makes qdoc run slower)\n" " -indexdir " - "Specify a directory where QDoc should search for indices to link to\n" + "Specify a directory where QDoc should search for index files to load\n" " -installdir " "Specify the directory where the output will be after running \"make install\"\n" " -no-examples " @@ -150,6 +153,88 @@ static void printVersion() Location::information(s); } +static void loadIndexFiles(Config& config) +{ + QDocDatabase* qdb = QDocDatabase::qdocDB(); + /* + Read some XML indexes containing definitions from other documentation sets. + */ + QStringList indexFiles = config.getStringList(CONFIG_INDEXES); + + dependModules += config.getStringList(CONFIG_DEPENDS); + + // Allow modules and third-party application/libraries to link + // to the Qt docs without having to explicitly pass --indexdir. + if (!indexDirs.contains(documentationPath)) + indexDirs.append(documentationPath); + + if (dependModules.size() > 0) { + if (indexDirs.size() > 0) { + for (int i = 0; i < indexDirs.size(); i++) { + if (indexDirs[i].startsWith("..")) { + const QString prefix(QDir(currentDir).relativeFilePath(prevCurrentDir)); + if (!prefix.isEmpty()) + indexDirs[i].prepend(prefix + QLatin1Char('/')); + } + } + /* + Add all subdirectories of the indexdirs as dependModules, + when an asterisk is used in the 'depends' list. + */ + if (dependModules.contains("*")) { + dependModules.removeOne("*"); + for (int i = 0; i < indexDirs.size(); i++) { + QDir scanDir = QDir(indexDirs[i]); + scanDir.setFilter(QDir::Dirs | QDir::NoDotAndDotDot); + QFileInfoList dirList = scanDir.entryInfoList(); + for (int j = 0; j < dirList.size(); j++) { + if (dirList[j].fileName().toLower() != config.getString(CONFIG_PROJECT).toLower()) + dependModules.append(dirList[j].fileName()); + } + } + } + for (int i = 0; i < dependModules.size(); i++) { + QString indexToAdd; + QList<QFileInfo> foundIndices; + for (int j = 0; j < indexDirs.size(); j++) { + QString fileToLookFor = indexDirs[j] + QLatin1Char('/') + dependModules[i] + + QLatin1Char('/') + dependModules[i] + QLatin1String(".index"); + if (QFile::exists(fileToLookFor)) { + QFileInfo tempFileInfo(fileToLookFor); + if (!foundIndices.contains(tempFileInfo)) + foundIndices.append(tempFileInfo); + } + } + qSort(foundIndices.begin(), foundIndices.end(), creationTimeBefore); + if (foundIndices.size() > 1) { + /* + QDoc should always use the last entry in the multimap when there are + multiple index files for a module, since the last modified file has the + highest UNIX timestamp. + */ + qDebug() << "Multiple indices found for dependency:" << dependModules[i] << "\nFound:"; + for (int k = 0; k < foundIndices.size(); k++) + qDebug() << foundIndices[k].absoluteFilePath(); + qDebug() << "Using" << foundIndices[foundIndices.size() - 1].absoluteFilePath() + << "as index for" << dependModules[i]; + indexToAdd = foundIndices[foundIndices.size() - 1].absoluteFilePath(); + } + else if (foundIndices.size() == 1) { + indexToAdd = foundIndices[0].absoluteFilePath(); + } + if (!indexToAdd.isEmpty() && !indexFiles.contains(indexToAdd)) + indexFiles << indexToAdd; + } + } + else { + qDebug() << "Dependant modules specified, but no index directories or " + << "install directory were set." + << "There will probably be errors for missing links."; + } + } + qdb->readIndexes(indexFiles); +} + /*! Processes the qdoc config file \a fileName. This is the controller for all of qdoc. @@ -168,8 +253,7 @@ static void processQdocconfFile(const QString &fileName) Config config(tr("qdoc")); int i = 0; while (defaults[i].key) { - config.setStringList(defaults[i].key, - QStringList() << defaults[i].value); + config.setStringList(defaults[i].key, QStringList() << defaults[i].value); ++i; } config.setStringList(CONFIG_SYNTAXHIGHLIGHTING, QStringList(highlighting ? "true" : "false")); @@ -177,8 +261,8 @@ static void processQdocconfFile(const QString &fileName) config.setStringList(CONFIG_NOLINKERRORS, QStringList(noLinkErrors ? "true" : "false")); config.setStringList(CONFIG_OBSOLETELINKS, QStringList(obsoleteLinks ? "true" : "false")); - QString documentationPath = QLibraryInfo::rawLocation(QLibraryInfo::DocumentationPath, - QLibraryInfo::EffectivePaths); + documentationPath = QLibraryInfo::rawLocation(QLibraryInfo::DocumentationPath, + QLibraryInfo::EffectivePaths); // Set a few environment variables that can be used from the qdocconf file qputenv("QT_INSTALL_DOCS", documentationPath.toLatin1()); @@ -202,10 +286,18 @@ static void processQdocconfFile(const QString &fileName) config.setStringList(CONFIG_DEFINES,defs); Location::terminate(); - QString prevCurrentDir = QDir::currentPath(); - QString dir = QFileInfo(fileName).path(); - if (!dir.isEmpty()) - QDir::setCurrent(dir); + prevCurrentDir = QDir::currentPath(); + currentDir = QFileInfo(fileName).path(); + if (!currentDir.isEmpty()) + QDir::setCurrent(currentDir); + + QString phase; + if (Generator::runPrepareOnly()) + phase = " in -prepare mode "; + else if (Generator::runGenerateOnly()) + phase = " in -generate mode "; + QString msg = "Running qdoc for " + config.getString(CONFIG_PROJECT) + phase; + Location::logToStdErr(msg); /* Initialize all the classes and data structures with the @@ -227,8 +319,7 @@ static void processQdocconfFile(const QString &fileName) while (fn != fileNames.constEnd()) { QTranslator *translator = new QTranslator(0); if (!translator->load(*fn)) - config.lastLocation().error(tr("Cannot load translator '%1'") - .arg(*fn)); + config.lastLocation().error(tr("Cannot load translator '%1'").arg(*fn)); QCoreApplication::instance()->installTranslator(translator); translators.append(translator); ++fn; @@ -260,86 +351,8 @@ static void processQdocconfFile(const QString &fileName) QSet<QString> outputFormats = config.getOutputFormats(); Location outputFormatsLocation = config.lastLocation(); - /* - Read some XML indexes containing definitions from other documentation sets. - */ - QStringList indexFiles = config.getStringList(CONFIG_INDEXES); - - dependModules += config.getStringList(CONFIG_DEPENDS); - - // Allow modules and third-party application/libraries to link - // to the Qt docs without having to explicitly pass --indexdir. - if (!indexDirs.contains(documentationPath)) - indexDirs.append(documentationPath); - - if (dependModules.size() > 0) { - if (indexDirs.size() > 0) { - for (int i = 0; i < indexDirs.size(); i++) { - if (indexDirs[i].startsWith("..")) { - const QString prefix(QDir(dir).relativeFilePath(prevCurrentDir)); - if (!prefix.isEmpty()) - indexDirs[i].prepend(prefix + QLatin1Char('/')); - } - } - /* - Add all subdirectories of the indexdirs as dependModules when an asterisk is used in - the 'depends' list. - */ - if (dependModules.contains("*")) { - dependModules.removeOne("*"); - for (int i = 0; i < indexDirs.size(); i++) { - QDir scanDir = QDir(indexDirs[i]); - scanDir.setFilter(QDir::Dirs | QDir::NoDotAndDotDot); - QFileInfoList dirList = scanDir.entryInfoList(); - for (int j = 0; j < dirList.size(); j++) { - if (dirList[j].fileName().toLower() != config.getString(CONFIG_PROJECT).toLower()) - dependModules.append(dirList[j].fileName()); - } - } - } - for (int i = 0; i < dependModules.size(); i++) { - QString indexToAdd; - QList<QFileInfo> foundIndices; - for (int j = 0; j < indexDirs.size(); j++) { - QString fileToLookFor = indexDirs[j] + QLatin1Char('/') + dependModules[i] + - QLatin1Char('/') + dependModules[i] + QLatin1String(".index"); - if (QFile::exists(fileToLookFor)) { - QFileInfo tempFileInfo(fileToLookFor); - if (!foundIndices.contains(tempFileInfo)) - foundIndices.append(tempFileInfo); - } - } - qSort(foundIndices.begin(), foundIndices.end(), creationTimeBefore); - if (foundIndices.size() > 1) { - /* - QDoc should always use the last entry in the multimap when there are - multiple index files for a module, since the last modified file has the - highest UNIX timestamp. - */ - qDebug() << "Multiple indices found for dependency:" << dependModules[i] << "\nFound:"; - for (int k = 0; k < foundIndices.size(); k++) - qDebug() << foundIndices[k].absoluteFilePath(); - qDebug() << "Using" << foundIndices[foundIndices.size() - 1].absoluteFilePath() - << "as index for" << dependModules[i]; - indexToAdd = foundIndices[foundIndices.size() - 1].absoluteFilePath(); - } - else if (foundIndices.size() == 1) { - indexToAdd = foundIndices[0].absoluteFilePath(); - } - else { - qDebug() << "No indices for" << dependModules[i] << - "could be found in the specified index directories."; - } - if (!indexToAdd.isEmpty() && !indexFiles.contains(indexToAdd)) - indexFiles << indexToAdd; - } - } - else { - qDebug() << "Dependant modules specified, but no index directories or install directory were set." - << "There will probably be errors for missing links."; - } - } - qdb->readIndexes(indexFiles); + if (!Generator::runPrepareOnly()) + loadIndexFiles(config); QSet<QString> excludedDirs; QSet<QString> excludedFiles; @@ -604,6 +617,9 @@ int main(int argc, char **argv) else if (opt == "-generate") { Generator::setQDocPass(Generator::Generate); } + else if (opt == "-log-progress") { + Location::startLoggingProgress(); + } else { qdocFiles.append(opt); } diff --git a/src/tools/qdoc/node.cpp b/src/tools/qdoc/node.cpp index 67805d3dff..3828709b7f 100644 --- a/src/tools/qdoc/node.cpp +++ b/src/tools/qdoc/node.cpp @@ -462,7 +462,7 @@ void Node::setLink(LinkType linkType, const QString &link, const QString &desc) */ void Node::setSince(const QString &since) { - sinc = since.simplified(); + since_ = since.simplified(); } /*! diff --git a/src/tools/qdoc/node.h b/src/tools/qdoc/node.h index 451b666a78..05133cab0c 100644 --- a/src/tools/qdoc/node.h +++ b/src/tools/qdoc/node.h @@ -222,7 +222,7 @@ public: Status inheritedStatus() const; ThreadSafeness threadSafeness() const; ThreadSafeness inheritedThreadSafeness() const; - QString since() const { return sinc; } + QString since() const { return since_; } QString templateStuff() const { return templateStuff_; } PageType pageType() const { return pageType_; } QString pageTypeString() const; @@ -280,7 +280,7 @@ private: QMap<LinkType, QPair<QString, QString> > linkMap_; QString moduleName_; QString url_; - QString sinc; + QString since_; QString templateStuff_; mutable QString uuid_; QString outSubDir_; diff --git a/src/tools/qdoc/qdocdatabase.cpp b/src/tools/qdoc/qdocdatabase.cpp index 0c0b30e8c7..cb93a92d33 100644 --- a/src/tools/qdoc/qdocdatabase.cpp +++ b/src/tools/qdoc/qdocdatabase.cpp @@ -321,7 +321,7 @@ void QDocDatabase::findAllClasses(const InnerNode* node) { NodeList::const_iterator c = node->childNodes().constBegin(); while (c != node->childNodes().constEnd()) { - if ((*c)->access() != Node::Private && (*c)->url().isEmpty()) { + if ((*c)->access() != Node::Private) { if ((*c)->type() == Node::Class && !(*c)->doc().isEmpty()) { QString className = (*c)->name(); if ((*c)->parent() && @@ -372,7 +372,7 @@ void QDocDatabase::findAllFunctions(const InnerNode* node) NodeList::ConstIterator c = node->childNodes().constBegin(); while (c != node->childNodes().constEnd()) { if ((*c)->access() != Node::Private) { - if ((*c)->isInnerNode() && (*c)->url().isEmpty()) { + if ((*c)->isInnerNode()) { findAllFunctions(static_cast<const InnerNode*>(*c)); } else if ((*c)->type() == Node::Function) { @@ -415,7 +415,7 @@ void QDocDatabase::findAllNamespaces(const InnerNode* node) NodeList::ConstIterator c = node->childNodes().constBegin(); while (c != node->childNodes().constEnd()) { if ((*c)->access() != Node::Private) { - if ((*c)->isInnerNode() && (*c)->url().isEmpty()) { + if ((*c)->isInnerNode()) { findAllNamespaces(static_cast<const InnerNode *>(*c)); if ((*c)->type() == Node::Namespace) { const NamespaceNode* nspace = static_cast<const NamespaceNode *>(*c); @@ -467,12 +467,11 @@ void QDocDatabase::findAllSince(const InnerNode* node) nsmap.value().insert(func->name(),(*child)); } } - else if ((*child)->url().isEmpty()) { - if ((*child)->type() == Node::Class && !(*child)->doc().isEmpty()) { + else { + if ((*child)->type() == Node::Class) { // Insert classes into the since and class maps. QString className = (*child)->name(); - if ((*child)->parent() && (*child)->parent()->type() == Node::Namespace && - !(*child)->parent()->name().isEmpty()) { + if ((*child)->parent() && !(*child)->parent()->name().isEmpty()) { className = (*child)->parent()->name()+"::"+className; } nsmap.value().insert(className,(*child)); @@ -481,8 +480,7 @@ void QDocDatabase::findAllSince(const InnerNode* node) else if ((*child)->subType() == Node::QmlClass) { // Insert QML elements into the since and element maps. QString className = (*child)->name(); - if ((*child)->parent() && (*child)->parent()->type() == Node::Namespace && - !(*child)->parent()->name().isEmpty()) { + if ((*child)->parent() && !(*child)->parent()->name().isEmpty()) { className = (*child)->parent()->name()+"::"+className; } nsmap.value().insert(className,(*child)); @@ -493,17 +491,15 @@ void QDocDatabase::findAllSince(const InnerNode* node) QString propertyName = (*child)->name(); nsmap.value().insert(propertyName,(*child)); } - } - else { - // Insert external documents into the general since map. - QString name = (*child)->name(); - if ((*child)->parent() && (*child)->parent()->type() == Node::Namespace && - !(*child)->parent()->name().isEmpty()) { - name = (*child)->parent()->name()+"::"+name; + else { + // Insert external documents into the general since map. + QString name = (*child)->name(); + if ((*child)->parent() && !(*child)->parent()->name().isEmpty()) { + name = (*child)->parent()->name()+"::"+name; + } + nsmap.value().insert(name,(*child)); } - nsmap.value().insert(name,(*child)); } - // Recursively find child nodes with since commands. if ((*child)->isInnerNode()) { findAllSince(static_cast<InnerNode *>(*child)); diff --git a/src/tools/qdoc/qdocindexfiles.cpp b/src/tools/qdoc/qdocindexfiles.cpp index d68fe0e6fa..14dfa334ae 100644 --- a/src/tools/qdoc/qdocindexfiles.cpp +++ b/src/tools/qdoc/qdocindexfiles.cpp @@ -48,13 +48,7 @@ #include "location.h" #include "atom.h" #include "generator.h" - -//include "doc.h" -//include "htmlgenerator.h" -//include "node.h" -//include "text.h" -//include <limits.h> -//include <qdebug.h> +#include <qdebug.h> QT_BEGIN_NAMESPACE @@ -109,8 +103,11 @@ void QDocIndexFiles::destroyQDocIndexFiles() */ void QDocIndexFiles::readIndexes(const QStringList& indexFiles) { - foreach (const QString& indexFile, indexFiles) + foreach (const QString& indexFile, indexFiles) { + QString msg = "Loading index file: " + indexFile; + Location::logToStdErr(msg); readIndexFile(indexFile); + } } /*! @@ -443,6 +440,11 @@ void QDocIndexFiles::readIndexSection(const QDomElement& element, section->setUrl(indexUrl + QLatin1Char('/') + href); } + QString since = element.attribute("since"); + if (!since.isEmpty()) { + section->setSince(since); + } + // Create some content for the node. QSet<QString> emptySet; Doc doc(location, location, " ", emptySet); // placeholder @@ -502,7 +504,7 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer, Node* node, bool generateInternalNodes) { - if (!node->url().isEmpty() || node->subType() == Node::DitaMap) + if (node->subType() == Node::DitaMap) return false; QString nodeName; @@ -642,6 +644,10 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer, if ((node->type() != Node::Document) && (!node->isQmlNode())) writer.writeAttribute("location", node->location().fileName()); + if (!node->since().isEmpty()) { + writer.writeAttribute("since", node->since()); + } + switch (node->type()) { case Node::Class: { @@ -1048,6 +1054,9 @@ void QDocIndexFiles::generateIndex(const QString& fileName, if (!file.open(QFile::WriteOnly | QFile::Text)) return; + QString msg = "Writing index file: " + fileName; + Location::logToStdErr(msg); + gen_ = g; QXmlStreamWriter writer(&file); writer.setAutoFormatting(true); diff --git a/src/tools/tools.pro b/src/tools/tools.pro index c67d6bfd76..f7d1e651ff 100644 --- a/src/tools/tools.pro +++ b/src/tools/tools.pro @@ -38,6 +38,6 @@ SUBDIRS = $$TOOLS_SUBDIRS # Ensure qdoc is built before making any docs. We rely on the existing dependency # on bootstrap for each of the other tools to ensure they also build qdoc first, # and likewise, the dependency of the rest of the build on tools, src, etc. -bootstrap_docs.depends += $${src_tools_qdoc.target}-make_first -bootstrap_docs.target = $${src_tools_bootstrap.target}-docs -QMAKE_EXTRA_TARGETS += bootstrap_docs +bootstrap_prepare_docs.depends += $${src_tools_qdoc.target}-make_first +bootstrap_prepare_docs.target = $${src_tools_bootstrap.target}-prepare_docs +QMAKE_EXTRA_TARGETS += bootstrap_prepare_docs |