From 44118fcfef5fcbf9caffcf1f6a9d46df2a1ca0bc Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Wed, 12 Feb 2025 11:05:48 +0100 Subject: [PATCH] moc: Do not accept empty input files on --collect-json ... and also don't generate them on --output-json. That was an invitation for build time race conditions. Change-Id: I206ee47f08aa657f9b1cbec4e9e9b3ea97605cae Reviewed-by: Thiago Macieira --- src/tools/moc/collectjson.cpp | 6 ++++-- src/tools/moc/main.cpp | 14 ++++++++++---- src/tools/moc/moc.cpp | 19 +++++++++++++------ src/tools/moc/moc.h | 1 + tests/auto/tools/moc/allmocs_baseline_in.json | 4 ++++ 5 files changed, 32 insertions(+), 12 deletions(-) diff --git a/src/tools/moc/collectjson.cpp b/src/tools/moc/collectjson.cpp index bc56d7d15b4..620fa78c149 100644 --- a/src/tools/moc/collectjson.cpp +++ b/src/tools/moc/collectjson.cpp @@ -12,8 +12,10 @@ static bool readFromFile(QFile *device, QJsonArray *allMetaObjects) { const QByteArray contents = device->readAll(); - if (contents.isEmpty()) - return true; + if (contents.isEmpty()) { + fprintf(stderr, "%s:0: metatypes input file is empty\n", qPrintable(device->fileName())); + return false; + } QJsonParseError error {}; QJsonDocument metaObjects = QJsonDocument::fromJson(contents, &error); diff --git a/src/tools/moc/main.cpp b/src/tools/moc/main.cpp index 71f3d86567f..472dac38039 100644 --- a/src/tools/moc/main.cpp +++ b/src/tools/moc/main.cpp @@ -580,11 +580,17 @@ int runMoc(int argc, char **argv) if (pp.preprocessOnly) { fprintf(out.get(), "%s\n", composePreprocessorOutput(moc.symbols).constData()); + } else if (moc.classList.isEmpty()) { + moc.note("No relevant classes found. No output generated."); + if (jsonOutput) { + const QJsonDocument jsonDoc(QJsonObject { + { "outputRevision"_L1, mocOutputRevision }, + { "inputFile"_L1, QLatin1StringView(moc.strippedFileName()) } + }); + fputs(jsonDoc.toJson().constData(), jsonOutput.get()); + } } else { - if (moc.classList.isEmpty()) - moc.note("No relevant classes found. No output generated."); - else - moc.generate(out.get(), jsonOutput.get()); + moc.generate(out.get(), jsonOutput.get()); } out.reset(); diff --git a/src/tools/moc/moc.cpp b/src/tools/moc/moc.cpp index 73c5bdd9cc1..283a75dad20 100644 --- a/src/tools/moc/moc.cpp +++ b/src/tools/moc/moc.cpp @@ -1076,6 +1076,18 @@ void Moc::parse() } } +QByteArrayView Moc::strippedFileName() const +{ + QByteArrayView fn = QByteArrayView(filename); + + auto isSlash = [](char ch) { return ch == '/' || ch == '\\'; }; + auto rit = std::find_if(fn.crbegin(), fn.crend(), isSlash); + if (rit != fn.crend()) + fn = fn.last(rit - fn.crbegin()); + + return fn; +} + static bool any_type_contains(const QList &properties, const QByteArray &pattern) { for (const auto &p : properties) { @@ -1143,12 +1155,7 @@ static QByteArrayList requiredQtContainers(const QList &classes) void Moc::generate(FILE *out, FILE *jsonOutput) { - QByteArrayView fn = QByteArrayView(filename); - - auto isSlash = [](char ch) { return ch == '/' || ch == '\\'; }; - auto rit = std::find_if(fn.crbegin(), fn.crend(), isSlash); - if (rit != fn.crend()) - fn = fn.last(rit - fn.crbegin()); + QByteArrayView fn = strippedFileName(); fprintf(out, "/****************************************************************************\n" "** Meta object code from reading C++ file '%s'\n**\n" , fn.constData()); diff --git a/src/tools/moc/moc.h b/src/tools/moc/moc.h index 549c294867b..6ee48b83df1 100644 --- a/src/tools/moc/moc.h +++ b/src/tools/moc/moc.h @@ -242,6 +242,7 @@ public: QList parsedPluginMetadataFiles; void parse(); + QByteArrayView strippedFileName() const; void generate(FILE *out, FILE *jsonOutput); bool parseClassHead(ClassDef *def); diff --git a/tests/auto/tools/moc/allmocs_baseline_in.json b/tests/auto/tools/moc/allmocs_baseline_in.json index 7f99b1073a5..c3425c6d15f 100644 --- a/tests/auto/tools/moc/allmocs_baseline_in.json +++ b/tests/auto/tools/moc/allmocs_baseline_in.json @@ -3381,5 +3381,9 @@ ], "inputFile": "trigraphs.h", "outputRevision": 69 + }, + { + "inputFile": "using-namespaces.h", + "outputRevision": 69 } ]