qdbusxml2cpp: modify the behavior of -m/--moc option
qdbusxml2cpp has a -m/--moc option. Change and modify the behavior such that -p foo -m includes moc_foo.cpp in the generated .cpp -p :foo.cpp includes moc_foo.cpp in the generated .cpp -p foo.h:foo.cpp includes moc_foo.cpp in the generated .cpp Change the Qt6DbusMacros.cmake file accordingly. [ChangeLog][qdbusxml2cpp] The -m/--moc option now generates idiomatic moc file names (moc_base.cpp for headers, base.moc for implementation files)(was: always base.moc). Build systems using workarounds for the non-idiomatic naming of moc files used by qdbusxml2cpp in the past can now drop these workarounds for Qt versions >= 6.5. Fixes: QTBUG-103313 Change-Id: I754b1b276f130cb8645166470e1b457a676590f7 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Alexey Edelev <alexey.edelev@qt.io> Reviewed-by: Marc Mutz <marc.mutz@qt.io>
This commit is contained in:
parent
214953fad6
commit
aa99bf532d
@ -10,7 +10,7 @@ function(qt6_add_dbus_interface _sources _interface _basename)
|
||||
get_filename_component(_infile ${_interface} ABSOLUTE)
|
||||
set(_header "${CMAKE_CURRENT_BINARY_DIR}/${_basename}.h")
|
||||
set(_impl "${CMAKE_CURRENT_BINARY_DIR}/${_basename}.cpp")
|
||||
set(_moc "${CMAKE_CURRENT_BINARY_DIR}/${_basename}.moc")
|
||||
set(_moc "${CMAKE_CURRENT_BINARY_DIR}/moc_${_basename}.cpp")
|
||||
|
||||
get_source_file_property(_nonamespace ${_interface} NO_NAMESPACE)
|
||||
if(_nonamespace)
|
||||
@ -42,7 +42,7 @@ function(qt6_add_dbus_interface _sources _interface _basename)
|
||||
|
||||
qt6_generate_moc("${_header}" "${_moc}")
|
||||
|
||||
list(APPEND ${_sources} "${_impl}" "${_header}" "${_moc}")
|
||||
list(APPEND ${_sources} "${_impl}" "${_header}")
|
||||
macro_add_file_dependencies("${_impl}" "${_moc}")
|
||||
set(${_sources} ${${_sources}} PARENT_SCOPE)
|
||||
endfunction()
|
||||
@ -156,7 +156,7 @@ function(qt6_add_dbus_adaptor _sources _xml_file _include) # _optionalParentClas
|
||||
set(_optionalClassName "${ARGV5}")
|
||||
set(_header "${CMAKE_CURRENT_BINARY_DIR}/${_basename}.h")
|
||||
set(_impl "${CMAKE_CURRENT_BINARY_DIR}/${_basename}.cpp")
|
||||
set(_moc "${CMAKE_CURRENT_BINARY_DIR}/${_basename}.moc")
|
||||
set(_moc "${CMAKE_CURRENT_BINARY_DIR}/moc_${_basename}.cpp")
|
||||
|
||||
if(_optionalClassName)
|
||||
add_custom_command(OUTPUT "${_impl}" "${_header}"
|
||||
@ -179,7 +179,7 @@ function(qt6_add_dbus_adaptor _sources _xml_file _include) # _optionalParentClas
|
||||
)
|
||||
macro_add_file_dependencies("${_impl}" "${_moc}")
|
||||
|
||||
list(APPEND ${_sources} "${_impl}" "${_header}" "${_moc}")
|
||||
list(APPEND ${_sources} "${_impl}" "${_header}")
|
||||
set(${_sources} ${${_sources}} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
|
@ -85,16 +85,32 @@ static void cleanInterfaces(QDBusIntrospection::Interfaces &interfaces)
|
||||
}
|
||||
}
|
||||
|
||||
static bool isSupportedSuffix(QStringView suffix)
|
||||
{
|
||||
const QLatin1StringView candidates[] = {
|
||||
"h"_L1,
|
||||
"cpp"_L1,
|
||||
"cc"_L1
|
||||
};
|
||||
|
||||
for (auto candidate : candidates)
|
||||
if (suffix == candidate)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// produce a header name from the file name
|
||||
static QString header(const QString &name)
|
||||
{
|
||||
QStringList parts = name.split(u':');
|
||||
QString retval = parts.first();
|
||||
QString retval = parts.front();
|
||||
|
||||
if (retval.isEmpty() || retval == "-"_L1)
|
||||
return retval;
|
||||
|
||||
if (!retval.endsWith(".h"_L1) && !retval.endsWith(".cpp"_L1) && !retval.endsWith(".cc"_L1))
|
||||
QFileInfo header{retval};
|
||||
if (!isSupportedSuffix(header.suffix()))
|
||||
retval.append(".h"_L1);
|
||||
|
||||
return retval;
|
||||
@ -104,12 +120,13 @@ static QString header(const QString &name)
|
||||
static QString cpp(const QString &name)
|
||||
{
|
||||
QStringList parts = name.split(u':');
|
||||
QString retval = parts.last();
|
||||
QString retval = parts.back();
|
||||
|
||||
if (retval.isEmpty() || retval == "-"_L1)
|
||||
return retval;
|
||||
|
||||
if (!retval.endsWith(".h"_L1) && !retval.endsWith(".cpp"_L1) && !retval.endsWith(".cc"_L1))
|
||||
QFileInfo source{retval};
|
||||
if (!isSupportedSuffix(source.suffix()))
|
||||
retval.append(".cpp"_L1);
|
||||
|
||||
return retval;
|
||||
@ -118,12 +135,47 @@ static QString cpp(const QString &name)
|
||||
// produce a moc name from the file name
|
||||
static QString moc(const QString &name)
|
||||
{
|
||||
QString retval = header(name);
|
||||
if (retval.isEmpty())
|
||||
return retval;
|
||||
QString retval;
|
||||
const QStringList fileNames = name.split(u':');
|
||||
|
||||
if (fileNames.size() == 1) {
|
||||
QFileInfo fi{fileNames.front()};
|
||||
if (isSupportedSuffix(fi.suffix())) {
|
||||
// Generates a file that contains the header and the implementation: include "filename.moc"
|
||||
retval += fi.baseName();
|
||||
retval += ".moc"_L1;
|
||||
} else {
|
||||
// Separate source and header files are generated: include "moc_filename.cpp"
|
||||
retval += "moc_"_L1;
|
||||
retval += fi.baseName();
|
||||
retval += ".cpp"_L1;
|
||||
}
|
||||
} else {
|
||||
QString headerName = fileNames.front();
|
||||
QString sourceName = fileNames.back();
|
||||
|
||||
if (sourceName.isEmpty() || sourceName == "-"_L1) {
|
||||
// If only a header is generated, don't include anything
|
||||
} else if (headerName.isEmpty() || headerName == "-"_L1) {
|
||||
// If only source file is generated: include "moc_sourcename.cpp"
|
||||
QFileInfo source{sourceName};
|
||||
|
||||
retval += "moc_"_L1;
|
||||
retval += source.baseName();
|
||||
retval += ".cpp"_L1;
|
||||
|
||||
fprintf(stderr, "warning: no header name is provided, assuming it to be \"%s\"\n",
|
||||
qPrintable(source.baseName() + ".h"_L1));
|
||||
} else {
|
||||
// Both source and header generated: include "moc_headername.cpp"
|
||||
QFileInfo header{headerName};
|
||||
|
||||
retval += "moc_"_L1;
|
||||
retval += header.baseName();
|
||||
retval += ".cpp"_L1;
|
||||
}
|
||||
}
|
||||
|
||||
retval.truncate(retval.length() - 1); // drop the h in .h
|
||||
retval += "moc"_L1;
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@ -23,6 +23,8 @@ private slots:
|
||||
void includeStyle();
|
||||
void missingAnnotation_data();
|
||||
void missingAnnotation();
|
||||
void includeMoc_data();
|
||||
void includeMoc();
|
||||
};
|
||||
|
||||
struct BasicTypeList {
|
||||
@ -59,20 +61,21 @@ static QString stripHeader(QString output)
|
||||
return output.remove(header);
|
||||
}
|
||||
|
||||
static void runTool(QProcess &process, const QByteArray &data)
|
||||
static void runTool(QProcess &process, const QByteArray &data,
|
||||
const QStringList &flags)
|
||||
{
|
||||
// test both interface and adaptor generation
|
||||
QFETCH_GLOBAL(QString, commandLineArg);
|
||||
|
||||
// Run the tool
|
||||
const QString binpath = QLibraryInfo::path(QLibraryInfo::BinariesPath);
|
||||
QStringList arguments = { commandLineArg, "-", "-N" };
|
||||
QStringList arguments = { commandLineArg };
|
||||
arguments += flags;
|
||||
process.setArguments(arguments);
|
||||
process.setProgram(binpath + QLatin1String("/qdbusxml2cpp"));
|
||||
process.start(QIODevice::Text | QIODevice::ReadWrite);
|
||||
QVERIFY2(process.waitForStarted(), qPrintable(process.errorString()));
|
||||
|
||||
// feed it our XML data
|
||||
static const char xmlHeader[] =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"
|
||||
DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE // \n is included
|
||||
@ -97,6 +100,33 @@ static void runTool(QProcess &process, const QByteArray &data)
|
||||
QCOMPARE(process.exitStatus(), QProcess::NormalExit);
|
||||
}
|
||||
|
||||
static void checkOneFile(const QString &fileName, const QByteArray &expected)
|
||||
{
|
||||
QFile file(fileName);
|
||||
QVERIFY(file.exists());
|
||||
const auto guard = QScopeGuard([&](){ QFile::remove(fileName); });
|
||||
|
||||
QVERIFY(file.open(QFile::Text | QFile::ReadOnly));
|
||||
QByteArray text = file.readAll();
|
||||
QVERIFY(text.contains(expected));
|
||||
}
|
||||
|
||||
static void checkTwoFiles(const QString &headerName, const QString &sourceName, const QByteArray &expected)
|
||||
{
|
||||
QFile headerFile(headerName);
|
||||
QFile sourceFile(sourceName);
|
||||
|
||||
QVERIFY(headerFile.exists());
|
||||
const auto headerGuard = QScopeGuard([&](){ QFile::remove(headerName); });
|
||||
|
||||
QVERIFY(sourceFile.exists());
|
||||
const auto sourceGuard = QScopeGuard([&](){ QFile::remove(sourceName); });
|
||||
|
||||
QVERIFY(sourceFile.open(QFile::Text | QFile::ReadOnly));
|
||||
QByteArray text = sourceFile.readAll();
|
||||
QVERIFY(text.contains(expected));
|
||||
}
|
||||
|
||||
void tst_qdbusxml2cpp::initTestCase_data()
|
||||
{
|
||||
QTest::addColumn<int>("outputMode");
|
||||
@ -242,7 +272,8 @@ void tst_qdbusxml2cpp::process()
|
||||
|
||||
QFETCH_GLOBAL(int, outputMode);
|
||||
QProcess process;
|
||||
runTool(process, xmlSnippet.toLatin1());
|
||||
QStringList flags = {"-", "-N"};
|
||||
runTool(process, xmlSnippet.toLatin1(), flags);
|
||||
if (QTest::currentTestFailed()) return;
|
||||
|
||||
QByteArray errOutput = process.readAllStandardError();
|
||||
@ -271,34 +302,15 @@ void tst_qdbusxml2cpp::includeStyle()
|
||||
{
|
||||
QFETCH(bool, isGlobal);
|
||||
QFETCH(QByteArray, expected);
|
||||
QFETCH_GLOBAL(QString, commandLineArg);
|
||||
|
||||
// feed it our XML data
|
||||
static const char xml[] =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"
|
||||
DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE // \n is included
|
||||
"<node>\n"
|
||||
" <interface name=\"local.name.is.not.important\">\n"
|
||||
" </interface>\n"
|
||||
"</node>\n";
|
||||
|
||||
// Run the tool
|
||||
const QString binpath = QLibraryInfo::path(QLibraryInfo::BinariesPath);
|
||||
const QString command = binpath + QLatin1String("/qdbusxml2cpp");
|
||||
QProcess process;
|
||||
process.start(command, QStringList() << commandLineArg << "-" << "-N" << (isGlobal ? "-I" : "-i") << "test.hpp");
|
||||
QVERIFY2(process.waitForStarted(), qPrintable(process.errorString()));
|
||||
QStringList flags = {"-", "-N", (isGlobal ? "-I" : "-i"), "test.hpp"};
|
||||
|
||||
process.write(xml, int(sizeof xml) - 1);
|
||||
while (process.bytesToWrite())
|
||||
QVERIFY2(process.waitForBytesWritten(), qPrintable(process.errorString()));
|
||||
|
||||
process.closeWriteChannel();
|
||||
QVERIFY2(process.waitForFinished(), qPrintable(process.errorString()));
|
||||
runTool(process,QByteArray{},flags);
|
||||
QCOMPARE(process.exitCode(), 0);
|
||||
|
||||
QByteArray errOutput = process.readAllStandardError();
|
||||
QVERIFY2(errOutput.isEmpty(), errOutput);
|
||||
QCOMPARE(process.exitCode(), 0);
|
||||
|
||||
QByteArray fullOutput = process.readAll();
|
||||
QVERIFY(!fullOutput.isEmpty());
|
||||
@ -342,7 +354,8 @@ void tst_qdbusxml2cpp::missingAnnotation()
|
||||
|
||||
QString type = "(ii)";
|
||||
QProcess process;
|
||||
runTool(process, xmlSnippet.arg(type).toLatin1());
|
||||
QStringList flags = {"-", "-N"};
|
||||
runTool(process, xmlSnippet.arg(type).toLatin1(),flags);
|
||||
if (QTest::currentTestFailed()) return;
|
||||
|
||||
// it must have failed
|
||||
@ -358,6 +371,54 @@ You should add <annotation name="%2" value="<type>"/> to the XML description for
|
||||
QCOMPARE(errOutput, expected);
|
||||
}
|
||||
|
||||
void tst_qdbusxml2cpp::includeMoc_data()
|
||||
{
|
||||
QTest::addColumn<QString>("filenames");
|
||||
QTest::addColumn<QByteArray>("expected");
|
||||
QTest::addColumn<QByteArray>("warning");
|
||||
|
||||
QTest::newRow("combined-h") << "foo.h" << QByteArray("#include \"foo.moc\"") << QByteArray("");
|
||||
QTest::newRow("combined-cpp") << "foo.cpp" << QByteArray("#include \"foo.moc\"") << QByteArray("");
|
||||
QTest::newRow("combined-cc") << "foo.cc" << QByteArray("#include \"foo.moc\"") << QByteArray("");
|
||||
QTest::newRow("without extension") << "foo" << QByteArray("#include \"moc_foo.cpp\"") << QByteArray("");
|
||||
QTest::newRow("cpp-only") << ":foo.cpp" << QByteArray("#include \"moc_foo.cpp\"")
|
||||
<< QByteArray("warning: no header name is provided, assuming it to be \"foo.h\"");
|
||||
QTest::newRow("header-and-cpp") << "foo_h.h:foo.cpp" << QByteArray("#include \"moc_foo_h.cpp\"") << QByteArray("");
|
||||
}
|
||||
|
||||
void tst_qdbusxml2cpp::includeMoc()
|
||||
{
|
||||
QFETCH(QString, filenames);
|
||||
QFETCH(QByteArray, expected);
|
||||
QFETCH(QByteArray, warning);
|
||||
|
||||
QProcess process;
|
||||
QStringList flags = {filenames, "--moc"};
|
||||
runTool(process,QByteArray{},flags);
|
||||
QByteArray errOutput = process.readAllStandardError();
|
||||
QVERIFY(errOutput.startsWith(warning));
|
||||
QCOMPARE(process.exitCode(), 0);
|
||||
|
||||
QStringList parts = filenames.split(u':');
|
||||
QFileInfo first{parts.first()};
|
||||
|
||||
if ((parts.size() == 1) && (!first.suffix().isEmpty())) {
|
||||
checkOneFile(parts.first(), expected);
|
||||
} else if ((parts.size() == 1) && (first.suffix().isEmpty())) {
|
||||
QString headerName{parts.first()};
|
||||
headerName += ".h";
|
||||
QString sourceName{parts.first()};
|
||||
sourceName += ".cpp";
|
||||
|
||||
checkTwoFiles(headerName, sourceName, expected);
|
||||
} else if ((parts.size() == 2) && (parts.first().isEmpty())) {
|
||||
checkOneFile(parts.last(), expected);
|
||||
}
|
||||
else if ((parts.size() == 2) && !parts.first().isEmpty() && !parts.last().isEmpty()) {
|
||||
checkTwoFiles(parts.first(), parts.last(), expected);
|
||||
}
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_qdbusxml2cpp)
|
||||
|
||||
#include "tst_qdbusxml2cpp.moc"
|
||||
|
Loading…
x
Reference in New Issue
Block a user