probonopd / linuxdeployqt

Makes Linux applications self-contained by copying in the libraries and plugins that the application uses, and optionally generates an AppImage. Can be used for Qt and other applications
Other
2.17k stars 408 forks source link

Bundling QML/QtQuick may need 2 runs #25

Open userappgate opened 7 years ago

userappgate commented 7 years ago

as of title ("List depend on qtdeclarative5-dev-tools")

userappgate commented 7 years ago

it errors out, about the lack of that binary. I don't know if it should actually be included in the appimage but isn't.

probonopd commented 7 years ago

Can you provide a link to the application that you are trying to bundle?

userappgate commented 7 years ago

https://github.com/Swordfish90/cool-retro-term

This. I compiled it locally and it works fine.

probonopd commented 7 years ago
sudo apt-get update
sudo apt install gitbuild-essential qmlscene libgl1-mesa-dev
cd cool-retro-term
git clone --recursive https://github.com/Swordfish90/cool-retro-term.git
cd cool-retro-term
export PATH=/tmp/.mount_QtCreator-5.7.0-x86_64/5.7/gcc_64/bin/:$PATH
qmake
make

./cool-retro-term 
# This application failed to start because it could not find or load the Qt platform plugin "xcb"
in "".

export QT_PLUGIN_PATH=/tmp/.mount_QtCreator-5.7.0-x86_64/5.7/gcc_64/plugins/
export LD_LIBRARY_PATH=/tmp/.mount_QtCreator-5.7.0-x86_64/5.7/gcc_64/lib/
export QTDIR=/tmp/.mount_QtCreator-5.7.0-x86_64/5.7/gcc_64 # not needed?

./cool-retro-term QQmlApplicationEngine failed to load component
qrc:/main.qml:24 module "QtGraphicalEffects" is not installed
qrc:/main.qml:23 module "QtQuick.Controls" is not installed
qrc:/main.qml:22 module "QtQuick.Window" is not installed
qrc:/main.qml:21 module "QtQuick" is not installed
qrc:/main.qml:24 module "QtGraphicalEffects" is not installed
qrc:/main.qml:23 module "QtQuick.Controls" is not installed
qrc:/main.qml:22 module "QtQuick.Window" is not installed
qrc:/main.qml:21 module "QtQuick" is not installed
qrc:/main.qml:24 module "QtGraphicalEffects" is not installed
qrc:/main.qml:23 module "QtQuick.Controls" is not installed
qrc:/main.qml:22 module "QtQuick.Window" is not installed
qrc:/main.qml:21 module "QtQuick" is not installed
qrc:/main.qml:24 module "QtGraphicalEffects" is not installed
qrc:/main.qml:23 module "QtQuick.Controls" is not installed
qrc:/main.qml:22 module "QtQuick.Window" is not installed
qrc:/main.qml:21 module "QtQuick" is not installed

# When I do

export QML2_IMPORT_PATH=/tmp/.mount_QtCreator-5.7.0-x86_64/5.7/gcc_64/qml/

# then it runs.

Looks like the code to bundle QML is there but /home/me/build-linuxdeployqt-Desktop_Qt_5_7_0_GCC_64bit-Debug/linuxdeployqt/linuxdeployqt /home/me/cool-retro-term/cool-retro-term -qmldir=/home/me/cool-retro-term/qml -verbose=3 must be used.

When doing this, then some of the QML plugins do get copied to qml/ but the bundled app still complains:

QQmlApplicationEngine failed to load component
qrc:/main.qml:24 module "QtGraphicalEffects" is not installed

Cannot load QML interface

Copying in all the files under 5.7/gcc_64/qml/QtGraphicalEffects solves this, then we get

QQmlApplicationEngine failed to load component
qrc:/main.qml:132 Type ApplicationSettings unavailable
qrc:/ApplicationSettings.qml:26 Type Storage unavailable
qrc:/Storage.qml:22 module "QtQuick.LocalStorage" is not installed

Cannot load QML interface

Deploying 5.7/gcc_64/qml/QtQuick/LocalStorage would solve this.

When I copy in the missing parts manually, then the lack of running patchelf makes it not work (tries to load Qt components from system Qt in /sur/lib which obviously fails). However, when I run linuxdeployqt a second time, it does the patching.

So it is possible to bundle cool-retro-term with some manual tweaking, but linuxdeployqt still needs to be worked on, so that no manual intervention will be necessary.

probonopd commented 7 years ago

