2015-12-18 15:17:43 +00:00
|
|
|
From fa0d02eedcacc22db1026b902801b29176755362 Mon Sep 17 00:00:00 2001
|
2015-12-16 22:11:53 +00:00
|
|
|
From: Thiago Macieira <thiago.macieira@intel.com>
|
|
|
|
Date: Fri, 21 Aug 2015 17:08:19 -0700
|
|
|
|
Subject: [PATCH] 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
|
|
|
|
---
|
|
|
|
mkspecs/features/moc.prf | 31 +++++++++++++--
|
|
|
|
qmake/main.cpp | 38 +++++++++++++++++++
|
|
|
|
src/tools/moc/main.cpp | 16 +++++++-
|
|
|
|
src/tools/moc/preprocessor.cpp | 60 +++++++++++++++++-------------
|
|
|
|
src/tools/moc/preprocessor.h | 1 +
|
|
|
|
tests/auto/tools/moc/subdir/extradefines.h | 1 +
|
|
|
|
tests/auto/tools/moc/tst_moc.cpp | 42 +++++++++++++++++++++
|
|
|
|
7 files changed, 158 insertions(+), 31 deletions(-)
|
|
|
|
create mode 100644 tests/auto/tools/moc/subdir/extradefines.h
|
|
|
|
|
|
|
|
diff --git a/mkspecs/features/moc.prf b/mkspecs/features/moc.prf
|
2015-12-18 15:17:43 +00:00
|
|
|
index c0b5682..af885c3 100644
|
2015-12-16 22:11:53 +00:00
|
|
|
--- a/mkspecs/features/moc.prf
|
|
|
|
+++ b/mkspecs/features/moc.prf
|
|
|
|
@@ -24,8 +24,25 @@ win32:count(MOC_INCLUDEPATH, 40, >) {
|
|
|
|
write_file($$absolute_path($$WIN_INCLUDETEMP, $$OUT_PWD), WIN_INCLUDETEMP_CONT)|error("Aborting.")
|
|
|
|
}
|
|
|
|
|
|
|
|
+# QNX's compiler sets "gcc" config, but does not support the -dM option;
|
|
|
|
+# iOS builds are multi-arch, so this feature cannot possibly work.
|
|
|
|
+if(gcc|intel_icl|msvc):!rim_qcc:!ios {
|
|
|
|
+ moc_predefs.CONFIG = no_link
|
|
|
|
+ gcc: moc_predefs.commands = $$QMAKE_CXX $$QMAKE_CXXFLAGS -dM -E -o ${QMAKE_FILE_OUT} ${QMAKE_FILE_IN}
|
|
|
|
+ else:intel_icl: moc_predefs.commands = $$QMAKE_CXX $$QMAKE_CXXFLAGS -QdM -P -Fi${QMAKE_FILE_OUT} ${QMAKE_FILE_IN}
|
|
|
|
+ else:msvc {
|
|
|
|
+ # make sure that our bin dir is first in path, so qmake is found
|
|
|
|
+ moc_predefs.commands = PATH $$shell_path($$[QT_INSTALL_BINS/src]);%PATH%&
|
|
|
|
+ moc_predefs.commands += $$QMAKE_CXX -Bxqmake $$QMAKE_CXXFLAGS -E ${QMAKE_FILE_IN} 2>NUL >${QMAKE_FILE_OUT}
|
|
|
|
+ } else: error("Oops, I messed up")
|
|
|
|
+ moc_predefs.output = $$MOC_DIR/moc_predefs.h
|
|
|
|
+ moc_predefs.input = MOC_PREDEF_FILE
|
|
|
|
+ silent: moc_predefs.commands = @echo generating $$moc_predefs.output$$escape_expand(\n\t)@$$moc_predefs.commands
|
|
|
|
+ QMAKE_EXTRA_COMPILERS += moc_predefs
|
2015-12-18 15:17:43 +00:00
|
|
|
+ MOC_PREDEF_FILE = $$[QT_HOST_DATA/src]/mkspecs/features/data/dummy.cpp
|
2015-12-16 22:11:53 +00:00
|
|
|
+}
|
|
|
|
+
|
|
|
|
defineReplace(mocCmdBase) {
|
|
|
|
- RET =
|
|
|
|
!isEmpty(WIN_INCLUDETEMP) {
|
|
|
|
incvar = @$$WIN_INCLUDETEMP
|
|
|
|
} else {
|
|
|
|
@@ -34,7 +51,13 @@ defineReplace(mocCmdBase) {
|
|
|
|
incvar += -I$$shell_quote($$inc)
|
|
|
|
incvar += $$QMAKE_FRAMEWORKPATH_FLAGS
|
|
|
|
}
|
|
|
|
- RET += $$QMAKE_MOC $(DEFINES) $$join(QMAKE_COMPILER_DEFINES, " -D", -D) $$incvar $$QMAKE_MOC_OPTIONS
|
|
|
|
+
|
|
|
|
+ RET = $$QMAKE_MOC $(DEFINES)
|
|
|
|
+
|
|
|
|
+ isEmpty(MOC_PREDEF_FILE): RET += $$join(QMAKE_COMPILER_DEFINES, " -D", -D)
|
|
|
|
+ else: RET += --include $$moc_predefs.output
|
|
|
|
+
|
|
|
|
+ RET += $$incvar $$QMAKE_MOC_OPTIONS
|
|
|
|
return($$RET)
|
|
|
|
}
|
|
|
|
|
|
|
|
@@ -46,7 +69,7 @@ moc_header.output = $$MOC_DIR/$${QMAKE_H_MOD_MOC}${QMAKE_FILE_BASE}$${first(QMAK
|
|
|
|
moc_header.input = HEADERS
|
|
|
|
moc_header.variable_out = SOURCES
|
|
|
|
moc_header.name = MOC ${QMAKE_FILE_IN}
|
|
|
|
-moc_header.depends += $$WIN_INCLUDETEMP
|
|
|
|
+moc_header.depends += $$WIN_INCLUDETEMP $$moc_predefs.output
|
|
|
|
silent:moc_header.commands = @echo moc ${QMAKE_FILE_IN} && $$moc_header.commands
|
|
|
|
QMAKE_EXTRA_COMPILERS += moc_header
|
|
|
|
INCREDIBUILD_XGE += moc_header
|
|
|
|
@@ -58,7 +81,7 @@ moc_source.commands = ${QMAKE_FUNC_mocCmdBase} ${QMAKE_FILE_IN} -o ${QMAKE_FILE_
|
|
|
|
moc_source.output = $$MOC_DIR/$${QMAKE_CPP_MOD_MOC}${QMAKE_FILE_BASE}$${QMAKE_EXT_CPP_MOC}
|
|
|
|
moc_source.input = SOURCES OBJECTIVE_SOURCES
|
|
|
|
moc_source.name = MOC ${QMAKE_FILE_IN}
|
|
|
|
-moc_source.depends += $$WIN_INCLUDETEMP
|
|
|
|
+moc_source.depends += $$WIN_INCLUDETEMP $$moc_predefs.output
|
|
|
|
silent:moc_source.commands = @echo moc ${QMAKE_FILE_IN} && $$moc_source.commands
|
|
|
|
QMAKE_EXTRA_COMPILERS += moc_source
|
|
|
|
INCREDIBUILD_XGE += moc_source
|
|
|
|
diff --git a/qmake/main.cpp b/qmake/main.cpp
|
|
|
|
index bde537d..e9b8bde 100644
|
|
|
|
--- a/qmake/main.cpp
|
|
|
|
+++ b/qmake/main.cpp
|
|
|
|
@@ -1,6 +1,7 @@
|
|
|
|
/****************************************************************************
|
|
|
|
**
|
|
|
|
** Copyright (C) 2015 The Qt Company Ltd.
|
|
|
|
+** Copyright (C) 2015 Intel Corporation.
|
|
|
|
** Contact: http://www.qt.io/licensing/
|
|
|
|
**
|
|
|
|
** This file is part of the qmake application of the Qt Toolkit.
|
|
|
|
@@ -47,6 +48,10 @@
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
|
|
|
|
+#ifdef Q_OS_WIN
|
|
|
|
+# include <qt_windows.h>
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
QT_BEGIN_NAMESPACE
|
|
|
|
|
|
|
|
#ifdef Q_OS_WIN
|
|
|
|
@@ -246,6 +251,30 @@ static int doInstall(int argc, char **argv)
|
|
|
|
return 3;
|
|
|
|
}
|
|
|
|
|
|
|
|
+static int dumpMacros(const wchar_t *cmdline)
|
|
|
|
+{
|
|
|
|
+ // from http://stackoverflow.com/questions/3665537/how-to-find-out-cl-exes-built-in-macros
|
|
|
|
+ int argc;
|
|
|
|
+ wchar_t **argv = CommandLineToArgvW(cmdline, &argc);
|
|
|
|
+ if (!argv)
|
|
|
|
+ return 2;
|
|
|
|
+ for (int i = 0; i < argc; ++i) {
|
|
|
|
+ if (argv[i][0] != L'-' || argv[i][1] != 'D')
|
|
|
|
+ continue;
|
|
|
|
+
|
|
|
|
+ wchar_t *value = wcschr(argv[i], L'=');
|
|
|
|
+ if (value) {
|
|
|
|
+ *value = 0;
|
|
|
|
+ ++value;
|
|
|
|
+ } else {
|
|
|
|
+ // point to the NUL at the end, so we don't print anything
|
|
|
|
+ value = argv[i] + wcslen(argv[i]);
|
|
|
|
+ }
|
|
|
|
+ wprintf(L"#define %Ls %Ls\n", argv[i] + 2, value);
|
|
|
|
+ }
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
#endif // Q_OS_WIN
|
|
|
|
|
|
|
|
/* This is to work around lame implementation on Darwin. It has been noted that the getpwd(3) function
|
|
|
|
@@ -280,6 +309,15 @@ int runQMake(int argc, char **argv)
|
|
|
|
// Workaround for inferior/missing command line tools on Windows: make our own!
|
|
|
|
if (argc >= 2 && !strcmp(argv[1], "-install"))
|
|
|
|
return doInstall(argc - 2, argv + 2);
|
|
|
|
+
|
|
|
|
+ {
|
|
|
|
+ // Support running as Visual C++'s compiler
|
|
|
|
+ const wchar_t *cmdline = _wgetenv(L"MSC_CMD_FLAGS");
|
|
|
|
+ if (!cmdline || !*cmdline)
|
|
|
|
+ cmdline = _wgetenv(L"MSC_IDE_FLAGS");
|
|
|
|
+ if (cmdline && *cmdline)
|
|
|
|
+ return dumpMacros(cmdline);
|
|
|
|
+ }
|
|
|
|
#endif
|
|
|
|
|
|
|
|
QMakeVfs vfs;
|
|
|
|
diff --git a/src/tools/moc/main.cpp b/src/tools/moc/main.cpp
|
|
|
|
index a5cbad7..d06335d 100644
|
|
|
|
--- a/src/tools/moc/main.cpp
|
|
|
|
+++ b/src/tools/moc/main.cpp
|
|
|
|
@@ -259,6 +259,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"));
|
|
|
|
@@ -406,7 +411,16 @@ int runMoc(int argc, char **argv)
|
|
|
|
moc.includes = pp.includes;
|
|
|
|
|
|
|
|
// 1. preprocess
|
|
|
|
- moc.symbols = pp.preprocessed(moc.filename, &in);
|
|
|
|
+ foreach (const QString &includeName, parser.values(includeOption)) {
|
|
|
|
+ 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);
|
|
|
|
|
|
|
|
if (!pp.preprocessOnly) {
|
|
|
|
// 2. parse
|
|
|
|
diff --git a/src/tools/moc/preprocessor.cpp b/src/tools/moc/preprocessor.cpp
|
|
|
|
index d036c40..70cf14a 100644
|
|
|
|
--- a/src/tools/moc/preprocessor.cpp
|
|
|
|
+++ b/src/tools/moc/preprocessor.cpp
|
|
|
|
@@ -1001,6 +1001,37 @@ 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;
|
|
|
|
+ QByteArray frameworkCandidate = include.left(slashPos);
|
|
|
|
+ frameworkCandidate.append(".framework/Headers/");
|
|
|
|
+ fi.setFile(QString::fromLocal8Bit(QByteArray(p.path + '/' + frameworkCandidate).constData()), 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);
|
|
|
|
@@ -1021,33 +1052,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;
|
|
|
|
- QByteArray frameworkCandidate = include.left(slashPos);
|
|
|
|
- frameworkCandidate.append(".framework/Headers/");
|
|
|
|
- fi.setFile(QString::fromLocal8Bit(QByteArray(p.path + '/' + frameworkCandidate).constData()), 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;
|
|
|
|
@@ -1202,6 +1209,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 9c81f86..d876caf 100644
|
|
|
|
--- a/src/tools/moc/preprocessor.h
|
|
|
|
+++ b/src/tools/moc/preprocessor.h
|
|
|
|
@@ -67,6 +67,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);
|
|
|
|
diff --git a/tests/auto/tools/moc/subdir/extradefines.h b/tests/auto/tools/moc/subdir/extradefines.h
|
|
|
|
new file mode 100644
|
|
|
|
index 0000000..e7888ce
|
|
|
|
--- /dev/null
|
|
|
|
+++ b/tests/auto/tools/moc/subdir/extradefines.h
|
|
|
|
@@ -0,0 +1 @@
|
|
|
|
+#define FOO 1
|
|
|
|
diff --git a/tests/auto/tools/moc/tst_moc.cpp b/tests/auto/tools/moc/tst_moc.cpp
|
|
|
|
index fa1b68b..1d6a911 100644
|
|
|
|
--- a/tests/auto/tools/moc/tst_moc.cpp
|
|
|
|
+++ b/tests/auto/tools/moc/tst_moc.cpp
|
|
|
|
@@ -552,6 +552,8 @@ private slots:
|
|
|
|
void frameworkSearchPath();
|
|
|
|
void cstyleEnums();
|
|
|
|
void defineMacroViaCmdline();
|
|
|
|
+ void defineMacroViaForcedInclude();
|
|
|
|
+ void defineMacroViaForcedIncludeRelative();
|
|
|
|
void specifyMetaTagsFromCmdline();
|
|
|
|
void invokable();
|
|
|
|
void singleFunctionKeywordSignalAndSlot();
|
|
|
|
@@ -1219,6 +1221,46 @@ void tst_Moc::defineMacroViaCmdline()
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
+void tst_Moc::defineMacroViaForcedInclude()
|
|
|
|
+{
|
|
|
|
+#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(QT_NO_PROCESS)
|
|
|
|
+ QProcess proc;
|
|
|
|
+
|
|
|
|
+ QStringList args;
|
|
|
|
+ args << "--include" << m_sourceDirectory + QLatin1String("/subdir/extradefines.h");
|
|
|
|
+ args << m_sourceDirectory + QStringLiteral("/macro-on-cmdline.h");
|
|
|
|
+
|
|
|
|
+ proc.start(m_moc, args);
|
|
|
|
+ QVERIFY(proc.waitForFinished());
|
|
|
|
+ QCOMPARE(proc.exitCode(), 0);
|
|
|
|
+ QCOMPARE(proc.readAllStandardError(), QByteArray());
|
|
|
|
+ QByteArray mocOut = proc.readAllStandardOutput();
|
|
|
|
+ QVERIFY(!mocOut.isEmpty());
|
|
|
|
+#else
|
|
|
|
+ QSKIP("Only tested on linux/gcc");
|
|
|
|
+#endif
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void tst_Moc::defineMacroViaForcedIncludeRelative()
|
|
|
|
+{
|
|
|
|
+#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(QT_NO_PROCESS)
|
|
|
|
+ QProcess proc;
|
|
|
|
+
|
|
|
|
+ QStringList args;
|
|
|
|
+ args << "--include" << QStringLiteral("extradefines.h") << "-I" + m_sourceDirectory + "/subdir";
|
|
|
|
+ args << m_sourceDirectory + QStringLiteral("/macro-on-cmdline.h");
|
|
|
|
+
|
|
|
|
+ proc.start(m_moc, args);
|
|
|
|
+ QVERIFY(proc.waitForFinished());
|
|
|
|
+ QCOMPARE(proc.exitCode(), 0);
|
|
|
|
+ QCOMPARE(proc.readAllStandardError(), QByteArray());
|
|
|
|
+ QByteArray mocOut = proc.readAllStandardOutput();
|
|
|
|
+ QVERIFY(!mocOut.isEmpty());
|
|
|
|
+#else
|
|
|
|
+ QSKIP("Only tested on linux/gcc");
|
|
|
|
+#endif
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
// tst_Moc::specifyMetaTagsFromCmdline()
|
|
|
|
// plugin_metadata.h contains a plugin which we register here. Since we're not building this
|
|
|
|
// application as a plugin, we need top copy some of the initializer code found in qplugin.h:
|
|
|
|
--
|
|
|
|
1.9.3
|
|
|
|
|