Андрей Янкович
Наурыз 24, 2020, 7:50 Т.Қ.

C++/Qt және QML қолданбасын орналастыру утилитасының CQtDeployer v1.4.0 шығарылымы (екілік қорап)

Спустя почти полгода вышло крупное обновление утилиты развертывания CQtDeployer.
В этом обновлении много нововведений, но основной упор сделан на создание пакетов.


CQtDeployer 1.4.0

Исправления

  • Исправлен вывод справки в консоль, теперь перед выводом пересчитывается реальный размер консоли, что позволяет корректно передавать текст.
  • Исправлена работа с деплоем плагинов Qt. Теперь плагины извлекают не все системные зависимости, а только qt. Извлечение системных зависимостей приводило к сбою приложений из-за несовместимых библиотек плагинов.
  • Мелкие исправления ошибок и улучшения.

Новые особенности

  • Добавлена поддержка поиска qmake из системной среды.
  • Добавлена возможность инициализировать репозиторий для дальнейшей упаковки, аналогично git init.
  • Добавлена поддержка пакетов Qt Install Framework. Теперь можно запаковать дистрибутив в установщик.
  • Добавлена возможность разбивать конечный дистрибутив на несколько пакетов.
  • Добавлена возможность унифицировать создание пакетов для финальной раздачи.
  • Добавлена поддержка добавления пользовательских скриптов в скрипты запуска приложений.
  • Добавлена поддержка извлечения системных зависимостей для Windows.
  • Добавлена поддержка RPATH для Linux. Теперь cqtdeployer может самостоятельно определить необходимый qmake для развертывания приложения.
  • Добавлена поддержка поиска нужной зависимости по имени библиотеки.
  • Добавлена поддержка библиотек Qt из репозиториев дистрибутивов Linux.
  • Добавлен новый псевдоним для команды запуска (cqt и cqtdeployer.cqt) для быстрого развертывания приложений.
  • Добавлена поддержка нативного имени команды для windows. Теперь вы можете запустить cqtdeployer из команды cqtdeployer в cmd и powershell.

Новые опции

  • init - инициализирует файл cqtdeployer.json (файл конфигурации). Например: «cqtdeployer init» — для инициализации конфигурации базового пакета. «cqtdeployer -init multi» — для инициализации конфигурации нескольких пакетов.
  • noCheckRPATH - отключает автоматический поиск путей к qmake в исполняемых файлах (только для Linux).
  • noCheckPATH - отключает автоматический поиск путей к qmake в системном окружении.
  • ExtractPlugins - принудительно извлекает все зависимости плагинов.
    -qif - создает установщик в конце развертывания.
  • extraLibs - добавляет шаблон для дополнительной библиотеки, которая должна быть включена в дистрибутив.
  • customScript - добавляет пользовательский скрипт в скрипт запуска приложения.
    --targetPackage [пакет; tar1, пакет; tar2] — используется для формирования пакетов, обозначает списки целевых файлов для конкретных пакетов.
    — recOut — указывает, в какую папку будут добавлены ресурсы после развертывания.
  • name - задает имя пакета.
  • description - устанавливает описание пакета
  • deployVersion — устанавливает версию пакета
  • releaseDate — устанавливает дату выпуска пакета.
  • icon - задает значок пакета.
  • publisher - устанавливает издателя пакета.
  • qifStyle - Задает путь к файлу стилей CSS или задает стиль по умолчанию. Доступные стили: квазар
  • qifBanner - Устанавливает путь к png файлу баннера.
  • qifLogo - Устанавливает путь к png файлу логотипа.

Ссылки для скачивания

Установщик:

Установщик можно скачать на социальной странице github

Snap

Get it from the Snap Store

Внимание

В снап-версии обязательно дайте программе доступ на чтение других процессов. Так как это необходимо для создания установщика и корректного поиска qt.

Подробный разбор самых интересных изменений.

Первое, на что следует обратить внимание, это то, что CQtDeployer научился работать с RPATH (только для Linux) и PATH. Это означает, что если ваше приложение собрано с поддержкой RPATH (а RPATH в qt включен по умолчанию) или ваш qmake прописан в PATH, то вам не нужно указывать путь к qmake. CQtDeployer сам найдет qmake.

Проверим на практике.
Я создал простое консольное приложение с помощью Qt.

  1. #include <QString>
  2. #include <QDebug>
  3. int main(int, char *[])
  4. {
  5. QString str = "hello CQtDeployer 1.4";
  6. qInfo() << str;
  7. return 0;
  8. }

