Evgenii Legotckoi
Evgenii Legotckoi30. Juli 2016 12:03

Qt WinAPI - Lektion 004. QtIFW - Automatisierung von WinDeployQt und Build-Installationsprogramme mit Qt Installer Framework

Ein guter Programmierer ist ein fauler Programmierer. Wenn es die Möglichkeit gibt, etwas zu automatisieren, dann müssen Sie es unbedingt tun. Beispielsweise können Sie windeployqt automatisch ausführen, indem Sie Online- und Offline-Installationsprogramme zusammenstellen, sowie das Anwendungs-Repository mit Qt Installer Framework und schwarzer Magie QMake .

Um dies auf die schönste Weise zu tun, ist es notwendig, dass das Projekt mit der Struktur Unterverzeichnisse organisiert ist, also aus mehreren Projekten besteht. Wir müssen nicht bei jedem Build des Projekts Installer erstellen. Daher wird das Installer-Projekt separat sein.

Aber lassen wir die windeployqt-Automatisierung im Hauptprojekt.

Projektstruktur

Wir haben also ein Projekt mit zwei Teilprojekten:

  1. Hello.pro - Anwendungsprojekt
  2. Installer.pro - Installationsprojekt

Das Hauptprojekt ist das häufigste „Hello world“, aber das größte Interesse gilt dem QMake-Skript, das für das windeployqt der Anwendung verantwortlich ist.

Das zweite Projekt hat eine minimale Struktur zum Erstellen von Offline- und Online-Installern sowie zum Erstellen eines Repositorys. Das QMake-Skript im Projektprofil enthält auch die notwendigen Informationen, um den Build der Installer zu automatisieren.


WinDeployQt-Automatisierung

HelloInstaller.pro

Diese Datei hat den traditionellen Inhalt für Projekt-Unterverzeichnisse.

TEMPLATE = subdirs

CONFIG += ordered

SUBDIRS += \
    Hello \
    Installer

Hallo.pro

Zusätzlich zur üblichen Angabe der Assemblyverzeichnisse der ausführbaren Datei sowie anderer Projektausgabedateien führt dieses QMake-Skript das Dienstprogramm windeployqt aus.

QT += core
QT -= gui

CONFIG += c++11

TARGET = Hello
CONFIG += console
CONFIG -= app_bundle

TEMPLATE = app

# Выбираем директорию сборки исполняемого файла
# в зависимости от режима сборки проекта
CONFIG(debug, debug|release) {
    DESTDIR = $$OUT_PWD/../../HelloDebug
} else {
    DESTDIR = $$OUT_PWD/../../HelloRelease
}
# разделяем по директориям все выходные файлы проекта
MOC_DIR = ../common/build/moc
RCC_DIR = ../common/build/rcc
UI_DIR = ../common/build/ui
unix:OBJECTS_DIR = ../common/build/o/unix
win32:OBJECTS_DIR = ../common/build/o/win32
macx:OBJECTS_DIR = ../common/build/o/mac

# в зависимости от режима сборки проекта
# запускаем win deploy приложения в целевой директории, то есть собираем все dll
CONFIG(debug, debug|release) {
    QMAKE_POST_LINK = $$(QTDIR)/bin/windeployqt $$OUT_PWD/../../HelloDebug
} else {
    QMAKE_POST_LINK = $$(QTDIR)/bin/windeployqt $$OUT_PWD/../../HelloRelease
}

SOURCES += main.cpp

Wenn mit der Angabe der Zusammenstellung des Ordners der ausführbaren Datei alles klar ist, lassen Sie uns herausfinden, was passiert, wenn windeployqt ausgeführt wird.

QMAKE_POST_LINK ist eine Anweisung, die angibt, was nach dem Erstellen des Projekts zu tun ist. Das heißt, was wir tun, nachdem die ausführbare Datei erstellt wurde.

$$(QTDIR) ist eine Variable, die den Pfad zum Qt-Build-Bundle enthält. In meinem Fall ist es D:\Qt\5.7\mingw53_32.

