Развертывание Qt и QML приложений в Linux и Windows

linux, Переносимость приложений, deploy, Развертывание, Qt, Run Linux Application, cqtdeployer, переносимость qt, windows, QML, deployment

Введение

В данной статье мы рассмотрим, как правильно собрать все зависимости qt для вашего приложения, которое было собрано динамически.

Для начало немного теории

Зачем это нужно?

Существует несколько способов сборки приложений, основные из них это:

  • Статическая сборка.
    Статическая сборка подразумевает создание бинарника, в котором будут слинковоны все необходимые ему компоненты. Другими словами все что нужно для его работы будет лежать в нем. Такой подход удобен для маленьких консольных приложений, у которых мало зависимостей, в противном случае размер конечного бинарника будет крайне велик.

  • Динамическая сборка.
    Отличается от статической тем, что в бинарнике будут лежать только исходные тексты вашего приложения (размер бинарника будет минимальный), но при выполнении такого приложения ему понадобятся сторонние библиотеки, которые использовались при его написании.

Теперь немного описания

Console-QtDeployer — это простая утилита, аналогичная windeployqt и macdeployqt . Но в отличие от аналогов имеет куда более гибкий интерфейс (флаги запуска) и более высокую скорость работы, к тому же она поддерживает 2 платформы windows и linux а это значит что теперь мы сможете собирать зависимости под windows на Linux и наоборот.

Давайте рассмотрим пример

Для примера я написал простое 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.
Если попробовать запустить приложение, сразу после сборки мы получим ошибку:

~/MyApp$ ./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)

Из сходных текстов мы видим, что приложение зависит от GUI библиотек qt и библиотек qml. Поиск и сборка всех ресурсов (библиотек и плагинов) займет очень много времени.
Чтобы сэкономить время и силы, мы воспользуемся утилитой CQtDeployer (скачать можно здесь )
или установить в Snap Store

Загрузите из Snap Store

cqtdeployer -bin myApp -qmake /media/D/Qt/5.12.3/gcc_64/bin/qmake -qmlDir ./

После выполнения данной команды, вы получите полностью готовое для работы приложение с готовым лаунчером, который настроит все необходимое окружение для работы вашего приложения на всех машинах под управлением Linux.

Давайте подробнее рассмотрим некоторые из параметров CQtDeployer:

Опция Описание
help / h Показывает справку
always-overwrite Копирует файлы с заменой уже существующих
-bin [list, params] Развертываемый файл или папка. пример -bin ~/my/project/bin/,~/my/project/bin.exe
-binDir [params] Папка с развертываемыми файлами (с рекурсивным поиском). ВНИМАНИЕ! Этот флаг поддерживает только файлы 'so', 'dll' и 'exe'. Если вы хотите развернуть бинарный файл Linux, используйте флаг '-bin'
-qmlDir [params] Папка qml. пример -qmlDir ~/my/project/qml
deploySystem Копирует все библиотеки
-qmake [params] Путь к qmake. пример
-qmake ~/Qt/5.11.1/gcc_64/bin/qmake
-ignore [list,params] Список библиотек для игнорирования
Пример -ignore libicudata.so.56,libicudata2.so.56
-ignoreEnv [list,params] Список путей для игнорирования.
Пример -ignoreEnv /bad/dir,/my/bad/Dir
clear Удаляет все старые файлы (с прошлого запуска)
пример -runScript myApp.sh
allQmlDependes Извлекает все библиотеки qml.
(не рекомендуется, так как занимает много памяти)
-libDir [list,params] Устанавливает дополнительные пути к библиотекам
Пример -libDir ~/myLib,~/newLibs
-extraPlugin [list,params] Устанавливает дополнительный путь для extraPlugin приложения
-recursiveDepth [params] Устанавливает глубину поиска библиотек (по умолчанию 0)
-targetDir [params] Устанавливает целевой каталог (по умолчанию это путь к первому развертываемому файлу)
noStrip Пропускает шаг strip
noTranslations Пропускает файлы переводов
qmlExtern Использует внешний сканер qml (qmlimportscaner)
не работает без qmake и в snap
-verbose [0-3] Показывает дебаг лога

Итог

После выполнения cqtdeployer у вас появится папка Distro c уже готовым приложением со всеми его зависимостями содержимое этой папки должно выглядеть примерно следующим образом:

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/