Я буду использовать систему сборки cmake, так как она более актуальна, чем qmake.

  1. andrei@HP:~/Hello$ tree
  2. .
  3. ├── CMakeLists.txt
  4. ├── CMakeLists.txt.user
  5. └── main.cpp
  6.  
  7. 0 directories, 3 files

Создайте папку для сборки.

  1. andrei@HP:~/Hello$ mkdir build

Запустите cmake в созданной папке.

  1. andrei@HP:~/Hello/build$ cmake .. -DCMAKE_PREFIX_PATH=~/Qt/5.14.1/gcc_64
  2. -- Configuring done
  3. -- Generating done
  4. -- Build files have been written to: /home/andrei/Hello/build

создание проекта

  1. andrei@HP:~/Hello/build$ make
  2. Scanning dependencies of target Hello_autogen
  3. [ 25%] Automatic MOC and UIC for target Hello
  4. [ 25%] Built target Hello_autogen
  5. Scanning dependencies of target Hello
  6. [ 50%] Building CXX object CMakeFiles/Hello.dir/Hello_autogen/mocs_compilation.cpp.o
  7. [ 75%] Building CXX object CMakeFiles/Hello.dir/main.cpp.o
  8. [100%] Linking CXX executable Hello
  9. [100%] Built target Hello

Проверяем нашу программу.

  1. andrei@HP:~/Hello/build$ ls
  2. CMakeCache.txt CMakeFiles cmake_install.cmake Hello Hello_autogen Makefile

И запускаем cqtdeployer минуя его программу без qmake.

  1. andrei@HP:~/Hello/build$ cqtdeployer -bin Hello
  2. Deploy ...
  3. flag targetDir not used. use default target dir : "/home/andrei/Hello/build/DistributionKit"
  4. target deploy started!!
  5. copy : "/home/andrei/Hello/build/Hello"
  6. extract lib : "/home/andrei/Hello/build/DistributionKit//bin//Hello"
  7. copy : "/home/andrei/Qt/5.14.1/gcc_64/lib/libQt5Core.so.5"
  8. copy : "/home/andrei/Qt/5.14.1/gcc_64/lib/libicuuc.so.56"
  9. copy : "/home/andrei/Qt/5.14.1/gcc_64/lib/libicui18n.so.56"
  10. copy : "/home/andrei/Qt/5.14.1/gcc_64/lib/libicudata.so.56"
  11. copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_ar.qm"
  12. copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_bg.qm"
  13. copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_ca.qm"
  14. copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_cs.qm"
  15. copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_da.qm"
  16. copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_de.qm"
  17. copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_en.qm"
  18. copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_es.qm"
  19. copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_fi.qm"
  20. copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_fr.qm"
  21. copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_gd.qm"
  22. copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_he.qm"
  23. copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_hu.qm"
  24. copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_it.qm"
  25. copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_ja.qm"
  26. copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_ko.qm"
  27. copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_lv.qm"
  28. copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_pl.qm"
  29. copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_ru.qm"
  30. copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_sk.qm"
  31. copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_uk.qm"
  32. copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_zh_TW.qm"
  33. try deploy msvc
  34. deploy done!

О чудо, теперь наше приложение полностью автономно.
Проверьте это.

  1. andrei@HP:~/Hello/build$ cd DistributionKit/
  2. andrei@HP:~/Hello/build/DistributionKit$ tree
  3. .
  4. ├── bin
  5.    ├── Hello
  6.    └── qt.conf
  7. ├── Hello.sh
  8. ├── lib
  9.    ├── libicudata.so.56
  10.    ├── libicui18n.so.56
  11.    ├── libicuuc.so.56
  12.    └── libQt5Core.so.5
  13. └── translations
  14. ├── qtbase_ar.qm
  15. ├── qtbase_bg.qm
  16. ├── qtbase_ca.qm
  17. ├── qtbase_cs.qm
  18. ├── qtbase_da.qm
  19. ├── qtbase_de.qm
  20. ├── qtbase_en.qm
  21. ├── qtbase_es.qm
  22. ├── qtbase_fi.qm
  23. ├── qtbase_fr.qm
  24. ├── qtbase_gd.qm
  25. ├── qtbase_he.qm
  26. ├── qtbase_hu.qm
  27. ├── qtbase_it.qm
  28. ├── qtbase_ja.qm
  29. ├── qtbase_ko.qm
  30. ├── qtbase_lv.qm
  31. ├── qtbase_pl.qm
  32. ├── qtbase_ru.qm
  33. ├── qtbase_sk.qm
  34. ├── qtbase_uk.qm
  35. └── qtbase_zh_TW.qm
  36.  
  37. 3 directories, 29 files
  38. andrei@HP:~/Hello/build/DistributionKit$