Um windeployqt auszuführen, ist es nicht erforderlich, die ausführbare Datei anzugeben, es reicht aus, den Ordner, in dem sich diese Datei befindet, als Argument anzugeben. Als Ergebnis wird nach Abschluss der Projekterstellung die für die Anwendung erforderliche DLL automatisch erstellt und neben der ausführbaren Datei platziert .

Gebäudeinstallateure und Repository

Die Zusammenstellung der Installer und des Online-Repositorys des Projekts erfolgt mit dem Qt Installer Framework, das Dienstprogramme sowohl zum Erstellen der Installer selbst als auch zum Vorbereiten des Anwendungs-Repositorys enthält.

Für die Assemblierung werden zwei Dienstprogramme aus diesem Framework verwendet:

  • binarycreator - Dienstprogramm zum Erstellen des Installationsprogramms;
  • repogen - Dienstprogramm zum Vorbereiten eines Online-Repositorys.

Bevor wir uns mit dem QMake-Skript befassen, wollen wir uns die Konfigurationsdateien und die Verzeichnisstruktur zum Erstellen von Installern ansehen.

Verzeichnisaufbau

Betrachten Sie die Projektstruktur:

  • config - enthält die Konfigurationsdatei des Installationsprogramms:
  • config.xml - diese Datei enthält Informationen über das Remote-Repository, die Version, den Projektnamen usw.
  • Pakete - die die Pakete enthalten, aus denen die Installationsprogramme erstellt werden, zum Beispiel:
  • ru.evileg.helloinstaller - Verzeichnis des ersten Pakets
  • meta - ein Verzeichnis, das Installationsskripts enthält, die bestimmte Funktionen beschreiben, z. B. das Schließen der aktiven Instanz der Anwendung, wenn die Anwendung aktualisiert wird, oder das Schreiben von Informationen in die Systemregistrierung.
  • package.xml - in der Mindestversion ist diese Datei erforderlich, die die Version und das Erstellungsdatum des Projekts beschreibt. Diese Informationen werden benötigt, um die Datei Updates.xml zu generieren, die in das Online-Repository gestellt wird.
  • Daten - In diesem Verzeichnis müssen die ausführbare Datei und alle erforderlichen DLLs, Ressourcendateien, Übersetzungsdateien usw. abgelegt werden. Das heißt, alles, was zum Erstellen einer funktionierenden Anwendung benötigt wird.
  • ru.evileg.ecolor - sowie beispielsweise das Verzeichnis des zweiten Pakets mit Inhalten, die ähnlich aufgebaut sind wie die vorherigen Optionen.

config.xml

Eine Datei, die Dienstinformationen über den Herausgeber, den Installationspfad der Anwendung, ihre Version und ihren Namen beschreibt. Es enthält auch Informationen über die Adresse des Remote-Repositorys. Diese Informationen sind für das Online-Installationsprogramm und das Offline-Installationsprogramm gleich. Schließlich müssen wir unter anderem auch die Anwendung aktualisieren, daher benötigen beide Versionen der Installer Informationen über das Remote-Repository.

<?xml version="1.0" encoding="UTF-8"?>
<Installer>
    <Name>Hello Installer</Name>
    <Version>1.0.0</Version>
    <Title>1.0.0 Installer</Title>
    <Publisher>EVILEG</Publisher>
    <StartMenuDir>HelloInstaller</StartMenuDir>
    <TargetDir>@RootDir@Program Files (x86)\EVILEG\HelloInstaller</TargetDir>
        <AllowSpaceInPath>true</AllowSpaceInPath>
    <RemoteRepositories>
        <Repository>
            <Url>http://www.evileg.ru/software/helloinstaller/</Url>
        </Repository>
    </RemoteRepositories>
</Installer>
  • Installer - generierter Installer
  • Name - Anwendungsname
  • Version - Anwendungsversion
  • Titel – Der Titel des Installationsfensters
  • Herausgeber - Herausgeber
  • StartMenuDir - gibt die Produktgruppe an, zu der die Anwendung im Windows-Startmenü gehört.
  • TargetDir - Anwendungsinstallationsordner; @RootDir@ - Stammordner. In diesem Fall C:\
  • AllowSpaceInPath - Leerzeichen im Verzeichnispfad zulassen
  • RemoteRepositories - Liste der Repositories
  • Repository - eines der Online-Repositorys, es können mehrere vorhanden sein oder sie können sogar ersetzt werden
  • URL - Repository-Adresse