cqtdeployer result

  • myApp.sh — скрипт запуска вашего приложения
  • bin — папка с вашим бинарником
  • lib — папка со всеми необходимыми зависимости вашего приложения
  • plugins — qt плагины, необходимые для работы приложения
  • qml — зависимости qml.
  • translations — стандартные переводы qt.

Таким образом можно подготовить ваше приложения для упаковки в deb или snap пакет, после чего можно приступить к его распространению. Учитывайте, что после выполнения cqtdeployer, ваше приложение необходимо запускать с помощью sh скрипта, который настроит для вашего приложения необходимое окружение.

Для Windows все точно так же. только в консоли нужно будет писать не cqtdeployer а %cqtdeployer%

Рекомендуем хостинг TIMEWEB
Рекомендуем хостинг TIMEWEB
Стабильный хостинг, на котором располагается социальная сеть EVILEG. Для проектов на Django рекомендуем VDS хостинг.
- блог компании

Напишите прожалуйста пример запуска для Windows :-)

отбой Разобрался.... После линуха сложно :-)

Возможно кому то пригодится

сqtdeployer для windows работает точно так же как и для Linux

разница лишь в команде запуска

  • Linux: cqtdeployer
  • Windows: %cqtdeployer%

Подробная инструкция использования под Windows:

  1. Качаем онлайн истолятор на момент версии 1.2.3 интерполятор не подписан, по этому Windows может ругаться.
  2. Устанавливаем
  3. Открываем cmd
  4. Пишем %cqdeployer%

Вот моя строка по которой все отлично сработало

%cqtdeployer% -bin c:/CentralMposKeys/CentalMposKeys.exe -qmake c:/Qt/5.12.2/mingw73_64/bin/qmake.exe

Комментарии

Только авторизованные пользователи могут публиковать комментарии.
Пожалуйста, авторизуйтесь или зарегистрируйтесь
Ищу работу?
25,000.00 руб. - 30,000.00 руб.
Разработчик Qt/C++
Barnaul, Altai Krai, Russia

Для зарегистрированных пользователей на сайте присутствует минимальное количество рекламы

ДП
19 октября 2019 г. 1:45
Дмитрий Пасынков

C++ - Тест 001. Первая программа и типы данных

  • Результат:26баллов,
  • Очки рейтинга-10
AS
18 октября 2019 г. 13:27
Artem Sergeevich

C++ - Тест 001. Первая программа и типы данных

  • Результат:13баллов,
  • Очки рейтинга-10
МБ
18 октября 2019 г. 11:05
Михаил Булатов

C++ - Тест 001. Первая программа и типы данных

  • Результат:86баллов,
  • Очки рейтинга6
Последние комментарии
17 октября 2019 г. 2:17
Евгений Легоцкой

Используем, там где требуется :)
MP
17 октября 2019 г. 2:15
Mikhail Petrov

Совет: подключайте ресурсы динамически. Используйте Resource Compiler: https://doc.qt.io/qt-5/rcc.html
16 октября 2019 г. 6:45
Евгений Легоцкой

Если это не чистой воды спам, а по делу, то без проблем. Но в таком случае лучше создавайте отдельный вопрос на форуме . При создании вопроса есть поле, в котором можно указать статью…
КК
16 октября 2019 г. 6:39
Кирилл Кирилыч

А тут можно ссылки на сторонний ресурс показывать? Нашёл на habr похожую статью, только там чуток отличается код и про локальный сервер написано, нужно чтоб кто то понимающий посмотрел и своё …
Сейчас обсуждают на форуме
18 октября 2019 г. 13:30
Евгений Легоцкой

Добрый день. У вас там пробелы находятся в тексте, поэтому и не может сконвертировать. фукция map применяет float ко все символам в каждой строке. В том числе и к символам пробела. А пробе…
17 октября 2019 г. 10:31
Руслан Волшебник

Я вас понял) Спасибо ещё раз. Вы помогли мне во всём разобраться.
t
17 октября 2019 г. 4:13
tupo_chel

И тебе спасибо за помощь)
17 октября 2019 г. 2:14
Евгений Легоцкой

Добрый день. Ну да, этот вариант жизнеспособен. Есть только один момент, который вам необходимо понимать в данном случае. И чего в этой статье или нет, или сказано как-то совсем вскользь, …
EVILEG
О нас
Услуги
© EVILEG 2015-2019
Рекомендует хостинг TIMEWEB