Корень программы:

image

Библиотеки необходимые для работы программы:

image

Как видно из примера, приложение полностью собрано.

Каркас установщика Qt

Второе новшество, о котором стоит знать, — это возможность формировать QIF-установщики из коробки. Все, что нужно для нашего примера, это добавить опцию qif в команду упаковки.

Пример использования.

  1. andrei@HP:~/Hello/build$ cqtdeployer -bin Hello qif

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

image

Этот установщик поддерживает минимальную интеграцию дистрибутивов Linux и Windows. А именно: создание ярлыков, и регистрация приложения в ОС.
Если вас по какой-то причине не устраивает внешний вид этого установщика, вы можете изменить его с помощью флага qifStyle. На момент версии 1.4 cqtdeployer поддерживает только 2 стиля (native и quasar).

Пример стиля квазара:

image

Вы также можете использовать свою собственную таблицу стилей qss. Для этого передайте путь к вашему qss или css файлу вместо имени стиля.
Например, рассмотрим следующую таблицу стилей qss.

Style.qss:

  1. QWidget
  2. {
  3. color: white;
  4. background-color: rgb(65, 65, 65);
  5. }
  6.  
  7. QPushButton
  8. {
  9. background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(150, 150, 150, 60%), stop:1 rgba(50, 50, 50, 60%));
  10. border-color: rgb(60, 60, 60);
  11. border-style: solid;
  12. border-width: 2px;
  13. border-radius: 9px;
  14. min-height: 20px;
  15. max-height: 20px;
  16. min-width: 60px;
  17. max-width: 60px;
  18. padding-left: 15px;
  19. padding-right: 15px;
  20. }
  21.  
  22. QPushButton:pressed, QPushButton:checked
  23. {
  24. background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(50, 50, 50, 60%), stop:1 rgba(150, 150, 150, 60%));
  25. }
  26.  

Давайте проверим, что мы получаем в этом случае.

  1. cqtdeployer -bin Hello qif -qifStyle ./../style.qss

image

Вот, собственно, и темная тема установщика.

Разбивка на пакеты

И, наверное, последнее важное обновление, о котором стоит знать, — это возможность разбивать большой мультибинарный проект на подпроекты.

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

Для начала усложним наш проект, добавив в него еще 2 исполняемых файла. Я не стал заморачиваться и просто сделал 2 копии своей утилиты Hello.

Для упрощения работы с пакетами необходимо инициализировать каталог.

  1. cqtdeployer init

Это еще одна новая функция, которая создает файл CQtDeployer.json, в который мы будем писать наши конфигурации, вместо того, чтобы передавать параметры утилите.

  1. {
  2. "binDir": ".",
  3. "clear": true,
  4. "libDir": "./",
  5. "recursiveDepth": 5
  6. }

Теперь сделаем 2 пакета из 3-х наших программ. Для этого укажите:

  1. {
  2. "binDir": ".",
  3. "clear": true,
  4. "libDir": "./",
  5. "recursiveDepth": 5,
  6. "targetPackage": [
  7. ["Dstro1", "Hello1"],
  8. ["Dstro2", "Hello2"],
  9. ["Dstro2", "Hello3"]
  10. ]
  11. }