Paket.xml

Hier werden bereits zusätzliche Informationen zum Verfahren zum Installieren der Anwendung im System angezeigt, dh zum Beispiel das Vorhandensein bestimmter Formulare, Fenster und Installationsskripts zum Eingeben von Informationen in die Registrierung. Außerdem wurden Informationen zum Veröffentlichungsdatum der Anwendung hinzugefügt, die auch in der Datei Updates.xml. abgelegt werden.

Diese Datei muss in jedem Paket enthalten sein. Das Installationsprogramm bietet möglicherweise die Möglichkeit, eine Reihe von Komponenten zu installieren, erinnern Sie sich an das Qt-Installationsprogramm, es gibt viele Punkte. Dementsprechend stellt jedes derartige Paket einen eigenen Artikel dar.

<?xml version="1.0" encoding="UTF-8"?>
<Package>
    <DisplayName>Hello Installer</DisplayName>
    <Description>The main component</Description>
    <Version>1.0.0</Version>
    <ReleaseDate>2016-07-30</ReleaseDate>
        <Default>true</Default>
    <Name>ru.evileg.helloinstaller</Name>
    <ForcedInstallation>true</ForcedInstallation>
    <RequiresAdminRights>true</RequiresAdminRights>
</Package>
  • DisplayName - Komponentenname. Erforderliches Tag.
  • Beschreibung - Beschreibung der Komponente. Erforderliches Tag.
  • Version - Version der Komponente. Erforderliches Tag.
  • ReleaseDate - Veröffentlichungsdatum. Erforderliches Tag.
  • Standard - Auswahl der Standardkomponente, dh die Komponente für die Installation ist ausgewählt oder nicht.
  • Name - Paketkennung in Form eines Domänennamens. Erforderliches Tag.
  • ForcedInstallation – gibt an, dass die Komponente installiert werden muss und der Benutzer sie nicht von der Installation ausschließen kann
  • RequiresAdminRights - gibt an, dass das Paket mit Administratorrechten installiert werden muss. Das Feld ist optional. Und das Interessanteste ist, dass der Installer während der Arbeit diese Administratorrechte verlieren kann. Das heißt, für einige Aktionen müssen Sie erneut Administratorrechte vom Benutzer anfordern.

Installer.pro

Hier ist eine Variante mit Zusammenstellung von Installern in separaten Ordnern für Release - und Debug -Versionen. Sowie das Vorbereiten des Repositorys für die Release -Version.

Verwenden Sie zum Erstellen des Offline-Installationsprogramms das Dienstprogramm binarycreator mit den folgenden Parametern:

  • --offline-only - wie der Name schon sagt, weist darauf hin, dass wir ein Offline-Installationsprogramm erstellen
  • -c - gibt den Pfad zur Konfigurationsdatei an
  • -p - gibt den Pfad zum Ordner mit Paketen an, während der Arbeit wird QtIFW herausfinden, wie Pakete im Installationsprogramm erstellt werden, wobei ihre Konfigurationsdateien und Skripte aus dem Metaordner berücksichtigt werden

Hinweis. Für die Online-Version des Installationsprogramms ist alles gleich, nur das Argument --offline-only wird durch --online-only ersetzt.**

Und um das Repository vorzubereiten, verwenden wir das Dienstprogramm repogen mit den folgenden Parametern:

  • -p - gibt einen Ordner mit Paketen an
  • -i - gibt Pakete an, die in das Installationsprogramm eingeschlossen werden sollen
  • -update - gibt an, dass Sie das Repository im folgenden Pfad aktualisieren müssen. Wenn sich in diesem Pfad kein Repository befindet, wird ein neues erstellt.
# Before run make project, need to put executable file and dlls into
# $$PWD/installer/packages/ru.evileg.helloinstaller/data

