Как сделать релиз программы qt

Qt сегодня стал крайне популярным SDK для разработки кросс-платформенных приложений. И это легко понять. Обеспечена поддержка всех основных операционных систем: *nix, Windows и MacOS, а мощные возможности библиотек позволяют решать даже сложные задачи минимальным количеством кода. Кроме того, организация проекта на базе pro-файла весьма удобна, поэтому я применяю ее даже для тех проектов на C/C++, которые напрямую не используют возможности Qt’а. О таком способе организации проектов мы и поговорим.

Дерево проекта

Начнем сразу с общей структуры всего проекта с последовательным разбором его элементов:

. ├── bin │ ├── debug │ └── release ├── build │ ├── debug │ └── release ├── import ├── include ├── lib.linux ├── lib.win32 ├── src │ ├── include │ ├── MyApp │ └── MyLib └── tests └── MyLibTest

На верхнем уровне у нас расположено 8 каталогов. Разберем каждый из них в отдельности.

Каталог с бинарниками — bin/

Сюда будут складываться все наши исполняемые файлы. Для режимов сборки debug/ и release/ предусмотрены собственные подкаталоги, чтобы упростить переключение между отладочной и чистовой версиями.

Qt 6 — Установка Qt Creator на Windows 10 — Первый проект

Каталог сборки — build/

Чтобы не смешивать вспомогательные obj , moc , rcc и ui файлы с исходниками или готовыми бинарниками отведен отдельный каталог. По аналогии с bin/ он разбит на подкаталоги debug/ и release/ для соответствующих режимов сборки.

Каталог с заголовочными файлами сторонних библиотек — import/

Сейчас довольно сложно написать более или менее серьезное приложение, в котором не задействованы никакие сторонние библиотеки. Конечно, всегда есть вариант разместить эти зависимости в системных папках и настроить к ним пути, но это решение имеет множество недостатков. Лучше всегда держать все зависимости проекта в едином каталоге, который будет помещен под управление системы контроля версий, однако это уже тема отдельной заметки. Организация этого подкаталога может быть достаточно произвольной, но я предпочитаю для каждой отдельной библиотеки выделить свой подкаталог с h -файлами, чтобы избежать возможного конфликта имен.

Каталог с внешними заголовочными файлами нашего проекта — include/

Сюда мы будем помещать все наши h -файлы, которые соответствуют открытым частям интерфейса библиотек проекта. Вообще, этот каталог можно было бы назвать не include/ , а export/ , но это уже дело вкуса. Он вполне может оказаться пустым, если вы пишите небольшой одноразовый проект, код которого потом не будет повторно использоваться. Но если вы решите передать кому-то ваши наработки, то при наличии такого каталога для этого будет достаточно скопировать его вместе с содержимым lib.*/ , о котором мы поговорим в следующем подразделе.

Каталог с библиотеками — lib.(linux|win32)/

Чтобы не плодить глубокую вложенную иерархию подкаталогов с ветвлением по версиям операционных систем, мы просто создаем необходимые каталоги верхнего уровня с нужным суффиксом linux или win32 . Я не занимаюсь разработкой приложений для MacOS, но думаю, что вы без труда добавите нужный суффикс, если это понадобится. Сюда мы будем помещать как сторонние библиотеки с разбиением на подкаталоги по аналогии с заголовочными файлами в import/ , так и наши собственные библиотеки, но уже непосредственно в сам каталог lib.*/ .

Как запустить .exe вне QT Creator (DLL Collector, windeployqt)

Кроме того, заметим, что для win32-приложений, собираемых с помощью компилятора msvc из Visual Studio, динамические библиотеки разделяются на *.lib и *.dll файлы. Первые используются во время линковки компоновщиком, а вторые непосредственно во время работы приложения и должны находиться в одном каталоге с использующим их исполняемым файлом.

Возникает вопрос о том, куда поместить эти файлы для используемых сторонних библиотек. Однозначно *.lib -файлы должны лежать по путям, параллельным *.so -шникам для линукс приложений. Но куда деть *.dll -ки? Возможно несколько вариантов. Один из них заключается в том, чтобы поместить их рядом с *.lib -файлами.

Но тогда их придется вручную копировать в bin/ . Если же поместить их сразу в bin/ , то они будут засорять сборку под другими операционными системами или с компилятором gcc, поэтому я бы не стал рекомендовать этот способ. Отдельный каталог для этого заводить тоже смысла нет, поэтому с учетом всех плюсов и минусов я сам храню *.dll -файлы рядом с *.lib -ами.

