woboq / qmetaobject-rs

Integrate Qml and Rust by building the QMetaObject at compile time.
MIT License
620 stars 89 forks source link

Deploying applications #45

Open LukasKnuth opened 4 years ago

LukasKnuth commented 4 years ago

Whats the recommended way to deploy an Application so that it runs on another computer without the QT SDK installed?

For Windows, I was able to get this working by putting all QML code into external files (loading them at runtime) and then running windeployqt --qmldir <qml-dir> <executable>.

Running this in a directory with only the release-binary from the /target/release-dir produces a 62MB directory with a lot of files in it. This works but seems iffy.

I have never deployed any kind of Qt application before.

ogoffart commented 4 years ago

Whats the recommended way to deploy an Application so that it runs on another computer without the QT SDK installed?

That is a good question. There is unfortunately no easy answer to it. The problem is the same as with any Qt application. On linux, you can try to use appimage for example. Or you can also try the Qt installer framework. Please let me know how that goes, i'm also interested by the result.

produces a 62MB directory with a lot of files in it.

62MB sounds a bit big, maybe it still packs lots of unnessesary components. I'm sure there are ways to optimize that.

Is there a way to create a single static binary with everything (Qt and Rust code) inside?

I guess that would be possible possible. Qt supports static build. So the qmetaobject crate's build.rs should be modified to pass the right compilation and link flag. One could imaging a feature for that. However this require that you compile a static build of Qt which is a bit tricky because of the plugins it uses.

Can I at least include the QML code into the binary and still create a deployment from it?

Yes, that you can do using the qrc! macro.

LukasKnuth commented 4 years ago

Thanks for all the info!

Quick follow-up question to qrc!-macro: I added this to the module:

qrc!(qml_resources, "qml" {
    "qml/test.qml" as "main.qml",
});

As you can see, the QML file is in a sub-directory named qml in my crate-directory. Then, in the main()-function, I call qml_resources(); and try to load the QML file from the resource by using QmlEngine::new().load_file("qrc:/main.qml".into());.

This compiles but gives me this error at runtime:

QQmlApplicationEngine failed to load component
qrc:/main.qml:-1 No such file or directory

How can I load the QML file from the resource bundle in the application? I got most of the info from this page: https://doc.qt.io/qt-5/qtquick-deployment.html#managing-resource-files-with-the-qt-resource-system

ogoffart commented 4 years ago

The todo example does that. https://github.com/woboq/qmetaobject-rs/blob/master/examples/todos/src/main.rs

Since you use "qml" for the directory in qrc, it would be load_file("qrc:/qml/main.qml".into());

Alternatively, you can do qrc!(qml_resources, "/" { ... so the files would be at the root.

LukasKnuth commented 4 years ago

Ah, I didn't understand that the first string in the macro will be part of the URL that you enter when loading a file. I got it working now, thanks!

I ran windeployqt again (I still had to point to the qml directory) went through its output and deleted all directories/dlls that weren't needed to launch the application. This gets it down to about 27MB.

Talking about static compilition again: As I understand it, I need a statically build Qt (see https://wiki.qt.io/Build_Standalone_Qt_Application_for_Windows#Build_a_static_application) and then modify the linker parameters in build.rs to encompass that. Am I missing something obvious?

Also, could I make this into something that can be enabled say for release-builds only? As I understand it, linking Qt statically will increase the built-time.

Thanks for your help btw!

Defaultldentity commented 4 years ago

On linux the build (for 0.1.2 crate) seems to be almost self-contained, except for QML modules (/usr/lib/x86_64-linux-gnu/qt5/qml/QtQuick.2/libqtquick2plugin.so and their metadata files). Is there a way to link them in statically?

tinywombat765 commented 3 years ago

If you're packing your software for Linux, your distro should already have the Qt libraries packaged. So you should be able to add them to your package's dependancy list.