TEMPLATE = aux

# В зависимости от режима сборки, определяем, куда именно будут собираться инсталляторы
CONFIG(debug, debug|release) {
    INSTALLER_OFFLINE = $$OUT_PWD/../../InstallerDebug/Hello.offline
    INSTALLER_ONLINE = $$OUT_PWD/../../InstallerDebug/Hello.online
    DESTDIR_WIN = $$PWD/packages/ru.evileg.helloinstaller/data
    DESTDIR_WIN ~= s,/,\\,g
    PWD_WIN = $$OUT_PWD/../../HelloDebug
    PWD_WIN ~= s,/,\\,g

    copydata.commands = $(COPY_DIR) $$PWD_WIN $$DESTDIR_WIN
    first.depends = $(first) copydata
    export(first.depends)
    export(copydata.commands)
    QMAKE_EXTRA_TARGETS += first copydata
} else {
    # Задаём переменные, которые будут содержать пути с названиями инсталляторов
    INSTALLER_OFFLINE = $$OUT_PWD/../../InstallerRelease/Hello.offline
    INSTALLER_ONLINE = $$OUT_PWD/../../InstallerRelease/Hello.online

    # Задаём переменную, которая должна содержать путь к папке с данными
    DESTDIR_WIN = $$PWD/packages/ru.evileg.helloinstaller/data
    DESTDIR_WIN ~= s,/,\\,g
    # Задаём путь откуда всё приложение с DLL-ками нужно будет скопировать
    PWD_WIN = $$OUT_PWD/../../HelloRelease
    PWD_WIN ~= s,/,\\,g

    # Прежде, чем выполнять сборку инсталляторов, необходимо скопировать файлы
    # из выходной папки проекта вместе со всеми DLL в папку data, которая относится
    # к собираемому пакету
    copydata.commands = $(COPY_DIR) $$PWD_WIN $$DESTDIR_WIN
    first.depends = $(first) copydata
    export(first.depends)
    export(copydata.commands)
    # задаём кастомную цель сборки, при которой сначала выполним компирование файлов
    # а потом уже и остальное, что следует по скрипту QMake
    QMAKE_EXTRA_TARGETS += first copydata
}

# Создаём цель по сборке Оффлайн Инсталлятора
INPUT = $$PWD/config/config.xml $$PWD/packages
offlineInstaller.depends = copydata
offlineInstaller.input = INPUT
offlineInstaller.output = $$INSTALLER_OFFLINE
offlineInstaller.commands = $$(QTDIR)/../../QtIFW2.0.3/bin/binarycreator --offline-only -c $$PWD/config/config.xml -p $$PWD/packages ${QMAKE_FILE_OUT}
offlineInstaller.CONFIG += target_predeps no_link combine

QMAKE_EXTRA_COMPILERS += offlineInstaller

# Создаём цель по сборке Онлайн Инсталлятора
INPUT = $$PWD/config/config.xml $$PWD/packages
onlineInstaller.depends = copydata
onlineInstaller.input = INPUT
onlineInstaller.output = $$INSTALLER_ONLINE
onlineInstaller.commands = $$(QTDIR)/../../QtIFW2.0.3/bin/binarycreator --online-only -c $$PWD/config/config.xml -p $$PWD/packages ${QMAKE_FILE_OUT}
onlineInstaller.CONFIG += target_predeps no_link combine

QMAKE_EXTRA_COMPILERS += onlineInstaller

# репозиторий будем собирать только в случае режима release
CONFIG(release, debug|release) {
    # Сборку репозитория производим после того, как были собраны Инсталляторы
    # Для этого воспользуемся QMAKE_POST_LINK вместо QMAKE_EXTRA_COMPILERS
    # Поскольку он хорошо для этого подходит
    QMAKE_POST_LINK += $$(QTDIR)/../../QtIFW2.0.3/bin/repogen -p $$PWD/packages -i ru.evileg.helloinstaller --update $$OUT_PWD/../../repository
}

DISTFILES += \
    packages/ru.evileg.helloinstaller/meta/package.xml \
    config/config.xml