Обратите внимание, что мне пришлось явно указать привязку Dstro2 к Hello2 Hello3. К сожалению, во время версии 1.4 cqtdeployer не мог анализировать целевые перечисления. Обратите внимание, что если я напишу вместо Hello1 Hello, то отбор будет производиться по всем совпадениям и будут выбраны все 3 программы.
Итак, давайте посмотрим, что произошло.

  1. cqtdeployer
  2.  
  3. .
  4. ├── Dstro1
  5.    ├── bin
  6.       ├── Hello1
  7.       └── qt.conf
  8.    ├── Hello1.sh
  9.    ├── lib
  10.       ├── libicudata.so.56
  11.       ├── libicui18n.so.56
  12.       ├── libicuuc.so.56
  13.       └── libQt5Core.so.5
  14.    └── translations
  15.    ├── qtbase_ar.qm
  16.    ├── qtbase_bg.qm
  17.    ├── qtbase_ca.qm
  18.    ├── qtbase_cs.qm
  19.    ├── qtbase_da.qm
  20.    ├── qtbase_de.qm
  21.    ├── qtbase_en.qm
  22.    ├── qtbase_es.qm
  23.    ├── qtbase_fi.qm
  24.    ├── qtbase_fr.qm
  25.    ├── qtbase_gd.qm
  26.    ├── qtbase_he.qm
  27.    ├── qtbase_hu.qm
  28.    ├── qtbase_it.qm
  29.    ├── qtbase_ja.qm
  30.    ├── qtbase_ko.qm
  31.    ├── qtbase_lv.qm
  32.    ├── qtbase_pl.qm
  33.    ├── qtbase_ru.qm
  34.    ├── qtbase_sk.qm
  35.    ├── qtbase_uk.qm
  36.    └── qtbase_zh_TW.qm
  37. └── Dstro2
  38. ├── bin
  39.    ├── Hello2
  40.    ├── Hello3
  41.    └── qt.conf
  42. ├── Hello2.sh
  43. ├── Hello3.sh
  44. ├── lib
  45.    ├── libicudata.so.56
  46.    ├── libicui18n.so.56
  47.    ├── libicuuc.so.56
  48.    └── libQt5Core.so.5
  49. └── translations
  50. ├── qtbase_ar.qm
  51. ├── qtbase_bg.qm
  52. ├── qtbase_ca.qm
  53. ├── qtbase_cs.qm
  54. ├── qtbase_da.qm
  55. ├── qtbase_de.qm
  56. ├── qtbase_en.qm
  57. ├── qtbase_es.qm
  58. ├── qtbase_fi.qm
  59. ├── qtbase_fr.qm
  60. ├── qtbase_gd.qm
  61. ├── qtbase_he.qm
  62. ├── qtbase_hu.qm
  63. ├── qtbase_it.qm
  64. ├── qtbase_ja.qm
  65. ├── qtbase_ko.qm
  66. ├── qtbase_lv.qm
  67. ├── qtbase_pl.qm
  68. ├── qtbase_ru.qm
  69. ├── qtbase_sk.qm
  70. ├── qtbase_uk.qm
  71. └── qtbase_zh_TW.qm
  72.  
  73. 8 directories, 60 files

Как видно из дерева результатов, у нас получилось 2 дистрибутива.
1. Dstro1 - содержит приложение Hello1
2. Dstro2 - содержит оставшиеся 2.

Теперь проверим, что будет, если все это запаковать установщиком. Добавьте для параметра qif значение true в CQtDeployer.json: qif: true, .

  1. {
  2. "binDir": ".",
  3. "clear": true,
  4. "qif": true,
  5. "libDir": "./",
  6. "recursiveDepth": 5,
  7. "targetPackage": [
  8. ["Dstro1", "Hello1"],
  9. ["Dstro2", "Hello2"],
  10. ["Dstro2", "Hello3"]
  11. ]

image

Как видно из скриншота, теперь у нас 2 пакета при установке.

Новые псевдонимы

И последнее небольшое, но приятное дополнение: теперь в cqtdeployer добавлены новые команды.

  • сqt — — это быстрый способ развернуть ваше приложение. Это упрощает вызов развертывания.

    • Пример:
      cqt myApp — это то же самое, что cqtdeployer -bin myApp .
  • cqtdeployer.cqt - то же, что и cqt, но для пакета snap.

  • В windows-версии теперь не нужно добавлять знак % для вызова утилиты.

  • В версии для windows теперь нет необходимости добавлять знак % для вызова утилиты.
    Теперь вызов выглядит как в Linux. (cqtdeployer)

GitHub репозиторийі

Мақала бойынша сұралады0сұрақтар(лар)

5

Ол саған ұнайды ма? Әлеуметтік желілерде бөлісіңіз!

o
  • Наурыз 25, 2020, 12:51 Т.Ж.

спасибо, за обзор!

Андрей Янкович
  • Наурыз 25, 2020, 1:29 Т.Ж.

Если будут вопросы, пишите. Найдем решение)

Ruslan Polupan
  • Наурыз 26, 2020, 5:47 Т.Қ.

Супер. Спасибо!

D
  • Наурыз 26, 2020, 6:50 Т.Қ.

Добрый день. У меня есть приложение с библиотеками собранными отдельно. Как мне сделать так, чтобы эти библиотеки помещались в установщик и при установке приложение были вместе с исполняемым файлом? И почему утилита при использовании -bin или -bindir создает ярылки для каких-то библиотек, но не для исполняемого файла? Я использую Windows.

