Спустя почти полгода вышло крупное обновление утилиты развертывания 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
Внимание
В снап-версии обязательно дайте программе доступ на чтение других процессов. Так как это необходимо для создания установщика и корректного поиска qt.
Подробный разбор самых интересных изменений.
Первое, на что следует обратить внимание, это то, что CQtDeployer научился работать с RPATH (только для Linux) и PATH. Это означает, что если ваше приложение собрано с поддержкой RPATH (а RPATH в qt включен по умолчанию) или ваш qmake прописан в PATH, то вам не нужно указывать путь к qmake. CQtDeployer сам найдет qmake.
Проверим на практике.
Я создал простое консольное приложение с помощью Qt.
- #include <QString>
- #include <QDebug>
- int main(int, char *[])
- {
- QString str = "hello CQtDeployer 1.4";
- qInfo() << str;
- return 0;
- }
Я буду использовать систему сборки cmake, так как она более актуальна, чем qmake.
- andrei@HP:~/Hello$ tree
- .
- ├── CMakeLists.txt
- ├── CMakeLists.txt.user
- └── main.cpp
- 0 directories, 3 files
Создайте папку для сборки.
- andrei@HP:~/Hello$ mkdir build
Запустите cmake в созданной папке.
- andrei@HP:~/Hello/build$ cmake .. -DCMAKE_PREFIX_PATH=~/Qt/5.14.1/gcc_64
- -- Configuring done
- -- Generating done
- -- Build files have been written to: /home/andrei/Hello/build
создание проекта
- andrei@HP:~/Hello/build$ make
- Scanning dependencies of target Hello_autogen
- [ 25%] Automatic MOC and UIC for target Hello
- [ 25%] Built target Hello_autogen
- Scanning dependencies of target Hello
- [ 50%] Building CXX object CMakeFiles/Hello.dir/Hello_autogen/mocs_compilation.cpp.o
- [ 75%] Building CXX object CMakeFiles/Hello.dir/main.cpp.o
- [100%] Linking CXX executable Hello
- [100%] Built target Hello
Проверяем нашу программу.
- andrei@HP:~/Hello/build$ ls
- CMakeCache.txt CMakeFiles cmake_install.cmake Hello Hello_autogen Makefile
И запускаем cqtdeployer минуя его программу без qmake.
- andrei@HP:~/Hello/build$ cqtdeployer -bin Hello
- Deploy ...
- flag targetDir not used. use default target dir : "/home/andrei/Hello/build/DistributionKit"
- target deploy started!!
- copy : "/home/andrei/Hello/build/Hello"
- extract lib : "/home/andrei/Hello/build/DistributionKit//bin//Hello"
- copy : "/home/andrei/Qt/5.14.1/gcc_64/lib/libQt5Core.so.5"
- copy : "/home/andrei/Qt/5.14.1/gcc_64/lib/libicuuc.so.56"
- copy : "/home/andrei/Qt/5.14.1/gcc_64/lib/libicui18n.so.56"
- copy : "/home/andrei/Qt/5.14.1/gcc_64/lib/libicudata.so.56"
- copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_ar.qm"
- copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_bg.qm"
- copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_ca.qm"
- copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_cs.qm"
- copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_da.qm"
- copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_de.qm"
- copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_en.qm"
- copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_es.qm"
- copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_fi.qm"
- copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_fr.qm"
- copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_gd.qm"
- copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_he.qm"
- copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_hu.qm"
- copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_it.qm"
- copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_ja.qm"
- copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_ko.qm"
- copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_lv.qm"
- copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_pl.qm"
- copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_ru.qm"
- copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_sk.qm"
- copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_uk.qm"
- copy : "/home/andrei/Qt/5.14.1/gcc_64/translations/qtbase_zh_TW.qm"
- try deploy msvc
- deploy done!
О чудо, теперь наше приложение полностью автономно.
Проверьте это.
- andrei@HP:~/Hello/build$ cd DistributionKit/
- andrei@HP:~/Hello/build/DistributionKit$ tree
- .
- ├── bin
- │ ├── Hello
- │ └── qt.conf
- ├── Hello.sh
- ├── lib
- │ ├── libicudata.so.56
- │ ├── libicui18n.so.56
- │ ├── libicuuc.so.56
- │ └── libQt5Core.so.5
- └── translations
- ├── qtbase_ar.qm
- ├── qtbase_bg.qm
- ├── qtbase_ca.qm
- ├── qtbase_cs.qm
- ├── qtbase_da.qm
- ├── qtbase_de.qm
- ├── qtbase_en.qm
- ├── qtbase_es.qm
- ├── qtbase_fi.qm
- ├── qtbase_fr.qm
- ├── qtbase_gd.qm
- ├── qtbase_he.qm
- ├── qtbase_hu.qm
- ├── qtbase_it.qm
- ├── qtbase_ja.qm
- ├── qtbase_ko.qm
- ├── qtbase_lv.qm
- ├── qtbase_pl.qm
- ├── qtbase_ru.qm
- ├── qtbase_sk.qm
- ├── qtbase_uk.qm
- └── qtbase_zh_TW.qm
- 3 directories, 29 files
- andrei@HP:~/Hello/build/DistributionKit$
Корень программы:
Библиотеки необходимые для работы программы:
Как видно из примера, приложение полностью собрано.
Каркас установщика Qt
Второе новшество, о котором стоит знать, — это возможность формировать QIF-установщики из коробки. Все, что нужно для нашего примера, это добавить опцию qif в команду упаковки.
Пример использования.
- andrei@HP:~/Hello/build$ cqtdeployer -bin Hello qif
Всего одна простая команда и программа приобретает презентабельный вид.
Этот установщик поддерживает минимальную интеграцию дистрибутивов Linux и Windows. А именно: создание ярлыков, и регистрация приложения в ОС.
Если вас по какой-то причине не устраивает внешний вид этого установщика, вы можете изменить его с помощью флага qifStyle. На момент версии 1.4 cqtdeployer поддерживает только 2 стиля (native и quasar).
Пример стиля квазара:
Вы также можете использовать свою собственную таблицу стилей qss. Для этого передайте путь к вашему qss или css файлу вместо имени стиля.
Например, рассмотрим следующую таблицу стилей qss.
Style.qss:
- QWidget
- {
- color: white;
- background-color: rgb(65, 65, 65);
- }
- QPushButton
- {
- background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(150, 150, 150, 60%), stop:1 rgba(50, 50, 50, 60%));
- border-color: rgb(60, 60, 60);
- border-style: solid;
- border-width: 2px;
- border-radius: 9px;
- min-height: 20px;
- max-height: 20px;
- min-width: 60px;
- max-width: 60px;
- padding-left: 15px;
- padding-right: 15px;
- }
- QPushButton:pressed, QPushButton:checked
- {
- background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(50, 50, 50, 60%), stop:1 rgba(150, 150, 150, 60%));
- }
Давайте проверим, что мы получаем в этом случае.
- cqtdeployer -bin Hello qif -qifStyle ./../style.qss
Вот, собственно, и темная тема установщика.
Разбивка на пакеты
И, наверное, последнее важное обновление, о котором стоит знать, — это возможность разбивать большой мультибинарный проект на подпроекты.
Эта функция самая сложная из всех перечисленных, так как для ее использования требуется много текста. Поэтому я рекомендую использовать файл конфигурации.
Для начала усложним наш проект, добавив в него еще 2 исполняемых файла. Я не стал заморачиваться и просто сделал 2 копии своей утилиты Hello.
Для упрощения работы с пакетами необходимо инициализировать каталог.
- cqtdeployer init
Это еще одна новая функция, которая создает файл CQtDeployer.json, в который мы будем писать наши конфигурации, вместо того, чтобы передавать параметры утилите.
- {
- "binDir": ".",
- "clear": true,
- "libDir": "./",
- "recursiveDepth": 5
- }
Теперь сделаем 2 пакета из 3-х наших программ. Для этого укажите:
- {
- "binDir": ".",
- "clear": true,
- "libDir": "./",
- "recursiveDepth": 5,
- "targetPackage": [
- ["Dstro1", "Hello1"],
- ["Dstro2", "Hello2"],
- ["Dstro2", "Hello3"]
- ]
- }
Обратите внимание, что мне пришлось явно указать привязку Dstro2 к Hello2 Hello3. К сожалению, во время версии 1.4 cqtdeployer не мог анализировать целевые перечисления. Обратите внимание, что если я напишу вместо Hello1 Hello, то отбор будет производиться по всем совпадениям и будут выбраны все 3 программы.
Итак, давайте посмотрим, что произошло.
- cqtdeployer
- .
- ├── Dstro1
- │ ├── bin
- │ │ ├── Hello1
- │ │ └── qt.conf
- │ ├── Hello1.sh
- │ ├── lib
- │ │ ├── libicudata.so.56
- │ │ ├── libicui18n.so.56
- │ │ ├── libicuuc.so.56
- │ │ └── libQt5Core.so.5
- │ └── translations
- │ ├── qtbase_ar.qm
- │ ├── qtbase_bg.qm
- │ ├── qtbase_ca.qm
- │ ├── qtbase_cs.qm
- │ ├── qtbase_da.qm
- │ ├── qtbase_de.qm
- │ ├── qtbase_en.qm
- │ ├── qtbase_es.qm
- │ ├── qtbase_fi.qm
- │ ├── qtbase_fr.qm
- │ ├── qtbase_gd.qm
- │ ├── qtbase_he.qm
- │ ├── qtbase_hu.qm
- │ ├── qtbase_it.qm
- │ ├── qtbase_ja.qm
- │ ├── qtbase_ko.qm
- │ ├── qtbase_lv.qm
- │ ├── qtbase_pl.qm
- │ ├── qtbase_ru.qm
- │ ├── qtbase_sk.qm
- │ ├── qtbase_uk.qm
- │ └── qtbase_zh_TW.qm
- └── Dstro2
- ├── bin
- │ ├── Hello2
- │ ├── Hello3
- │ └── qt.conf
- ├── Hello2.sh
- ├── Hello3.sh
- ├── lib
- │ ├── libicudata.so.56
- │ ├── libicui18n.so.56
- │ ├── libicuuc.so.56
- │ └── libQt5Core.so.5
- └── translations
- ├── qtbase_ar.qm
- ├── qtbase_bg.qm
- ├── qtbase_ca.qm
- ├── qtbase_cs.qm
- ├── qtbase_da.qm
- ├── qtbase_de.qm
- ├── qtbase_en.qm
- ├── qtbase_es.qm
- ├── qtbase_fi.qm
- ├── qtbase_fr.qm
- ├── qtbase_gd.qm
- ├── qtbase_he.qm
- ├── qtbase_hu.qm
- ├── qtbase_it.qm
- ├── qtbase_ja.qm
- ├── qtbase_ko.qm
- ├── qtbase_lv.qm
- ├── qtbase_pl.qm
- ├── qtbase_ru.qm
- ├── qtbase_sk.qm
- ├── qtbase_uk.qm
- └── qtbase_zh_TW.qm
- 8 directories, 60 files
Как видно из дерева результатов, у нас получилось 2 дистрибутива.
1. Dstro1 - содержит приложение Hello1
2. Dstro2 - содержит оставшиеся 2.
Теперь проверим, что будет, если все это запаковать установщиком. Добавьте для параметра qif значение true в CQtDeployer.json: qif: true, .
- {
- "binDir": ".",
- "clear": true,
- "qif": true,
- "libDir": "./",
- "recursiveDepth": 5,
- "targetPackage": [
- ["Dstro1", "Hello1"],
- ["Dstro2", "Hello2"],
- ["Dstro2", "Hello3"]
- ]
Как видно из скриншота, теперь у нас 2 пакета при установке.
Новые псевдонимы
И последнее небольшое, но приятное дополнение: теперь в cqtdeployer добавлены новые команды.
сqt — — это быстрый способ развернуть ваше приложение. Это упрощает вызов развертывания.
-
Пример:
cqt myApp — это то же самое, что cqtdeployer -bin myApp .
-
Пример:
cqtdeployer.cqt - то же, что и cqt, но для пакета snap.
В windows-версии теперь не нужно добавлять знак % для вызова утилиты.
В версии для windows теперь нет необходимости добавлять знак % для вызова утилиты.
Теперь вызов выглядит как в Linux. (cqtdeployer)
спасибо, за обзор!
Если будут вопросы, пишите. Найдем решение)
Супер. Спасибо!
Добрый день. У меня есть приложение с библиотеками собранными отдельно. Как мне сделать так, чтобы эти библиотеки помещались в установщик и при установке приложение были вместе с исполняемым файлом? И почему утилита при использовании -bin или -bindir создает ярылки для каких-то библиотек, но не для исполняемого файла? Я использую Windows.
Если все ваши библиотеки требуются для работы ./path/to/my/file.exe т они автоматически попадут в инсталятор. если ваши библиотеки очень далеко запрятаны от расположения json файла то можете по больше выставить значение "recursiveDepth": 5,
путь "./path/to/my/file.exe", должен обязательно начинается с "." и быть относительным от json файла.
Обратите внимание на то что в Windows версии все еще нужно явно указывать путь к qmake которым был собран проект.
Исключение составляет тот факт что если qmake уже прописан у вас в окружении PATH, тогда cqtdeployer будет использовать значение из PATH.
затем сохраняете ваш файл и повторно запускаете cqtdeployer.
что касается ярлыков на библиотеки то звучит как ошибка. Собирите максимум информации о ваших дествиях и опишите ошибку на GitHub
можно еще так:
это тоже самое, просто гораздо удобнее когда инициализация будет у вас записана в файл, и вам не придется постоянно водить эту длинную строку для развертывания.
LibDir вообще не видит библиотеки. Пробовал разные попытки записи, исходя из вашего сообщения. Библиотеки лежат рядом с исполняемым файлом, json там же. Если использовать binDir вместо bin тогда библиотеки добавляются. А при установке создадутся ярлыки на все библиотеки, но не на исполняемый файл. Оно так и должно работать?
нет, так не должно быть, вы уверены что ваш исполняемый файл зависит от ваших библиотек ? или он подключает их как плагины?
а с ярлыками это точно ошибка, уже завел задачу на это .
@Den125 можно взгялнуть на ваш проект ?
Мой исполняемый файл не зависит от библиотек. Библиотеки подключаются при необходимости в процессе работы программы.
тогда это плагины )
для них есть отделный флаг extraPlugin
Это сработало, но библиотеки при установке находятся в папке plugins. А можно их вынести к исполняемому файлу? Можно ли в установщик закинуть файл не библиотеку и не исполняемый, например *.jar?
тогда переместите ваши библиотеки из extraPlugin в bin
но появятся ярлыки, сейчас поправим
Ошибка с ярлыками в Windows исправлена в версиии 1.4.0.4