Laden Sie das Archiv mit dem Projekt herunter Qt Installer Framework example

Videoanleitung

Рекомендуємо хостинг TIMEWEB
Рекомендуємо хостинг TIMEWEB
Stabiles Hosting des sozialen Netzwerks EVILEG. Wir empfehlen VDS-Hosting für Django-Projekte.

Magst du es? In sozialen Netzwerken teilen!

grig_p
  • 29. März 2017 09:34

Очень полезная статья. Спасибо большое! Но у меня осталась пара вопросов. Я новичок в QT и не все понятно. Поэтому вопросы будут дилетантские. У Вас уже был создан проект с поддиректориями (это правильно?) включающий в себя проект программы и проект инсталлятора. Для проекта программы, как я понимаю, может при создании быть выбран любой шаблон. А вот, чтобы создать проект инсталлятора, какой должен шаблон необходимо выбрать? Второй вопрос. Вы рассказали про структуру файлов в проекте. Это все понятно. А вот какова должна быть структура файлов на диске. Есть корневой проект HelloInstaller, есть папка HelloInstaller. Есть два подпроекта: Hello и Installer. Так вот вопрос, папки этих проектов должны быть расположены внутри HelloInstaller, рядом с ним, или в любом другом месте? Подозреваю, что можно по разному. Но, на Ваш взгляд, как правильно? Заранее спасибо за ответ!

Evgenii Legotckoi
  • 30. März 2017 00:19

Да. За основу был взят проект с поддиректориями.

Я не нашёл подходящего шаблона проекта для инсталлятора, поэтому взял пустой проект qmake и уже переписал его для инсталлятора.

Вот как выглядит структура проекта, так и располагаются файлы и папки на диске. То есть есть общая папка HelloInstaller, а в ней уже папки проектов Hello и Installer, а также HelloInstaller.pro. Да, можно, конечно, по-разному. Но не вижу смысла раскидывать подпроекты повсюду, если есть возможность держать всё в одной папке. Будете использовать git-репозиторий, то заметите, что это удобно. Конечно, третьесторонние библиотеки могут располагаться и в другом месте, особенно если они используются в другом проекте, никак не связанном с текущим проектом. Но по-максимуму всё располагайте в одном месте.

grig_p
  • 30. März 2017 01:20

Огромное спасибо за быстрый ответ.

Evgenii Legotckoi
  • 30. März 2017 06:25

Пожалуйста. Будут ещё вопросы, спрашивайте. Только задавайте их на форуме , чтобы были отдельные ветки обсуждений.

r
  • 6. Dezember 2019 05:48

Певевести бы это на cmake

r
  • 6. Dezember 2019 11:37

А что сделать чтоб qt не тащило весь свой гигабайт в инсталлер?

Evgenii Legotckoi
  • 6. Dezember 2019 12:40

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

А что касается гигабайта Qt, то обычно QtIFW тянет только необходимое, что в зависимостях и может затащить что-то из QML, если QML не используется, то я бы порылся в документации, скорее всего можно вырубить это. Просто сами все библиотеки, такие как Qt Core имеют вес. Тут никуда не денешься. Но как вариант есть ещё две возможности:

  • Попытаться собрать программу статически, но нужно учитывать особенности лицензии тогда
  • Либо посмотреть в сторону Qt lite , завезли с версией 5,8, но точно не помню - является ли это коммерческой лицензией, а там сами знаете какая цена за Qt.
r
  • 6. Dezember 2019 12:46

С cmake разобрался. Всетаки писать на нем сильно проще. С размером dll тоже разобрался. windeployqt надо давать флаг --release (тогда библиотеки в 20 раз меньше)

Evgenii Legotckoi
  • 6. Dezember 2019 12:47
  • (bearbeitet)

я подумал насчёт debug/release, но мне показалось - это сильно очевидным ))))

Насчёт cmake согласен - он лучше

Юрий
  • 21. Dezember 2019 11:21

Если возможность автоматически ставить версию сборки?

Evgenii Legotckoi
  • 9. Januar 2020 16:15

