From ccd6fa219500a055703798a798731736f3b6a570 Mon Sep 17 00:00:00 2001 From: Pierre Lamot Date: Thu, 6 Jun 2024 18:05:45 +0200 Subject: [PATCH] qt module: add qml module test --- test cases/frameworks/4 qt/QmlMain.cpp | 10 + test cases/frameworks/4 qt/meson.build | 173 ------------------ test cases/frameworks/4 qt/qml/Basic.qml | 5 + test cases/frameworks/4 qt/qml/Internal.qml | 5 + test cases/frameworks/4 qt/qml/Main.qml | 42 +++++ .../frameworks/4 qt/qml/QmlCppExposed.hpp | 25 +++ .../4 qt/qml/QmlCppOtherExposed.hpp | 25 +++ test cases/frameworks/4 qt/qml/QmlMain.cpp | 12 ++ .../frameworks/4 qt/qml/QmlSingleton.qml | 10 + test cases/frameworks/4 qt/qml/custom_qmldir | 4 + .../frameworks/4 qt/qml/custom_qmldir.qrc | 5 + test cases/frameworks/4 qt/qml/meson.build | 63 +++++++ .../frameworks/4 qt/qml/subdir/Thing.qml | 5 + 13 files changed, 211 insertions(+), 173 deletions(-) create mode 100644 test cases/frameworks/4 qt/QmlMain.cpp delete mode 100644 test cases/frameworks/4 qt/meson.build create mode 100644 test cases/frameworks/4 qt/qml/Basic.qml create mode 100644 test cases/frameworks/4 qt/qml/Internal.qml create mode 100644 test cases/frameworks/4 qt/qml/Main.qml create mode 100644 test cases/frameworks/4 qt/qml/QmlCppExposed.hpp create mode 100644 test cases/frameworks/4 qt/qml/QmlCppOtherExposed.hpp create mode 100644 test cases/frameworks/4 qt/qml/QmlMain.cpp create mode 100644 test cases/frameworks/4 qt/qml/QmlSingleton.qml create mode 100644 test cases/frameworks/4 qt/qml/custom_qmldir create mode 100644 test cases/frameworks/4 qt/qml/custom_qmldir.qrc create mode 100644 test cases/frameworks/4 qt/qml/meson.build create mode 100644 test cases/frameworks/4 qt/qml/subdir/Thing.qml diff --git a/test cases/frameworks/4 qt/QmlMain.cpp b/test cases/frameworks/4 qt/QmlMain.cpp new file mode 100644 index 000000000000..16794fef3a27 --- /dev/null +++ b/test cases/frameworks/4 qt/QmlMain.cpp @@ -0,0 +1,10 @@ +#include +#include + +int main(int argCount, char* argVector[]) +{ + QGuiApplication app(argCount, argVector); + QQmlApplicationEngine engine; + engine.load("qrc:///qt/qml/Foo/Bar/QmlStuff.qml"); + app.exec(); +} diff --git a/test cases/frameworks/4 qt/meson.build b/test cases/frameworks/4 qt/meson.build deleted file mode 100644 index 54cd7cb9bac3..000000000000 --- a/test cases/frameworks/4 qt/meson.build +++ /dev/null @@ -1,173 +0,0 @@ -project('qt4, qt5, and qt6 build test', 'cpp', - # Qt6 requires C++ 17 support - default_options : ['cpp_std=c++17']) - -# Visit the subdir before entering the loop -subdir('mocdep') - -qt5_modules = ['Widgets'] -qt6_modules = ['Widgets'] -foreach qt : ['qt4', 'qt5', 'qt6'] - qt_modules = ['Core', 'Gui'] - if qt == 'qt5' - qt_modules += qt5_modules - elif qt == 'qt6' - qt_modules += qt6_modules - endif - - # Test that invalid modules are indeed not found - fakeqtdep = dependency(qt, modules : ['DefinitelyNotFound'], required : false, method : get_option('method')) - if fakeqtdep.found() - error('Invalid qt dep incorrectly found!') - endif - - # Test that partially-invalid modules are indeed not found - fakeqtdep = dependency(qt, modules : ['Core', 'DefinitelyNotFound'], required : false, method : get_option('method')) - if fakeqtdep.found() - error('Invalid qt dep incorrectly found!') - endif - - # This test should be skipped if the required version of Qt isn't found - # - # (In the CI environment, the specified version of Qt is definitely present. - # An unexpected skip here is treated as a failure, so we are testing that the - # detection mechanism is able to find Qt.) - needed_qt = get_option('required').to_lower() - required = (qt == needed_qt) - if required - dep = dependency(qt, modules : ['Core'], required : false, method : get_option('method')) - if not dep.found() - error('MESON_SKIP_TEST @0@ not found.'.format(needed_qt)) - endif - endif - - # Ensure that the "no-Core-module-specified" code branch is hit - nocoredep = dependency(qt, modules : ['Gui'], required : required, method : get_option('method')) - - # If 'qt' modules are found, test that. - qtdep = dependency(qt, modules : qt_modules, main : true, private_headers: true, required : required, method : get_option('method')) - if qtdep.found() - qtmodule = import(qt) - assert(qtmodule.has_tools(), 'You may be missing a devel package. (qttools5-dev-tools on Debian based systems)') - - # Test that fetching a variable works and yields a non-empty value - assert(qtdep.get_variable('prefix', configtool: 'QT_INSTALL_PREFIX') != '') - - # The following has two resource files because having two in one target - # requires you to do it properly or you get linker symbol clashes. - - prep = qtmodule.preprocess( - moc_headers : ['mainWindow.h'], # These need to be fed through the moc tool before use. - method : get_option('method') - ) - # XML files that need to be compiled with the uic tol. - prep += qtmodule.compile_ui( - sources : 'ui/mainWindow.ui', - method: get_option('method'), - preserve_paths: true) - - qtmodule.preprocess( - ui_files : 'ui/mainWindow.ui', - method: get_option('method'), - preserve_paths: true) - - # Resource file(s) for rcc compiler - extra_cpp_args = [] - if meson.is_unity() - extra_cpp_args += '-DUNITY_BUILD' - prep_rcc = qtmodule.preprocess(qt + '_unity_resource', qresources : ['stuff.qrc', 'stuff2.qrc'], method : get_option('method')) - else - prep_rcc = qtmodule.preprocess(qresources : ['stuff.qrc', 'stuff2.qrc'], method : get_option('method')) - endif - - # Test that setting a unique name with a positional argument works - qtmodule.compile_resources( - name : qt + 'teststuff', - sources : files(['stuff.qrc', 'stuff2.qrc']), - method : get_option('method') - ) - - # Test that passing extra arguments to rcc works - # qt4-rcc and qt5-rcc take different arguments, for example qt4: ['-compress', '3']; qt5: '--compress=3' - qtmodule.preprocess(qt + 'testrccarg', qresources : files(['stuff.qrc', 'stuff2.qrc']), rcc_extra_arguments : '--compress=3', method : get_option('method')) - - translations_cpp = qtmodule.compile_translations(qresource: qt+'_lang.qrc') - # unity builds suck and definitely cannot handle two qrc embeds in one compilation unit - unityproof_translations = static_library(qt+'unityproof_translations', translations_cpp, dependencies: qtdep) - - extra_cpp_args += '-DQT="@0@"'.format(qt) - qexe = executable(qt + 'app', - sources : ['main.cpp', 'mainWindow.cpp', # Sources that don't need preprocessing. - prep, prep_rcc], - dependencies : qtdep, - link_with: unityproof_translations, - cpp_args: extra_cpp_args, - gui_app : true) - - # We need a console test application because some test environments - # do not have an X server. - - translations = qtmodule.compile_translations(ts_files : qt+'core_fr.ts', build_by_default : true) - - qtcore = dependency(qt, modules : 'Core', method : get_option('method')) - - qtcoreapp = executable(qt + 'core', 'q5core.cpp', - cpp_args: '-DQT="@0@"'.format(qt), - dependencies : qtcore) - - test(qt + 'test', qtcoreapp) - - # The build system needs to include the cpp files from - # headers but the user must manually include moc - # files from sources. - qtmodule.preprocess( - moc_extra_arguments : ['-DMOC_EXTRA_FLAG'], # This is just a random macro to test `extra_arguments` - moc_sources : 'manualinclude.cpp', - moc_headers : 'manualinclude.h', - method : get_option('method'), - dependencies: mocdep, - ) - - manpreprocessed = qtmodule.compile_moc( - extra_args : ['-DMOC_EXTRA_FLAG'], # This is just a random macro to test `extra_arguments` - sources : 'manualinclude.cpp', - headers : 'manualinclude.h', - method : get_option('method'), - dependencies: mocdep, - ) - - qtmaninclude = executable(qt + 'maninclude', - sources : ['manualinclude.cpp', manpreprocessed], - dependencies : [qtcore, mocdep]) - - test(qt + 'maninclude', qtmaninclude) - - # building Qt plugins implies to give include path to moc - plugin_includes = include_directories('pluginInterface', 'plugin') - pluginpreprocess = qtmodule.preprocess( - moc_headers : 'plugin/plugin.h', - include_directories : plugin_includes - ) - plugin = library(qt + 'plugin', 'plugin/plugin.cpp', pluginpreprocess, - include_directories : plugin_includes, - dependencies : qtcore) - - # implementing Qt interfaces requires passing Qt include paths to moc - qtinterfacepreprocess = qtmodule.preprocess( - moc_sources : 'qtinterface.cpp', - dependencies : qtdep - ) - qtinterface = library(qt + 'qtinterface', - sources : ['qtinterface.cpp', qtinterfacepreprocess], - dependencies : qtdep) - - if qt == 'qt5' - subdir('subfolder') - endif - - # Check we can apply a version constraint - accept_versions = ['>=@0@'.format(qtdep.version()), '<@0@'.format(qtdep.version()[0].to_int() + 1)] - dependency(qt, modules: qt_modules, version: accept_versions, method : get_option('method')) - - endif -endforeach diff --git a/test cases/frameworks/4 qt/qml/Basic.qml b/test cases/frameworks/4 qt/qml/Basic.qml new file mode 100644 index 000000000000..33c0a28c70b0 --- /dev/null +++ b/test cases/frameworks/4 qt/qml/Basic.qml @@ -0,0 +1,5 @@ +import QtQuick 2.0 + +Item { + property int ok: 1 +} diff --git a/test cases/frameworks/4 qt/qml/Internal.qml b/test cases/frameworks/4 qt/qml/Internal.qml new file mode 100644 index 000000000000..e8eee472379b --- /dev/null +++ b/test cases/frameworks/4 qt/qml/Internal.qml @@ -0,0 +1,5 @@ +import QtQuick + +Item { + property int ok: 5 +} diff --git a/test cases/frameworks/4 qt/qml/Main.qml b/test cases/frameworks/4 qt/qml/Main.qml new file mode 100644 index 000000000000..7d2b0f6bbd23 --- /dev/null +++ b/test cases/frameworks/4 qt/qml/Main.qml @@ -0,0 +1,42 @@ +import QtQuick +import My.Module1 as M1 +import My.Module2 as M2 +import My.Module3 as M3 +import My.Module4 as M4 + +Item { + + M1.Basic { id: b1 } + M1.Thing { id: t1 } + M1.QmlCppExposed { id: c1 } + + M2.Thing { id: t2 } + + M3.Basic { id: b3 } + + M4.BasicAliased { id: b4 } + + Component.onCompleted: { + function checkClass(display, id, value) { + if (id.ok !== value) { + console.log(display, "KO got", id.ok, "expected", value) + Qt.exit(-1) + } + else + console.log(display, "OK") + } + + checkClass("M1.Basic", b1, 1); + checkClass("M1.Thing", t1, 2); + checkClass("M1.QmlCppExposed", c1, 3); + checkClass("M1.QmlSingleton", M1.QmlSingleton, 5); + + checkClass("M2.Thing", t2, 2); + + checkClass("M3.Basic", b3, 1); + + checkClass("M4.BasicAliased", b4, 1); + + Qt.quit() + } +} diff --git a/test cases/frameworks/4 qt/qml/QmlCppExposed.hpp b/test cases/frameworks/4 qt/qml/QmlCppExposed.hpp new file mode 100644 index 000000000000..10568c8b717e --- /dev/null +++ b/test cases/frameworks/4 qt/qml/QmlCppExposed.hpp @@ -0,0 +1,25 @@ +#pragma once +#include +#include + +class QmlCppExposed : public QObject +{ + Q_OBJECT + QML_ELEMENT + Q_PROPERTY(int ok READ getOk WRITE setOk NOTIFY okChanged) + +public: + inline int getOk() const { return m_ok; } + inline void setOk(int value) { + if (value == m_ok) + return; + m_ok = value; + emit okChanged(); + } + +signals: + void okChanged(); + +private: + int m_ok = 3; +}; diff --git a/test cases/frameworks/4 qt/qml/QmlCppOtherExposed.hpp b/test cases/frameworks/4 qt/qml/QmlCppOtherExposed.hpp new file mode 100644 index 000000000000..78426163566f --- /dev/null +++ b/test cases/frameworks/4 qt/qml/QmlCppOtherExposed.hpp @@ -0,0 +1,25 @@ +#pragma once +#include +#include + +class QmlCppOtherExposed : public QObject +{ + Q_OBJECT + QML_ELEMENT + Q_PROPERTY(int ok READ getOk WRITE setOk NOTIFY okChanged) + +public: + inline int getOk() const { return m_ok; } + inline void setOk(int value) { + if (value == m_ok) + return; + m_ok = value; + emit okChanged(); + } + +signals: + void okChanged(); + +private: + int m_ok = 42; +}; diff --git a/test cases/frameworks/4 qt/qml/QmlMain.cpp b/test cases/frameworks/4 qt/qml/QmlMain.cpp new file mode 100644 index 000000000000..6b53f44996e2 --- /dev/null +++ b/test cases/frameworks/4 qt/qml/QmlMain.cpp @@ -0,0 +1,12 @@ +#include +#include + +int main(int argCount, char* argVector[]) +{ + QGuiApplication app(argCount, argVector); + QQmlApplicationEngine engine; + engine.addImportPath("qrc:///qt/qml"); + engine.addImportPath("qrc:///test"); + engine.load("qrc:///qt/qml/My/Module0/Main.qml"); + return app.exec(); +} diff --git a/test cases/frameworks/4 qt/qml/QmlSingleton.qml b/test cases/frameworks/4 qt/qml/QmlSingleton.qml new file mode 100644 index 000000000000..73ea95d11bf6 --- /dev/null +++ b/test cases/frameworks/4 qt/qml/QmlSingleton.qml @@ -0,0 +1,10 @@ +pragma Singleton +import QtQuick + +Item { + property alias ok: sub.ok + + Internal { + id: sub + } +} diff --git a/test cases/frameworks/4 qt/qml/custom_qmldir b/test cases/frameworks/4 qt/qml/custom_qmldir new file mode 100644 index 000000000000..9d84db651401 --- /dev/null +++ b/test cases/frameworks/4 qt/qml/custom_qmldir @@ -0,0 +1,4 @@ +module My.Module4 +prefer :/qt/qml/My/Module4/ +BasicAliased 1.0 Basic.qml +Thing 1.0 Thing.qml diff --git a/test cases/frameworks/4 qt/qml/custom_qmldir.qrc b/test cases/frameworks/4 qt/qml/custom_qmldir.qrc new file mode 100644 index 000000000000..bee52092c587 --- /dev/null +++ b/test cases/frameworks/4 qt/qml/custom_qmldir.qrc @@ -0,0 +1,5 @@ + + + custom_qmldir + + diff --git a/test cases/frameworks/4 qt/qml/meson.build b/test cases/frameworks/4 qt/qml/meson.build new file mode 100644 index 000000000000..b3d1aa726d59 --- /dev/null +++ b/test cases/frameworks/4 qt/qml/meson.build @@ -0,0 +1,63 @@ +qmlmodule1 = qtmodule.qml_module( + qt + 'qmlmodule1', + 'My.Module1', + '1.0', + qml_sources: files('Basic.qml', 'subdir/Thing.qml'), + qml_singletons: files('QmlSingleton.qml'), + qml_internals: files('Internal.qml'), + moc_headers: files('QmlCppExposed.hpp', 'QmlCppOtherExposed.hpp'), + designer_supported: true, + dependencies: [qtdep], + install: true +) + +#with a different resource prefix +qmlmodule2 = qtmodule.qml_module( + qt + 'qmlmodule2', + 'My.Module2', + '1.0', + qml_sources: files('Basic.qml', 'subdir/Thing.qml'), + resources_prefix: '/test', + dependencies: [qtdep], +) + +#build without cachegen +qmlmodule3 = qtmodule.qml_module( + qt + 'qmlmodule3', + 'My.Module3', + '1.10', + qml_sources: files('Basic.qml', 'subdir/Thing.qml'), + cachegen: false, + dependencies: [qtdep], +) + +#build without cachegen +qmlmodule4 = qtmodule.qml_module( + qt + 'qmlmodule4', + 'My.Module4', + '1.10', + qml_sources: files('Basic.qml', 'subdir/Thing.qml'), + generate_qmldir: false, + dependencies: [qtdep], +) +qmlmodule4_res = qtmodule.compile_resources( + name : qt + 'qmlmodule4_resource', + sources : files(['custom_qmldir.qrc']), + method : get_option('method') +) + +#qml entry point and qmldir dependecies +qmlmodule0 = qtmodule.qml_module( + 'qmlmodule0', + 'My.Module0', + '1.0', + qml_sources: files('Main.qml'), + imports: ['QtQuick/2.0', 'My.Module1'], + optional_imports: ['My.Module2/auto'], + dependencies: [qtdep], +) + + +qmltest = executable(qt + '_qmlmodule', + sources : ['QmlMain.cpp', qmlmodule0, qmlmodule1, qmlmodule2, qmlmodule3, qmlmodule4, qmlmodule4_res], + dependencies : qtdep) diff --git a/test cases/frameworks/4 qt/qml/subdir/Thing.qml b/test cases/frameworks/4 qt/qml/subdir/Thing.qml new file mode 100644 index 000000000000..5b015c35ca01 --- /dev/null +++ b/test cases/frameworks/4 qt/qml/subdir/Thing.qml @@ -0,0 +1,5 @@ +import QtQuick 2.0 + +Item { + property int ok: 2 +}