Андрей Янкович
  • Наурыз 26, 2020, 7:27 Т.Қ.
  • (өңделген)
  1. Откройте cmd, перейдите в папку с вашими проектами, запустите cqtdeployer init.
  2. Должен появится файл CQtDeployer.json, откройте его.
  1. {
  2. "bin": [
  3. "./path/to/my/file.exe",
  4. ],
  5. "qmake": "C:/path/to/my/qmake.exe",
  6. "clear": true,
  7. "libDir": "./",
  8. "recursiveDepth": 5,
  9. "qif": true
  10. }

Если все ваши библиотеки требуются для работы ./path/to/my/file.exe т они автоматически попадут в инсталятор. если ваши библиотеки очень далеко запрятаны от расположения json файла то можете по больше выставить значение "recursiveDepth": 5,
путь "./path/to/my/file.exe", должен обязательно начинается с "." и быть относительным от json файла.

Обратите внимание на то что в Windows версии все еще нужно явно указывать путь к qmake которым был собран проект.
Исключение составляет тот факт что если qmake уже прописан у вас в окружении PATH, тогда cqtdeployer будет использовать значение из PATH.
затем сохраняете ваш файл и повторно запускаете cqtdeployer.

что касается ярлыков на библиотеки то звучит как ошибка. Собирите максимум информации о ваших дествиях и опишите ошибку на GitHub

Андрей Янкович
  • Наурыз 26, 2020, 8:29 Т.Қ.

можно еще так:

  1. cqtdeployer -bin "path/to/my/file.exe" -qmake "C:/path/to/my/qmake.exe" -libDir "./" -recursiveDepth 5 qif

это тоже самое, просто гораздо удобнее когда инициализация будет у вас записана в файл, и вам не придется постоянно водить эту длинную строку для развертывания.

D
  • Наурыз 26, 2020, 9:56 Т.Қ.

LibDir вообще не видит библиотеки. Пробовал разные попытки записи, исходя из вашего сообщения. Библиотеки лежат рядом с исполняемым файлом, json там же. Если использовать binDir вместо bin тогда библиотеки добавляются. А при установке создадутся ярлыки на все библиотеки, но не на исполняемый файл. Оно так и должно работать?

Андрей Янкович
  • Наурыз 26, 2020, 10:39 Т.Қ.
  • (өңделген)

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

Андрей Янкович
  • Наурыз 26, 2020, 10:42 Т.Қ.

@Den125 можно взгялнуть на ваш проект ?

D
  • Наурыз 26, 2020, 10:51 Т.Қ.

Мой исполняемый файл не зависит от библиотек. Библиотеки подключаются при необходимости в процессе работы программы.

Андрей Янкович
  • Наурыз 26, 2020, 11:13 Т.Қ.
  • (өңделген)

тогда это плагины )
для них есть отделный флаг extraPlugin

  1. {
  2. "bin": [
  3. "./path/to/my/file.exe",
  4. ],
  5. "qmake": "C:/path/to/my/qmake.exe",
  6. "extraPlugin": [
  7. "./plugin1.dll",
  8. "./plugin2.dll",
  9. ],
  10. "clear": true,
  11. "libDir": "./",
  12. "recursiveDepth": 5,
  13. "qif": true
  14. }
D
  • Наурыз 26, 2020, 11:34 Т.Қ.

Это сработало, но библиотеки при установке находятся в папке plugins. А можно их вынести к исполняемому файлу? Можно ли в установщик закинуть файл не библиотеку и не исполняемый, например *.jar?

Андрей Янкович
  • Наурыз 26, 2020, 11:37 Т.Қ.

тогда переместите ваши библиотеки из extraPlugin в bin

  1. {
  2. "bin": [
  3. "./path/to/my/file.exe",
  4. "./plugin1.dll",
  5. "./plugin2.dll",
  6. ],
  7. "qmake": "C:/path/to/my/qmake.exe",
  8. "clear": true,
  9. "libDir": "./",
  10. "recursiveDepth": 5,
  11. "qif": true
  12. }
Андрей Янкович
  • Наурыз 26, 2020, 11:37 Т.Қ.

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

Андрей Янкович
  • Наурыз 27, 2020, 12:47 Т.Қ.

Ошибка с ярлыками в Windows исправлена в версиии 1.4.0.4

Пікірлер

Тек рұқсаты бар пайдаланушылар ғана пікір қалдыра алады.
Кіріңіз немесе Тіркеліңіз