summaryrefslogtreecommitdiffstats
path: root/src/tools/moc
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2015-08-21 17:08:19 -0700
committerThiago Macieira <thiago.macieira@intel.com>2016-07-20 02:54:03 +0000
commit36d524e6a3b64a8c35805c1b868d6d67ccae765c (patch)
tree56a864ba56b3426f17cb202d4d8bbc9e9912aa55 /src/tools/moc
parent23bf3da5a0767f0c54824b4db1ecf23edeb71e91 (diff)
moc: get the system #defines from the compiler itself
In order for moc to properly parse #ifdefs and family, we've had QMAKE_COMPILER_DEFINES as a list of pre-defined macros from the compiler. That list is woefully incomplete. Instead, let's simply ask the compiler for the list. With GCC and family, we use the -dM flag while preprocessing. With ICC on Windows, the flag gains an extra "Q" but is otherwise the same. For MSVC, it requires using some undocumented switches and parsing environment variables (I've tested MSVC 2012, 2013 and 2015). The new moc option is called --include to be similar to GCC's -include option. It does more than just parse a list of pre-defined macros and can be used to insert any sort of code that moc needs to parse prior to the main file. Change-Id: I7de033f80b0e4431b7f1ffff13fca02dbb60a0a6 Reviewed-by: Olivier Goffart (Woboq GmbH) <ogoffart@woboq.com>
Diffstat (limited to 'src/tools/moc')
-rw-r--r--src/tools/moc/main.cpp17
-rw-r--r--src/tools/moc/preprocessor.cpp58
-rw-r--r--src/tools/moc/preprocessor.h1
3 files changed, 50 insertions, 26 deletions
diff --git a/src/tools/moc/main.cpp b/src/tools/moc/main.cpp
index 0c327a641f..c111fa4e6b 100644
--- a/src/tools/moc/main.cpp
+++ b/src/tools/moc/main.cpp
@@ -263,6 +263,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"));
@@ -420,7 +425,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 14d1cd46dc..b9359ff3f4 100644
--- a/src/tools/moc/preprocessor.cpp
+++ b/src/tools/moc/preprocessor.cpp
@@ -1004,6 +1004,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);
@@ -1024,32 +1054,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;
@@ -1204,6 +1211,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);