Вступление
В этой статье мы рассмотрим, как правильно собрать все зависимости qt для вашего приложения, которое было собрано динамически.
Для начала немного теории.
Зачем это нужно?
Существует несколько способов сборки приложений, основные из них:
Статическая сборка.
Статическая сборка предполагает создание бинарника, в котором будут все необходимые ссылки на него. Другими словами, в нем будет лежать все, что нужно для его работы. Этот подход подходит для небольших консольных приложений, у которых мало зависимостей, иначе размер конечного бинарного файла будет чрезвычайно большим.Динамичная сборка.
Отличается от статического тем, что в бинарнике будет только исходный код вашего приложения (размер бинарника будет минимальным), но при запуске такого приложения ему потребуются сторонние библиотеки, которые использовались при его написании.
Теперь небольшое описание.
Console-QtDeployer — это простая утилита, похожая на windeployqt и macdeployqt . Но в отличии от аналогов у него гораздо более гибкий интерфейс (флаги запуска) и более высокая скорость, к тому же он поддерживает 2 платформы windows и linux, а значит теперь мы можем строить зависимости для windows на линуксе и наоборот.
Возьмем пример.
Например, я написал простое qt-приложение с использованием qml — MyApp.
MyApp (main.cpp)
#include <QGuiApplication> #include <QQmlApplicationEngine> int main (int argc, char * argv []) { QCoreApplication :: setAttribute (Qt :: AA_EnableHighDpiScaling); QGuiApplication app (argc, argv); QQmlApplicationEngine engine; engine.load (QUrl (QStringLiteral ("qrc: /main.qml"))); if (engine.rootObjects (). isEmpty ()) return -1; return app.exec (); }
MyApp (main.qml)
import QtQuick 2.9 import QtQuick.Controls 2.2 ApplicationWindow { visible: true width: 640 height: 480 title: qsTr ("Scroll") ScrollView { anchors.fill: parent ListView { width: parent.width model: 20 delegate: ItemDelegate { text: "Item" + (index + 1) width: parent.width } } } }
MyApp подключается динамически, то есть для работы ему нужны библиотеки qt.
Если мы попытаемся запустить приложение, то сразу после сборки получим ошибку:
~/build-MyApp-Desktop_Qt_5_11_1_GCC_64bit4-Release $ ./MyApp ./MyApp: /usr/lib/x86_64-linux-gnu/libQt5Qml.so.5: version `Qt_5 'not found (required by ./MyApp) ./MyApp: /usr/lib/x86_64-linux-gnu/libQt5Gui.so.5: version `Qt_5 'not found (required by ./MyApp) ./MyApp: /usr/lib/x86_64-linux-gnu/libQt5Core.so.5: version `Qt_5.11 'not found (required by ./MyApp) ./MyApp: /usr/lib/x86_64-linux-gnu/libQt5Core.so.5: version `Qt_5 'not found (required by ./MyApp)
Из подобных текстов мы видим, что приложение зависит от графических библиотек qt и qml. Поиск и сборка всех ресурсов (библиотек и плагинов) займет много времени.
Для экономии времени и сил воспользуемся утилитой CQtDeployer (ее можно скачать
здесь
)
или установить в Snap Store
cqtdeployer -bin myApp -qmake /media/D/Qt/5.12.3/gcc_64/bin/qmake -qmlDir ./
После выполнения этой команды вы получите полностью готовое приложение для работы с готовым лаунчером, который настроит все необходимые окружения для работы вашего приложения на всех машинах под управлением Linux.
Общее
После запуска Консоли QtDeployer содержимое папки с вашим приложением должно выглядеть так:
drwxr-xr-x 7 andrei andrei 4096 May 24 12:22 ./ drwxrwxr-x 3 andrei andrei 4096 May 24 12:22 ../ drwxr-xr-x 2 andrei andrei 4096 May 24 12:22 bin/ drwxr-xr-x 2 andrei andrei 4096 May 24 12:22 lib/ -rwx---rwx 1 andrei andrei 433 May 24 12:22 myApp.sh* drwxr-xr-x 6 andrei andrei 4096 May 24 12:22 plugins/ drwxr-xr-x 5 andrei andrei 4096 May 24 12:22 qml/ drwxr-xr-x 2 andrei andrei 4096 May 24 12:22 translations/
- myApp.sh - скрипт запуска вашего приложения
- bin - папка с вашим бинарником
- lib - папка со всеми необходимыми зависимостями вашего приложения.
- plugins - qt плагины, необходимые для работы приложения
- qml - qml зависимости.
- translations - стандартные переводы qt.
Таким образом, вы можете подготовить свое приложение к упаковке в deb или snap пакет, после чего можете приступить к его распространению. Обратите внимание, что после запуска cqtdeployer ваше приложение должно быть запущено с помощью скрипта sh, который настроит необходимое окружение для вашего приложения.
Напишите прожалуйста пример запуска для Windows :-)
отбой Разобрался.... После линуха сложно :-)
Возможно кому то пригодится
сqtdeployer для windows работает точно так же как и для Linux
разница лишь в команде запуска
Подробная инструкция использования под Windows:
Вот моя строка по которой все отлично сработало
написал приложение, холоворд на qt виджетах, без qml. Из визарда QtCreator. Собрал кросскомпилятором. Нужно перенести на таргет.
juvf@juvf-VirtualBox:~/qtWs/test/imx6/release$ ~/CQtDeployer/1.5/cqtdeployer.sh -bin test -qmake ~/soft/juvfTool/arm-buildroot-linux-gnueabihf/sysroot/home/juvf/tools/imx6/qt5_15_2_J/bin/qmake -qmlDir ./
Info: Deploy ...
Info: The targetDir option is not used. CQtDeployer will use default target dir :/home/juvf/qtWs/test/imx6/release/DistributionKit
Info: copy :/home/juvf/qtWs/test/imx6/release/test
Warning: Failed to extract qml! The qt qml dir is not initialized!
Warning: Failed to copy standard Qt translations
Info: deploy done!
Info: copy :/home/juvf/qtWs/test/imx6/release/DistributionKit/tmp_data/Application/bin/qt.conf
Info: copy :/home/juvf/qtWs/test/imx6/release/DistributionKit/tmp_data/Application/bin/test
Info: copy :/home/juvf/qtWs/test/imx6/release/DistributionKit/tmp_data/Application/test.sh
juvf@juvf-VirtualBox:~/qtWs/test/imx6/release$
после имею ТОЛЬКО скрипт test.sh и папку bin в которой два файла: само приложение test и файл qt.conf. Всё! Ни паки lib, ни plugin
перенёс всё на таргет. запускаю скриптом
./test.sh
/opt/argo/bin/test: error while loading shared libraries: libQt5Widgets.so.5: cannot open shared object file: No such file or directory
ну кагбэ неудевительно, что не может найти libQt5Widgets.so.5. Удевительно, что cqtdeployer не подтянул ни библиотеки, ни плагиины