Каталог с исходниками — src/

В нем для каждого модуля заводится отдельный подкаталог с его именем, в котором будут лежать cpp -файлы и закрытые h -файлы, которые нужны только внутри этого модуля. Не забудьте про каталог include/ верхнего уровня, в который идет на экспорт часть внешних заголовочных файлов нашего приложения. Но что делать с разделяемыми заголовочными файлами, которые нужны в нескольких наших модулях, но не имеющих такого большого значения, чтобы можно было их экспортировать? Для этого предназначен внутренний каталог src/include/ . В него мы можем поместить наборы внутренних констант, объявлений классов и функций, а потом совместно использовать их в наших модулях, не нарушая инкапсуляцию.

Читайте также:
Какой программой открыть ppt

Каталог с тестами — tests/

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

Создаем файлы проекта

А теперь посмотрим на файлы, определяющие структуру проекта для утилиты qmake , на основе которых будет создан набор Makefile ‘ов. Как говорилось во введении, утилита qmake позволяет управлять проектами для любых C/C++ приложений, поэтому если вы пишите программу на C++, но по какой-то причине для разработки графического интерфейса применяете модули GTK+ или Win32 API, то вас не должно это останавливать от применения приведенного ниже материала.

MyProject.pro

Главный pro -файл нашего проекта. В Visual Studio этот уровень называется Solution.

TEMPLATE = subdirs SUBDIRS += src/MyApp src/MyLib

Для него используется Qt-шаблон subdirs , что означает, что наш проект будет состоять из набора модулей-подпроектов. Кто-то может решить, что нет смысла заниматься компоновкой такой многоуровневой структуры и гораздо удобнее сделать приложение на базе единственного app -проекта. Возможно, что в некоторых случаях это так, но шаблон subdirs не запрещает использование одного модуля, да и много времени вы на этом не сэкономите. Зато в дальнейшем очень часто оказывается, что одного модуля было недостаточно и все равно приходится что-то менять.

В приведенном примере у нас всего два модуля: MyApp — исполняемое приложение и MyLib — вспомогательная библиотека. Но прежде чем спуститься на уровень ниже и посмотреть на то, как устроены MyApp и MyLib , рассмотрим несколько вспомогательных pri -файлов.

common.pri

Общий для всех модулей файл с определениями путей и некоторых констант, задействованных при сборке:

PROJECT_ROOT_PATH = $$/ win32: OS_SUFFIX = win32 linux-g++: OS_SUFFIX = linux CONFIG(debug, debug|release) < BUILD_FLAG = debug LIB_SUFFIX = d >else < BUILD_FLAG = release >LIBS_PATH = $$/lib.$$/ INC_PATH = $$/include/ IMPORT_PATH = $$/import/ BIN_PATH = $$/bin/$$/ BUILD_PATH = $$/build/$$/$$/ RCC_DIR = $$/rcc/ UI_DIR = $$/ui/ MOC_DIR = $$/moc/ OBJECTS_DIR = $$/obj/ LIBS += -L$$/ INCLUDEPATH += $$/ INCLUDEPATH += $$/ linux-g++: QMAKE_CXXFLAGS += -std=c++11

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

PROJECT_ROOT_PATH = $$/

Далее определяем то, под какой ОС происходит сборка, и устанавливаем соответствующим образом значение суффикса OS_SUFFIX . Значение этого суффикса будет использовано для ветвления по каталогам lib.*/ .

win32: OS_SUFFIX = win32 linux-g++: OS_SUFFIX = linux

В следующем фрагменте в зависимости от режима сборки ( debug или release ) определяется значение BUILD_FLAG , которое будет указывать на версию используемого подкаталога в bin/ и build/ :

CONFIG(debug, debug|release) < BUILD_FLAG = debug LIB_SUFFIX = d >else

Кроме того, определяется вспомогательный суффикс LIB_SUFFIX . Мы будем использовать его для того, чтобы к именам библиотек в отладочном режиме присоединялся символ d . За счет этого мы можем иметь единый каталог для библиотек и не допускать конфликтов имен. Например, в lib.win32/ у нас может одновременно находиться обе версии MyLib.lib и MyLibd.lib .

Далее по порядку определяются пути к библиотекам lib.*/ , к открытым заголовочным файлам include/ , к импортируемым заголовочным файлам import/ и путь к каталогу с бинарниками bin/ :

LIBS_PATH = $$/lib.$$/ INC_PATH = $$/include/ IMPORT_PATH = $$/import/ BIN_PATH = $$/bin/$$/

Заметим, что в конце определения LIBS_PATH мы воспользовались нашим OS_SUFFIX , а в конце BIN_PATH подставили BUILD_FLAG , чтобы привести пути в соответствие с нашей начальной задумкой по ветвлению конфигурации проекта на основании версии ОС и режиму сборки.

Ниже стоит блок, который задает пути сборки для файлов ресурсов rcc , файлов графического интерфейса ui , МОК-файлов moc и объектных файлов obj :

BUILD_PATH = $$/build/$$/$$/ RCC_DIR = $$/rcc/ UI_DIR = $$/ui/ MOC_DIR = $$/moc/ OBJECTS_DIR = $$/obj/

Каталог сборки для каждого подпроекта будет свой. При этом его расположение зависит от режима сборки и от имени самого подпроекта, которому соответствует переменная TARGET , определенная для каждого модуля.

Поскольку библиотеки и заголовочные файлы с большой вероятностью будут использоваться многими модулями совместно, то мы определяем ключевые переменные LIBS и INCLUDEPATH тоже в общем файле:

LIBS += -L$$/ INCLUDEPATH += $$/ INCLUDEPATH += $$/

Ключ -L перед $$ означает, что мы определяем каталог, в котором компоновщик должен искать библиотеки в процессе сборки. А чтобы добавить конкретную библиотеку, нужно использовать ключ -l . Например:

Читайте также:
Преемственность программы формирования универсальных учебных действий

LIBS += -lMyLib

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

Последняя строка не является обязательной для сборки, но если вы хотите задействовать в вашем приложении возможности C++11, то имеет смысл ее не забыть:

linux-g++: QMAKE_CXXFLAGS += -std=c++11

app.pri

Между всеми исполняемыми модулями есть что-то общее. Определим соответствующие настройки сборки в pri -файле:

DESTDIR = $$/ linux-g++: QMAKE_LFLAGS += -Wl,—rpath=\$$ORIGIN/../../lib.$$/

Переменная DESTDIR указывает путь, в который будет помещен готовый исполняемый файл. Это окажется либо bin/debug/ , либо bin/release/ .

В следующей строке определяется путь поиска динамических библиотек по умолчанию. В Windows он работать не будет. А в Linux позволяет упростить запуск скомпонованного исполняемого файла. Если опустить эту строку, то приложение все равно можно будет запустить, но тогда:

  1. Либо библиотеки должны лежать в системных папках, по которым осуществляется поиск;
  2. Либо путь сборки библиотек должен быть добавлен к системным с помощью файла /etc/ld.so.conf ;
  3. Либо должна быть определена переменная окружения LD_LIBRARY_PATH .

Вариант с LD_LIBRARY_PATH является самым простым, поскольку в этом случае вам не нужны root -права в системе. Удобно использовать для этого скрипт следующего вида:

#!/bin/sh export LD_LIBRARY_PATH=../../lib.linux/. /../lib.linux/import_dir/ ./MyApp

lib.pri

Как и для исполняемых файлов, для библиотек тоже удобно определить общий pri -файл:

DESTDIR = $$/ win32: DLLDESTDIR = $$/ VERSION = 1.0.0 QMAKE_TARGET_COPYRIGHT = (c) My Company Name

Переменная DESTDIR имеет такой же смысл, как и в app.pri .

Следующая строка будет работать только в Windows. Она удобна тем, что позволяет автоматически скопировать все *.dll -файлы в каталог к исполняемым файлам.

Определения переменных в конце указывают информацию о версии библиотеки и ваш копирайт. Например, в Linux при значении VERSION = 2.0.1 вы получите библиотеки с именем вида libMyLib.so.2.0.1 . Но копирайт будет отображаться только в Windows, при этом имя библиотек будет выглядеть следующим образом: MyLib2.dll , а в свойствах вы увидите что-то подобное:

MyLib2

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

Кроме того, обратите внимание, что в описании библиотеки указаны не только «Авторские права», но и «Описание файла» с «Названием продукта». Эти два значения уже имеет смысл определять для каждой библиотеки в отдельности.

MyApp.pro

Пришло время посмотреть на содержимое файла конкретного модуля:

QT += core gui TARGET = MyApp TEMPLATE = app SOURCES += main.cpp mainwindow.cpp HEADERS += mainwindow.h FORMS += mainwindow.ui include( ../../common.pri ) include( ../../app.pri ) LIBS += -lMyLib$$

Содержимое этого файла достаточно типично для Qt-проектов и не вызывает особых сложностей. Большую его часть может легко создать QtCreator , поэтому рассмотрим лишь последние 3 строки. Директива include позволяет включить содержимое наших pri -файлов, объявленных ранее.

В зависимости от версии утилиты qmake мы могли бы вынести команду include( ../../common.pri ) в начало файла app.pri , чтобы уменьшить количество кода, поэтому проверьте, будет ли работать такой вариант у вас. В последней строке мы просто подключаем наш модуль MyLib с суффиксом LIB_SUFFIX . Заметим, что путь поиска библиотек компоновщиком уже был определен в common.pri , поэтому здесь нам его дублировать не нужно.

MyLib.pro

include( ../../common.pri ) include( ../../lib.pri ) QT += core gui TARGET = MyLib$$ TEMPLATE = lib DEFINES += MYLIB_LIBRARY SOURCES += mylib.cpp HEADERS += ../../include/mylib.h ../../include/mylib_global.h win32

Здесь тоже все достаточно стандартно, но обратим внимание на следующие моменты:

  1. Чтобы в переменной TARGET задействовать суффикс LIB_SUFFIX из common.pri подключаем его заранее в самом начале;
  2. Заголовочные файлы предполагается передать в дальнейшем кому-то другому, поэтому перенесем их в предназначенный для этого каталог include/ ;
  3. Название продукта и описание, про которые говорилось выше, мы описываем для каждой библиотеки с помощью переменных QMAKE_TARGET_PRODUCT и QMAKE_TARGET_DESCRIPTION .

Заключение

Вот мы и рассмотрели способ организации проекта на C++. Очевидно, что нет особой необходимости пользоваться утилитой qmake для того, чтобы ей следовать. Кроме того, с минимальными изменениями она вполне может подойти и для проектов на других языках программирования. Однако следует учитывать, что не существует идеального способа организации проекта, поэтому вы можете взять предложенный мной вариант в качестве основы и адаптировать его под свои нужды.

Источник: itnotesblog.ru

Как сбилдить релиз версию приложения на Qt?

Приложение запускается через Creator, поставил Release тип сборки,собрал проект.В папке файл не запускается, посмотрел по stackoverflow,пишут все что надо пройтись через dependency walker,чтобы понять каких dll не хватает.Натравил его на exe файл, высветилась туева куча dll. Неужели нет какого нибудь более простого способа релиз билда приложения на qt.

  • Вопрос задан более трёх лет назад
  • 5668 просмотров

Комментировать
Решения вопроса 1

1) идёте в папку с собранным *.exe файлом.
2) копируете путь не к файлу, а к папке, где находится этот файл из п.1
3) запускаете «командную строку Qt (с нужным вам компилятором.. там их может быть несколько)» через меню «Пуск».
4) с помощью команды cd /d в открывшейся консоли переходите в папку с собранным *.exe
5) выполняете windeployqt.exe .
6) готово. Все нужные *.dll скопируются в папку с исполняемым файлом.

Читайте также:
Список литературы на лето по программе перспектива для 2 класса

Ответ написан более трёх лет назад
Комментировать
Нравится 7 Комментировать
Ответы на вопрос 2
Живу в своё удовольствие

Погуглите по запросу «Статическая линковка Qt».

Если очень кратко, то вам нужно «пересобрать» компилятор, чтобы он все эти dll-ки сам линковал с релиз версией программы

Источник: qna.habr.com

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

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

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

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

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

Теперь небольшое описание.

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

Возьмем пример.

Например, я написал простое qt-приложение с использованием qml — MyApp.

MyApp (main.cpp)

#include #include 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/

cqtdeployer result

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

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

Рекомендуем хостинг TIMEWEB

Рекомендуем хостинг TIMEWEB

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

Рекомендуемые статьи по этой тематике

  • Релиз утилиты развертывания С++/Qt и QML приложений CQtDeployer v1.3.0
  • Релиз утилиты развертывания С++/QML приложений CQtDeployer v1.2.3
  • SNAP Урок 04. Работаем с деплоем для Qt приложений на основе снап пакета

По статье задано0 вопрос(ов)

Подписка на обсуждение 4
Подписка на раздел 336

Вам это нравится? Поделитесь в социальных сетях!

Источник: evileg.com

Рейтинг
( Пока оценок нет )
Загрузка ...
EFT-Soft.ru