Forward declare all types required for compilation with -trace

This patch fixes compilation with `-trace lttng` or `-trace etw`. We
need to forward declare QEvent, QImageReader etc., otherwise the types
will be unknown while compiling the trace points.

In order to handle this generically, the tracegen utility is extended
to support a 'prefix text' in the `*.tracepoints` input files. Any
text within curly braces will be embedded as-is in the generated file.
This can then be used to add forward declarations for the types we
need, including potential namespaces and such.

Change-Id: I5cb16763ce0fcb48ce3ea4577578d468ff3a4f4b
Reviewed-by: Konstantin Tokarev <annulen@yandex.ru>
This commit is contained in:
Milian Wolff 2019-03-26 14:07:03 +01:00
parent df7eec6bcb
commit 6ce2a87c23
7 changed files with 67 additions and 19 deletions

View File

@ -1,3 +1,9 @@
{
QT_BEGIN_NAMESPACE
class QEvent;
QT_END_NAMESPACE
}
QCoreApplicationPrivate_init_entry()
QCoreApplicationPrivate_init_exit()

View File

@ -1,3 +1,9 @@
{
QT_BEGIN_NAMESPACE
class QImageReader;
QT_END_NAMESPACE
}
QGuiApplicationPrivate_init_entry()
QGuiApplicationPrivate_init_exit()

View File

@ -110,19 +110,21 @@ static QString createGuid(const QUuid &uuid)
return guid;
}
static void writePrologue(QTextStream &stream, const QString &fileName, const QString &providerName)
static void writePrologue(QTextStream &stream, const QString &fileName, const Provider &provider)
{
QUuid uuid = QUuid::createUuidV5(QUuid(), providerName.toLocal8Bit());
QUuid uuid = QUuid::createUuidV5(QUuid(), provider.name.toLocal8Bit());
const QString provider = providerVar(providerName);
const QString providerV = providerVar(provider.name);
const QString guard = includeGuard(fileName);
const QString guid = createGuid(uuid);
const QString guidString = uuid.toString();
stream << "#ifndef " << guard << "\n"
<< "#define " << guard << "\n"
<< "\n"
<< "#include <windows.h>\n"
<< "#include <TraceLoggingProvider.h>\n";
<< "#include <TraceLoggingProvider.h>\n"
<< "\n";
/* TraceLogging API macros cannot deal with UTF8
* source files, so we work around it like this
@ -132,30 +134,33 @@ static void writePrologue(QTextStream &stream, const QString &fileName, const QS
"#define _TlgPragmaUtf8Begin\n"
"#define _TlgPragmaUtf8End\n";
stream << qtHeaders();
stream << "\n";
stream << qtHeaders();
stream << "\n";
if (!provider.prefixText.isEmpty())
stream << provider.prefixText.join(QLatin1Char('\n')) << "\n\n";
stream << "#ifdef TRACEPOINT_DEFINE\n"
<< "/* " << guidString << " */\n"
<< "TRACELOGGING_DEFINE_PROVIDER(" << provider << ", \""
<< providerName <<"\", " << guid << ");\n\n";
<< "TRACELOGGING_DEFINE_PROVIDER(" << providerV << ", \""
<< provider.name <<"\", " << guid << ");\n\n";
stream << "static inline void registerProvider()\n"
<< "{\n"
<< " TraceLoggingRegister(" << provider << ");\n"
<< " TraceLoggingRegister(" << providerV << ");\n"
<< "}\n\n";
stream << "static inline void unregisterProvider()\n"
<< "{\n"
<< " TraceLoggingUnregister(" << provider << ");\n"
<< " TraceLoggingUnregister(" << providerV << ");\n"
<< "}\n";
stream << "Q_CONSTRUCTOR_FUNCTION(registerProvider)\n"
<< "Q_DESTRUCTOR_FUNCTION(unregisterProvider)\n\n";
stream << "#else\n"
<< "TRACELOGGING_DECLARE_PROVIDER(" << provider << ");\n"
<< "TRACELOGGING_DECLARE_PROVIDER(" << providerV << ");\n"
<< "#endif // TRACEPOINT_DEFINE\n\n";
}
@ -224,7 +229,7 @@ void writeEtw(QFile &file, const Provider &provider)
const QString fileName = QFileInfo(file.fileName()).fileName();
writePrologue(stream, fileName, provider.name);
writePrologue(stream, fileName, provider);
writeTracepoints(stream, provider);
writeEpilogue(stream, fileName);
}

View File

@ -104,17 +104,22 @@ static void writeCtfMacro(QTextStream &stream, const Tracepoint::Field &field)
}
}
static void writePrologue(QTextStream &stream, const QString &fileName, const QString &providerName)
static void writePrologue(QTextStream &stream, const QString &fileName, const Provider &provider)
{
stream << "#undef TRACEPOINT_PROVIDER\n";
stream << "#define TRACEPOINT_PROVIDER " << providerName << "\n\n";
stream << qtHeaders();
const QString guard = includeGuard(fileName);
stream << "#undef TRACEPOINT_PROVIDER\n";
stream << "#define TRACEPOINT_PROVIDER " << provider.name << "\n";
stream << "\n";
// include prefix text or qt headers only once
stream << "#if !defined(" << guard << ")\n";
stream << qtHeaders();
stream << "\n";
if (!provider.prefixText.isEmpty())
stream << provider.prefixText.join(QLatin1Char('\n')) << "\n\n";
stream << "#endif\n\n";
/* the first guard is the usual one, the second is required
* by LTTNG to force the re-evaluation of TRACEPOINT_* macros
*/
@ -213,7 +218,7 @@ void writeLttng(QFile &file, const Provider &provider)
const QString fileName = QFileInfo(file.fileName()).fileName();
writePrologue(stream, fileName, provider.name);
writePrologue(stream, fileName, provider);
writeTracepoints(stream, provider);
writeEpilogue(stream, fileName);
}

View File

@ -275,9 +275,21 @@ Provider parseProvider(const QString &filename)
Provider provider;
provider.name = QFileInfo(filename).baseName();
bool parsingPrefixText = false;
for (int lineNumber = 1; !s.atEnd(); ++lineNumber) {
QString line = s.readLine().trimmed();
if (line == QLatin1String("{")) {
parsingPrefixText = true;
continue;
} else if (parsingPrefixText && line == QLatin1String("}")) {
parsingPrefixText = false;
continue;
} else if (parsingPrefixText) {
provider.prefixText.append(line);
continue;
}
if (line.isEmpty() || line.startsWith(QLatin1Char('#')))
continue;
@ -296,7 +308,14 @@ Provider parseProvider(const QString &filename)
}
}
if (parsingPrefixText) {
panic("Syntax error while processing '%s': "
"no closing brace found for prefix text block",
qPrintable(filename));
}
#ifdef TRACEGEN_DEBUG
qDebug() << provider.prefixText;
for (auto i = provider.tracepoints.constBegin(); i != provider.tracepoints.constEnd(); ++i)
dumpTracepoint(*i);
#endif

View File

@ -86,6 +86,7 @@ struct Provider
{
QString name;
QVector<Tracepoint> tracepoints;
QStringList prefixText;
};
Provider parseProvider(const QString &filename);

View File

@ -1,3 +1,9 @@
{
QT_BEGIN_NAMESPACE
class QEvent;
QT_END_NAMESPACE
}
QApplication_notify_entry(QObject *receiver, QEvent *event, int type)
QApplication_notify_event_filtered(QObject *receiver, QEvent *event, int type)
QApplication_notify_before_delivery(QObject *receiver, QEvent *event, int type)