diff options
| author | ruki <[email protected]> | 2022-06-11 08:56:52 +0800 |
|---|---|---|
| committer | GitHub <[email protected]> | 2022-06-11 08:56:52 +0800 |
| commit | 5b718c4f9ac86a13edc1ac5e7c135ac2a3022b4a (patch) | |
| tree | 14edb1035f4a49028c0969b7c14e7ad15ae0bbd6 | |
| parent | 6228b34ad91719e309bef698f7c611887040b825 (diff) | |
| parent | 4331ffcbbb032102f16b0a7516c690b64516e824 (diff) | |
Merge pull request #2447 from Arthapz/qtquick-plugins
Add qt.qmlplugin rule and support of qmltypesregistrar
| -rw-r--r-- | tests/projects/qt/quickplugin/src/Foo.cpp | 16 | ||||
| -rw-r--r-- | tests/projects/qt/quickplugin/src/Foo.h | 22 | ||||
| -rw-r--r-- | tests/projects/qt/quickplugin/src/Plugin.cpp | 10 | ||||
| -rw-r--r-- | tests/projects/qt/quickplugin/src/Plugin.h | 10 | ||||
| -rw-r--r-- | tests/projects/qt/quickplugin/xmake.lua | 8 | ||||
| -rw-r--r-- | xmake/rules/qt/env/xmake.lua | 4 | ||||
| -rw-r--r-- | xmake/rules/qt/moc/xmake.lua | 3 | ||||
| -rw-r--r-- | xmake/rules/qt/qmltyperegistrar/xmake.lua | 125 | ||||
| -rw-r--r-- | xmake/rules/qt/xmake.lua | 7 |
9 files changed, 204 insertions, 1 deletions
diff --git a/tests/projects/qt/quickplugin/src/Foo.cpp b/tests/projects/qt/quickplugin/src/Foo.cpp new file mode 100644 index 000000000..d4065cb52 --- /dev/null +++ b/tests/projects/qt/quickplugin/src/Foo.cpp @@ -0,0 +1,16 @@ +#include "Foo.h" + +Foo::Foo(QObject *parent) : QObject { parent }, m_bar{ 0 } { +} + +int Foo::bar() const noexcept { + return m_bar; +} + +void Foo::setBar(int bar) noexcept { + if (bar == m_bar) return; + + m_bar = bar; + + Q_EMIT barChanged(m_bar); +}
\ No newline at end of file diff --git a/tests/projects/qt/quickplugin/src/Foo.h b/tests/projects/qt/quickplugin/src/Foo.h new file mode 100644 index 000000000..71e2b0e23 --- /dev/null +++ b/tests/projects/qt/quickplugin/src/Foo.h @@ -0,0 +1,22 @@ +#include <QtCore/QObject> +#include <QtQml/qqml.h> + +class Foo: public QObject { + Q_OBJECT + Q_PROPERTY(int bar READ bar WRITE setBar NOTIFY barChanged) + QML_NAMED_ELEMENT(Foo) + + public: + explicit Foo(QObject *parent = nullptr); + + int bar() const noexcept; + void setBar(int bar) noexcept; + + Q_SIGNALS: + void barChanged(int bar); + + private: + int m_bar; +}; + +QML_DECLARE_TYPE(Foo) diff --git a/tests/projects/qt/quickplugin/src/Plugin.cpp b/tests/projects/qt/quickplugin/src/Plugin.cpp new file mode 100644 index 000000000..9138c68b0 --- /dev/null +++ b/tests/projects/qt/quickplugin/src/Plugin.cpp @@ -0,0 +1,10 @@ +#include "Plugin.h" + +void qml_register_types_My_Plugin(); + +///////////////////////////////////// +///////////////////////////////////// +Plugin::Plugin(QObject *parent) : QQmlEngineExtensionPlugin { parent } { + volatile auto registration = &qml_register_types_My_Plugin; + Q_UNUSED(registration); +} diff --git a/tests/projects/qt/quickplugin/src/Plugin.h b/tests/projects/qt/quickplugin/src/Plugin.h new file mode 100644 index 000000000..72f7b6466 --- /dev/null +++ b/tests/projects/qt/quickplugin/src/Plugin.h @@ -0,0 +1,10 @@ +#include <QtCore/QObject> +#include <QtQml/QQmlEngineExtensionPlugin> + +class Plugin: public QQmlEngineExtensionPlugin { + Q_OBJECT + Q_PLUGIN_METADATA(IID QQmlEngineExtensionInterface_iid) + + public: + explicit Plugin(QObject *parent = nullptr); +}; diff --git a/tests/projects/qt/quickplugin/xmake.lua b/tests/projects/qt/quickplugin/xmake.lua new file mode 100644 index 000000000..afd4cc59b --- /dev/null +++ b/tests/projects/qt/quickplugin/xmake.lua @@ -0,0 +1,8 @@ +add_rules("mode.debug", "mode.release") + +target("demo") + add_rules("qt.qmlplugin") + add_headerfiles("src/*.h") + add_files("src/*.cpp") + + set_values("qt.qmlplugin.import_name", "My.Plugin")
\ No newline at end of file diff --git a/xmake/rules/qt/env/xmake.lua b/xmake/rules/qt/env/xmake.lua index 4cc39794c..47bc0760c 100644 --- a/xmake/rules/qt/env/xmake.lua +++ b/xmake/rules/qt/env/xmake.lua @@ -34,6 +34,10 @@ rule("qt.env") target:add("runenvs", "PATH", qt.bindir) target:set("runenv", "QML2_IMPORT_PATH", qt.qmldir) target:set("runenv", "QML_IMPORT_TRACE", "1") + + if not target:is_plat("mingw") then + target:add("cxxflags", "/permissive-") + end elseif target:is_plat("msys", "cygwin") then raise("please run `xmake f -p mingw --mingw=/mingw64` to support Qt/Mingw64 on Msys!") end diff --git a/xmake/rules/qt/moc/xmake.lua b/xmake/rules/qt/moc/xmake.lua index 5a10f73f8..2092ebe71 100644 --- a/xmake/rules/qt/moc/xmake.lua +++ b/xmake/rules/qt/moc/xmake.lua @@ -78,8 +78,9 @@ rule("qt.moc") table.insert(flags, pathitem) end end + local user_flags = target:get("qt.moc.flags") or {} batchcmds:mkdir(path.directory(sourcefile_moc)) - batchcmds:vrunv(moc, table.join(flags, path(sourcefile), "-o", path(sourcefile_moc))) + batchcmds:vrunv(moc, table.join(user_flags, flags, path(sourcefile), "-o", path(sourcefile_moc))) -- we need compile this moc_xxx.cpp file if exists Q_PRIVATE_SLOT, @see https://github.com/xmake-io/xmake/issues/750 local mocdata = io.readfile(sourcefile) diff --git a/xmake/rules/qt/qmltyperegistrar/xmake.lua b/xmake/rules/qt/qmltyperegistrar/xmake.lua new file mode 100644 index 000000000..38a04bbc4 --- /dev/null +++ b/xmake/rules/qt/qmltyperegistrar/xmake.lua @@ -0,0 +1,125 @@ +--!A cross-platform build utility based on Lua +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author arthapz +-- @file xmake.lua +-- + +rule("qt.qmltyperegistrar") + add_deps("qt.env") + set_extensions(".h", ".hpp") + + on_load(function(target) + -- get qt + local qt = assert(target:data("qt"), "qt not found!") + + -- get qmltyperegistrar + local qmltyperegistrar = path.join(qt.bindir, is_host("windows") and "qmltyperegistrar.exe" or "qmltyperegistrar") + if not os.isexec(qmltyperegistrar) and qt.libexecdir then + qmltyperegistrar = path.join(qt.libexecdir, is_host("windows") and "qmltyperegistrar.exe" or "qmltyperegistrar") + end + if not os.isexec(qmltyperegistrar) and qt.libexecdir_host then + qmltyperegistrar = path.join(qt.libexecdir_host, is_host("windows") and "qmltyperegistrar.exe" or "qmltyperegistrar") + end + assert(qmltyperegistrar and os.isexec(qmltyperegistrar), "qmltyperegistrar not found!") + + -- set targetdir + local importname = target:values("qt.qmlplugin.import_name") + assert(importname, "QML plugin import name not set") + + local targetdir = path.join(target:targetdir(), "imports") + for _, dir in pairs(importname:split(".", { plain = true })) do + targetdir = path.join(targetdir, dir) + end + os.mkdir(targetdir) + target:set("targetdir", targetdir) + + -- add qmldir + local qmldir = target:values("qt.qmlplugin.qmldirfile") + if qmldir then + target:add("installfiles", qmldir) + end + + -- add qmltypes + target:add("installfiles", target:get("targetdir") .. "/plugin.qmltypes") + + local sourcefile = path.join(target:autogendir(), "rules", "qt", "qmltyperegistrar", target:name() .. "_qmltyperegistrations.cpp") + local sourcefile_dir = path.directory(sourcefile) + os.mkdir(sourcefile_dir) + target:data_set("qt.qmlplugin.sourcefile", sourcefile) + + -- add moc arguments + target:add("qt.moc.flags", "--output-json") + + -- save qmltyperegistrar + target:data_set("qt.qmltyperegistrar", qmltyperegistrar) + -- save qmltyperegistrar + target:data_set("qt.qmlplugin.qmltyperegistrar", qmltyperegistrar) + end) + + on_buildcmd_files(function(target, batchcmds, sourcebatch, opt) + + -- setup qmltyperegistrar arguments + local qmltyperegistrar = target:data("qt.qmltyperegistrar") + local sourcefile = target:data("qt.qmlplugin.sourcefile") + + local importname = target:values("qt.qmlplugin.import_name") + local majorversion = target:values("qt.qmlplugin.majorversion") or 1 + local minorversion = target:values("qt.qmlplugin.minorversion") or 0 + + local metatypefiles = {} + for _, mocedfile in ipairs(sourcebatch.sourcefiles) do + target:add("includedirs", path.directory(mocedfile)) + local basename = path.basename(mocedfile) + local filename_moc = "moc_" .. basename .. ".cpp" + if mocedfile:endswith(".cpp") then + filename_moc = basename .. ".moc" + end + local sourcefile_moc = target:autogenfile(path.join(path.directory(mocedfile), filename_moc)) + table.insert(metatypefiles, path(sourcefile_moc .. ".json")) + end + + local args = { + "--generate-qmltypes=" .. target:get("targetdir") .. "/plugin.qmltypes", + "--import-name=" .. importname, + "--major-version=" .. majorversion, + "--minor-version=" .. minorversion, + "-o", sourcefile + } + + -- gen sourcefile + batchcmds:show_progress(opt.progress, "${color.build.object}generate.qt.qmltyperegistrar %s", path.filename(sourcefile)) + qmltype_source = os.vrunv(qmltyperegistrar, table.join(args, metatypefiles)) + + -- add objectfile + local objectfile = target:objectfile(sourcefile) + table.insert(target:objectfiles(), objectfile) + + -- compile sourcefile + batchcmds:show_progress(opt.progress, "${color.build.object}compile.qt.qmltyperegistrar %s", path.filename(sourcefile)) + batchcmds:compile(sourcefile, objectfile) + + batchcmds:add_depfiles(sourcefile) + batchcmds:set_depmtime(os.mtime(objectfile)) + batchcmds:set_depcache(target:dependfile(objectfile)) + end) + + after_build(function(target) + local qmldir = target:values("qml.plugin.qmldirfile") + if qmldir then + os.cp(qmldir, target:targetdir()) + end + end)
\ No newline at end of file diff --git a/xmake/rules/qt/xmake.lua b/xmake/rules/qt/xmake.lua index b26a458a5..b8cc59cfd 100644 --- a/xmake/rules/qt/xmake.lua +++ b/xmake/rules/qt/xmake.lua @@ -235,6 +235,13 @@ rule("qt.quickapp_static") on_install("android", "install.android") after_install("windows", "install.windows") +-- define rule: qt qmlplugin +rule("qt.qmlplugin") + add_deps("qt.shared", "qt.qmltyperegistrar") + on_load(function(target) + import("load")(target, {frameworks = { "QtCore", "QtGui", "QtQuick", "QtQml", "QtNetwork" }}) + end) + -- define rule: qt application (deprecated) rule("qt.application") add_deps("qt.quickapp", "qt.ui") |