Нет, не сталкивался с такой возможностью. Скорее всего только с помощью скриптов это можно решить.

k
  • 9. März 2020 16:22
  • (bearbeitet)

Здравствуйте. У меня вопрос: как добавить файл ресурсов (.rc) к установщику Hello.offline (в этом файле ресурсов - команда включения файла манифеста и информация, которая должна выводиться при нажатии на свойства файла -> подробно) ? У binarycreator есть флаг -r, после которого можно указать ресурсы. Но файлы таким образом просто включаются в исходник, но не обрабатываются! Пробовал также через утилиту windows sdk mt.exe, но она режит размер установщика. Если нет возможности подключить файл ресурсов, то хотя бы нужно, чтобы установщик мог запускаться только под админом.

Evgenii Legotckoi
  • 10. März 2020 09:09

Насколько помню, то для получения прав администратора нужно добавить в package.xml следующее

<RequiresAdminRights>true</RequiresAdminRights>

Помимо прочего, при написании скриптов установщика можно запрашивать права через функцию gainAdminRights() , но подробного кейса по применению я уже не помню.

S
  • 18. Januar 2023 08:03

Hello Evgenij,
regarding the online installer, I've tried many times to use web host for the created repo after repogen step.
I tried using github but I found people talking it is not possible to to be read by qt ifw and tried google cloud source and code berg but both couldn't be read by the installer.
Do you have a recomendation for a certain web host for the repo? I also want it to be private but I don't want to put a password for the account in the config.xml, so is there another way to give authorization for installer to reach the repo without writing password in plain text?
I know this post is very old but I couldn't find any recent reference online, thanks in advanced.

Kommentare

Nur autorisierte Benutzer können Kommentare posten.
Bitte Anmelden oder Registrieren
Letzte Kommentare
ИМ
Игорь Максимов5. Oktober 2024 07:51
Django – Lektion 064. So schreiben Sie eine Python-Markdown-Erweiterung Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
d
dblas55. Juli 2024 11:02
QML - Lektion 016. SQLite-Datenbank und das Arbeiten damit in QML Qt Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
k
kmssr8. Februar 2024 18:43
Qt Linux - Lektion 001. Autorun Qt-Anwendung unter Linux как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
Qt WinAPI - Lektion 007. Arbeiten mit ICMP-Ping in Qt Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
EVA
EVA25. Dezember 2023 10:30
Boost - statisches Verknüpfen im CMake-Projekt unter Windows Ошибка LNK1104 часто возникает, когда компоновщик не может найти или открыть файл библиотеки. В вашем случае, это файл libboost_locale-vc142-mt-gd-x64-1_74.lib из библиотеки Boost для C+…
Jetzt im Forum diskutieren
J
JacobFib17. Oktober 2024 03:27
добавить qlineseries в функции Пользователь может получить любые разъяснения по интересующим вопросам, касающимся обработки его персональных данных, обратившись к Оператору с помощью электронной почты https://topdecorpro.ru…
JW
Jhon Wick1. Oktober 2024 15:52
Indian Food Restaurant In Columbus OH| Layla’s Kitchen Indian Restaurant If you're looking for a truly authentic https://www.laylaskitchenrestaurantohio.com/ , Layla’s Kitchen Indian Restaurant is your go-to destination. Located at 6152 Cleveland Ave, Colu…
КГ
Кирилл Гусарев27. September 2024 09:09
Не запускается программа на Qt: точка входа в процедуру не найдена в библиотеке DLL Написал программу на C++ Qt в Qt Creator, сбилдил Release с помощью MinGW 64-bit, бинарнику напихал dll-ки с помощью windeployqt.exe. При попытке запуска моей сбилженной программы выдаёт три оши…
F
Fynjy22. Juli 2024 04:15
при создании qml проекта Kits есть но недоступны для выбора Поставил Qt Creator 11.0.2. Qt 6.4.3 При создании проекта Qml не могу выбрать Kits, они все недоступны, хотя настроены и при создании обычного Qt Widget приложения их можно выбрать. В чем может …

Folgen Sie uns in sozialen Netzwerken