Working with some manual steps:

sudo apt-get update
sudo apt install gitbuild-essential qmlscene libgl1-mesa-dev
git clone --recursive https://github.com/Swordfish90/cool-retro-term.git
cd cool-retro-term
export PATH=/tmp/.mount_QtCreator-5.7.0-x86_64/5.7/gcc_64/bin/:$PATH
qmake
make
cd ..
wget https://transfer.sh/tlUbT/linuxdeployqt.appimage
chmod a+x linuxdeployqt.appimage
./linuxdeployqt.appimage /home/me/cool-retro-term/cool-retro-term -qmldir=/home/me/cool-retro-term/qmltermwidget/

# Work around https://github.com/probonopd/linuxdeployqt/issues/25
cp -r /tmp/.mount_QtCreator-5.7.0-x86_64/5.7/gcc_64/qml/QtQuick/Dialogs cool-retro-term/qml/QtQuick/
cp -r /tmp/.mount_QtCreator-5.7.0-x86_64/5.7/gcc_64/qml/QtQuick/PrivateWidgets cool-retro-term/qml/QtQuick/
cp -r /tmp/.mount_QtCreator-5.7.0-x86_64/5.7/gcc_64/qml/QtQuick/LocalStorage cool-retro-term/qml/QtQuick/

# Run again so that the manually copied in libraries get their rpath set
./linuxdeployqt.appimage /home/me/cool-retro-term/cool-retro-term -qmldir=/home/me/cool-retro-term/qmltermwidget/

cool-retro-term/cool-retro-term # runs!
probonopd commented 7 years ago

So the remaining question is:

Why doesn't it deploy

automatically?

userappgate commented 7 years ago

It could be because AFAIK QML is run dynamically, so probably the files are loaded at runtime and paths do not appear in the binary?

probonopd commented 7 years ago

We might have inherited this issue: https://bugreports.qt.io/browse/QTBUG-45977

larpon commented 7 years ago

The only "fix" I've been able to come up with in my python version was to let the user specify the dynamically loaded QML imports in the arguments like this: --qml-import "QtMultimedia 5.0" --qml-import "QtQuick.Dialogs 1.2"

Then write a temporary dummy .qml file using those imports and run qmlimportscanner on that. Not beautiful but it works.

probonopd commented 7 years ago

80aca76 Fix bundling of QtQuick/PrivateWidgets. Still have to run linuxdeployqt twice so that it finds all Sql libs. Why? Otherwise, works. No more manual copying needed.

probonopd commented 7 years ago

Also in https://github.com/probonopd/xdgurl-1/blob/patch-1/.travis.yml, https://travis-ci.org/probonopd/xdgurl-1/builds/171791783

probonopd commented 7 years ago

Still need to run twice, https://github.com/probonopd/linuxdeployqt/commit/4b2c81ff84ac4b869ce60eb2651d6d1bd5cb6b0b

Revert this once running twice is no longer needed.

probonopd commented 7 years ago

QtQuick.Layouts gets deployed now, but QtQuick.Controls doesn't. Why? What can we do to have it deployed automatically?

Would we have to parse all qml files for statements like

import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.0

and deploy these? How do macedployqt and windeployqt solve this? Is this what qmlimportscanner is supposed to do?

larpon commented 7 years ago

Are you relying on qmlimportscanner? Some of the guys at QtMob says it's got a bad habit of not finding things. I was recommended to have a dummy file, e.g. imports.qml in the project root directory with all (or troublesome) imports in it. So until it's fixed you might want to roll your own import scanner? :-/

probonopd commented 7 years ago

Yes I am using qmlimportscanner, but perhaps I am running it with the wrong arguments?

larpon commented 7 years ago

It never hurts to double check - just wanted to note that it's known to be inconsistent in it's import discoveries (some runs work - some runs don't) - I've experienced it several times now with the version from 5.6.x

probonopd commented 7 years ago

See https://github.com/probonopd/linuxdeployqt/issues/78#issuecomment-280933299 for my current suspicion

TheAssassin commented 6 years ago

I guess the algorithm checking for libraries should just be implemented like here: https://github.com/Genymobile/copydeps

They just create a dependency tree (a real tree structure, see the graphics), then traverse the graph, and have the list of libraries to bundle. That shouldn't be too hard to implement on our side, too.

I'd love to be able to generate such graphs with linuxdeployqt, too.

probonopd commented 6 years ago

PR welcome! :+1: :100: