diff options
Diffstat (limited to 'src/tools')
-rw-r--r-- | src/tools/moc/main.cpp | 46 | ||||
-rw-r--r-- | src/tools/moc/preprocessor.cpp | 58 | ||||
-rw-r--r-- | src/tools/moc/preprocessor.h | 1 |
3 files changed, 79 insertions, 26 deletions
diff --git a/src/tools/moc/main.cpp b/src/tools/moc/main.cpp index 0c327a641f..0a10aef989 100644 --- a/src/tools/moc/main.cpp +++ b/src/tools/moc/main.cpp @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2016 Intel Corporation. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the tools applications of the Qt Toolkit. @@ -242,6 +243,11 @@ int runMoc(int argc, char **argv) metadataOption.setFlags(QCommandLineOption::ShortOptionStyle); parser.addOption(metadataOption); + QCommandLineOption compilerFlavorOption(QStringLiteral("compiler-flavor")); + compilerFlavorOption.setDescription(QStringLiteral("Set the compiler flavor: either \"msvc\" or \"unix\".")); + compilerFlavorOption.setValueName(QStringLiteral("flavor")); + parser.addOption(compilerFlavorOption); + QCommandLineOption noIncludeOption(QStringLiteral("i")); noIncludeOption.setDescription(QStringLiteral("Do not generate an #include statement.")); parser.addOption(noIncludeOption); @@ -263,6 +269,11 @@ int runMoc(int argc, char **argv) prependIncludeOption.setValueName(QStringLiteral("file")); parser.addOption(prependIncludeOption); + QCommandLineOption includeOption(QStringLiteral("include")); + includeOption.setDescription(QStringLiteral("Parse <file> as an #include before the main source(s).")); + includeOption.setValueName(QStringLiteral("file")); + parser.addOption(includeOption); + QCommandLineOption noNotesWarningsCompatOption(QStringLiteral("n")); noNotesWarningsCompatOption.setDescription(QStringLiteral("Do not display notes (-nn) or warnings (-nw). Compatibility option.")); noNotesWarningsCompatOption.setValueName(QStringLiteral("which")); @@ -323,9 +334,32 @@ int runMoc(int argc, char **argv) if (parser.isSet(pathPrefixOption)) moc.includePath = QFile::encodeName(parser.value(pathPrefixOption)); } + const auto includePaths = parser.values(includePathOption); for (const QString &path : includePaths) pp.includes += Preprocessor::IncludePath(QFile::encodeName(path)); + QString compilerFlavor = parser.value(compilerFlavorOption); + if (compilerFlavor.isEmpty() || compilerFlavor == QLatin1String("unix")) { + // traditional Unix compilers use both CPATH and CPLUS_INCLUDE_PATH + // $CPATH feeds to #include <...> and #include "...", whereas + // CPLUS_INCLUDE_PATH is equivalent to GCC's -isystem, so we parse later + const auto cpath = qgetenv("CPATH").split(QDir::listSeparator().toLatin1()); + for (const QByteArray &p : cpath) + pp.includes += Preprocessor::IncludePath(p); + const auto cplus_include_path = qgetenv("CPLUS_INCLUDE_PATH").split(QDir::listSeparator().toLatin1()); + for (const QByteArray &p : cplus_include_path) + pp.includes += Preprocessor::IncludePath(p); + } else if (compilerFlavor == QLatin1String("msvc")) { + // MSVC uses one environment variable: INCLUDE + const auto include = qgetenv("INCLUDE").split(QDir::listSeparator().toLatin1()); + for (const QByteArray &p : include) + pp.includes += Preprocessor::IncludePath(p); + } else { + error(qPrintable(QLatin1String("Unknown compiler flavor '") + compilerFlavor + + QLatin1String("'; valid values are: msvc, unix."))); + parser.showHelp(1); + } + const auto macFrameworks = parser.values(macFrameworkOption); for (const QString &path : macFrameworks) { // minimalistic framework support for the mac @@ -420,7 +454,17 @@ int runMoc(int argc, char **argv) moc.includes = pp.includes; // 1. preprocess - moc.symbols = pp.preprocessed(moc.filename, &in); + const auto includeFiles = parser.values(includeOption); + for (const QString &includeName : includeFiles) { + QByteArray rawName = pp.resolveInclude(QFile::encodeName(includeName), moc.filename); + QFile f(QFile::decodeName(rawName)); + if (f.open(QIODevice::ReadOnly)) { + moc.symbols += Symbol(0, MOC_INCLUDE_BEGIN, rawName); + moc.symbols += pp.preprocessed(rawName, &f); + moc.symbols += Symbol(0, MOC_INCLUDE_END, rawName); + } + } + moc.symbols += pp.preprocessed(moc.filename, &in); // We obviously do not support MS extensions pp.macros.remove("_MSC_EXTENSIONS"); diff --git a/src/tools/moc/preprocessor.cpp b/src/tools/moc/preprocessor.cpp index befc280f4e..415003e6b1 100644 --- a/src/tools/moc/preprocessor.cpp +++ b/src/tools/moc/preprocessor.cpp @@ -1005,6 +1005,36 @@ static void mergeStringLiterals(Symbols *_symbols) } } +QByteArray Preprocessor::resolveInclude(const QByteArray &include, const QByteArray &relativeTo) +{ + // #### stringery + QFileInfo fi; + if (!relativeTo.isEmpty()) + fi.setFile(QFileInfo(QString::fromLocal8Bit(relativeTo.constData())).dir(), QString::fromLocal8Bit(include.constData())); + for (int j = 0; j < Preprocessor::includes.size() && !fi.exists(); ++j) { + const IncludePath &p = Preprocessor::includes.at(j); + if (p.isFrameworkPath) { + const int slashPos = include.indexOf('/'); + if (slashPos == -1) + continue; + fi.setFile(QString::fromLocal8Bit(p.path + '/' + include.left(slashPos) + ".framework/Headers/"), + QString::fromLocal8Bit(include.mid(slashPos + 1).constData())); + } else { + fi.setFile(QString::fromLocal8Bit(p.path.constData()), QString::fromLocal8Bit(include.constData())); + } + // try again, maybe there's a file later in the include paths with the same name + // (186067) + if (fi.isDir()) { + fi = QFileInfo(); + continue; + } + } + + if (!fi.exists() || fi.isDir()) + return QByteArray(); + return fi.canonicalFilePath().toLocal8Bit(); +} + void Preprocessor::preprocess(const QByteArray &filename, Symbols &preprocessed) { currentFilenames.push(filename); @@ -1025,32 +1055,9 @@ void Preprocessor::preprocess(const QByteArray &filename, Symbols &preprocessed) continue; until(PP_NEWLINE); - // #### stringery - QFileInfo fi; - if (local) - fi.setFile(QFileInfo(QString::fromLocal8Bit(filename.constData())).dir(), QString::fromLocal8Bit(include.constData())); - for (int j = 0; j < Preprocessor::includes.size() && !fi.exists(); ++j) { - const IncludePath &p = Preprocessor::includes.at(j); - if (p.isFrameworkPath) { - const int slashPos = include.indexOf('/'); - if (slashPos == -1) - continue; - fi.setFile(QString::fromLocal8Bit(p.path + '/' + include.left(slashPos) + ".framework/Headers/"), - QString::fromLocal8Bit(include.mid(slashPos + 1).constData())); - } else { - fi.setFile(QString::fromLocal8Bit(p.path.constData()), QString::fromLocal8Bit(include.constData())); - } - // try again, maybe there's a file later in the include paths with the same name - // (186067) - if (fi.isDir()) { - fi = QFileInfo(); - continue; - } - } - - if (!fi.exists() || fi.isDir()) + include = resolveInclude(include, local ? filename : QByteArray()); + if (include.isNull()) continue; - include = fi.canonicalFilePath().toLocal8Bit(); if (Preprocessor::preprocessedIncludes.contains(include)) continue; @@ -1205,6 +1212,7 @@ Symbols Preprocessor::preprocessed(const QByteArray &filename, QFile *file) input = cleaned(input); // phase 2: tokenize for the preprocessor + index = 0; symbols = tokenize(input); #if 0 diff --git a/src/tools/moc/preprocessor.h b/src/tools/moc/preprocessor.h index 9a49751eb0..a7eb1a19e1 100644 --- a/src/tools/moc/preprocessor.h +++ b/src/tools/moc/preprocessor.h @@ -62,6 +62,7 @@ public: QList<QByteArray> frameworks; QSet<QByteArray> preprocessedIncludes; Macros macros; + QByteArray resolveInclude(const QByteArray &filename, const QByteArray &relativeTo); Symbols preprocessed(const QByteArray &filename, QFile *device); void parseDefineArguments(Macro *m); |