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 <thiago.macieira@intel.com>
This commit is contained in:
Ulf Hermann 2025-02-12 11:05:48 +01:00
parent 06b7a9b19e
commit 44118fcfef
5 changed files with 32 additions and 12 deletions

View File

@ -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);

View File

@ -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();

View File

@ -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<PropertyDef> &properties, const QByteArray &pattern)
{
for (const auto &p : properties) {
@ -1143,12 +1155,7 @@ static QByteArrayList requiredQtContainers(const QList<ClassDef> &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());

View File

@ -242,6 +242,7 @@ public:
QList<QString> parsedPluginMetadataFiles;
void parse();
QByteArrayView strippedFileName() const;
void generate(FILE *out, FILE *jsonOutput);
bool parseClassHead(ClassDef *def);

View File

@ -3381,5 +3381,9 @@
],
"inputFile": "trigraphs.h",
"outputRevision": 69
},
{
"inputFile": "using-namespaces.h",
"outputRevision": 69
}
]