Linux&Windows system Qt application package release

Recently, I have encountered some difficulties in publishing Qt applications. Windows is okay, but I have encountered a lot of troubles in publishing on Linux (actually Linux should be simple). After searching the Internet, I found that there are many posts, but they are all one-sided. Now put The package deployment of Qt applications on Linux&Windows is summarized as follows.

core

The core of application deployment is to load libraries. A Qt application contains at least the following libraries:

Windows

Qt5Core.dll、Qt5Gui.dll、Qt5Widgets.dll

Linux

libQt5Core.so.5、libQt5Gui.so、libQt5Widgets.so


Like other applications, Qt applications depend on the operating system to load these library files, which means they must be placed where the operating system can find them. On Windows, this means in the same directory as the .exe file or in a directory specified in the search path (e.g. C:\Windows\System32). When copying a DLL to another PC that doesn't have Qt installed, we usually don't want to mess with the search paths on the other computer, but putting the DLL together with the .exe file is probably the best solution.

On Linux, placing .so files in the same directory as the executable does not automatically load them like in Windows. But most Linux systems come with Qt pre-installed, such as on Ubuntu, usually Qt is installed in /usr/lib/i686-linux-gnu or /usr/lib/x86_64-linux-gnu, so our application still It works (but please be aware of version issues, the Qt provided by Ubuntu may be too old for our application to start).

Another point that is more error-prone when deploying Qt applications is the Qt plug-in mechanism. In addition to the several Qt core libraries mentioned above, some plug-ins must be provided if the program wants to run, such as: platforms, sqldrivers, imageformats, these are Plug-in directory, the name is determined by Qt (of course it can be modified, but it is not recommended to modify). The most important one is the platforms plug-in directory, which provides some platform plug-ins. All Qt applications need these libraries. For Windows, the default is qwindows.dll, and for Linux, it is libqxcb.so. This is Qt's QPA (Qt Platform Abstraction layer) which is responsible for many OS-specific things, such as translating calls to setWindowState(Qt::WindowMaximized) into Windows/Linux-specific system calls.

plugin settings

Some Qt plugins are mentioned above, how are these plugins Qt loaded? By default, Qt will look for and load these plugins in the directory where the executable file is located. But in order to make our program directory more concise, we can customize the plug-in directory.

Set environment variables QT_PLUGIN_PATH:

Using an environment variable might be the easier option, for example:

export QT_PLUGIN_PATH=plugins

Windows useset

Set the above environment variables, QT will be plugins\platformslooking for qwindows.dll. Of course, absolute paths can also be set in this way. And, if you want to get a large number of plugin directories, you can append ;additional paths separated by . (in Linux it is :).

Specify the plugin path in the code:

#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
    QApplication::addLibraryPath("plugins");//设置插件目录
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}

The plug-in path can be specified in the code, but since Qt loads the plug-in when constructing QApplication, the opportunity to set this is before calling the QApplication constructor. The above code has the same effect as setting environment variables.

Create a qt.conffile:

This is a popular way of setting up plugin path comparisons.

[Paths]
Plugins=plugins

This file is located in the same directory as the application executable, and Qt will read it and plugins= pathadd the path to its list of plugin directories. The above example achieves the same effect as before.

Note if you're on Windows: Plugins=Backslashes in this setting have no effect, Linux-style forward slashes should be used.

Plugin troubleshooting:

QT_DEBUG_PLUGINSFinally, if you still encounter plugin loading issues, you can turn on the log of the plugin loading process by setting the environment variable to a non-zero value

export QT_DEBUG_PLUGINS=1

Then start the application from a Terminal/CMD window. For Linux, you will see a line like this in the terminal QFactoryLoader :: QFactoryLoader()checking..., but in Windows Qt, the output will be routed to the OutputDebugString() API, so nothing will be displayed in the CMD window. The output can be seen using Visual Studio or Qt Creator, which isn't much help if you have problems with the plugin on a non-development PC. Another option is to download a utility and turn it on before launching the application.

Windows deployment

First use the Release mode to build the application to get the executable file myapp.exe. Using windeployqt.exea tool can automatically copy the Qt library and plugins to the application directory, but this tool will copy a lot more than the program needs. It is usually necessary to manually delete some libraries that are not needed by the program.

A Windows-deployed Qt application usually contains at least the following files:

windows

Included in the platforms directory qwindows.dll, such a simple application can run, and can be packaged and distributed.
This is the most basic application, usually our application will be more complex, such as plug-ins sqldrivers, imageformats, translations are required. for example:

More plugins

It would be messy to put all plugins in one directory, now we create one with qt.confthe following content:

[Paths]
Plugins=plugins

Then we create a new directory plugins and move all plugins to plugins. Let's make our application directory a lot cleaner:

Note: plugins is the directory that Qt will search by default, so it doesn't matter if there is no qt.conf, but if you want to specify a special plugin directory name, you must use qt.conf, such as: third.

Linux deployment

Almost all Linux distributions will pre-install Qt, so if our application is compiled for a specific distribution, we hardly need to do any configuration, just package and distribute executable files directly (if this is the case for you, just You don't need to read the following content).

But if the target Linux does not have Qt installed or the version is older, then our application may not run. This is also the problem I encountered, my application was Qt5.12.5developed and compiled, but the current very mainstream Ubuntu 18.04 ltshighest can only be used Qt5.9.5.

Is there no other way? Is it possible to upgrade the Qt installation of the Linux system? There are related articles on the Internet that need to destroy the basic configuration of the system. If you only want to run an application, you need to destroy the system environment configuration, which is not worth the candle. Can Qt5.12.5the dynamic library copied like Windows be run on other Qt installed with a lower version, or even on Linux without Qt installed? The answer is yes. The following content is to explain how to fully deploy Qt applications to Linux.

Modify the connection library (not recommended)

It is to link the system Qt library to the new version of the Qt library. There are similar methods on the Internet. This method is not recommended, because the Linux distribution has preset all libraries during development, and forcible modification may cause an application to fail. Used it, and ten apps crashed.

Package and publish with dynamic library (recommended)

First, use the Release mode to build the application and get the executable file myapp. There is a linuxdeployqt tool on GitHub that can help build .AppImageLinux executable programs in the format, but its purpose is to build Qt programs that can run on all platforms, so there will be the same problem. If our compilation environment is too new, it will not be available. this tool.

living comfortably without anybody's help

Many articles on the Internet use lddcommands to check which libraries our application depends on, and there are scripts that can automatically copy these libraries to the application directory, which is usually not feasible. Because lddmost of the libraries listed are not what we need, some are even unique to our build system, and we are not very sure which libraries to delete, and we can only check what our application directly depends lddon Which libraries cannot find out the indirect dependencies of the dependent libraries, which are only known by Qt itself, for example: libqxcb.so depends on libQt5DBus.so.5.

link library

Putting .sothe file next to the executable file will not be automatically loaded by the system like Windows loads a DLL. Linux has several ways to configure and load dynamic libraries. I use the method of setting environment variables here. Other methods usually require permissions LD_LIBRARY_PATH, rootand It destroys the original operating mode of the system, so LD_LIBRARY_PATHit is the best way to deploy a stand-alone application .

The following is the directory of my application under Linux. This is the directory structure of the most basic application, and you can hardly delete any files in it.

linux

./bin executable file directory
./bin/qt.conf qt special configuration file
./bin/myapp executable file
./plugins plugin directory
./plugins/platforms
./plugins/platforms/libqxcb.so
./lib dynamic library Load directory
./lib/libQt5Gui.so.5
./lib/libQt5Widgets.so.5
./lib/libQt5XcbQpa.so.5
./lib/libQt5DBus.so.5
./lib/libicudata.so.56
./lib /libicui18n.so.56
./lib/libQt5Core.so.5
./lib/libicuuc.so.56
./myapp.sh application startup script

startup script

Because our program contains the required libraries, we need to let the operating system load our own libraries. Based on this, we need to use scripts to start our applications instead of running executable files directly. Use LD_LIBRARY_PATHto specify the dynamic library loading directory, which needs to be specified here lib.

myapp.shThe content is as follows:

#!/bin/sh
appname=`basename $0 | sed s,\.sh$,,`

dirname=`dirname $0`
tmp="${dirname#?}"

if [ "${dirname%$tmp}" != "/" ]; then
dirname=$PWD/$dirname
fi
LD_LIBRARY_PATH=$dirname/lib
export LD_LIBRARY_PATH
$dirname/bin/$appname "$@"

If you use the above script to start the application, you only need to modify the script name.

bin directory

binThe directory stores executable files and qt.conf
qt.conftheir contents are as follows:

[Paths]
Prefix = ../
Plugins = plugins

PrefixSpecifies the program working directory, relative to the executable path. The default is .the current directory. Here I specify it as the ..parent directory in order to make the directory more tidy.
PluginsSpecifies the plugin loading directory, relative to the Prefix directory. pluginsIn the above specified way, Qt will look for plug-ins in my directory, for example plugins/platforms/libqxcb.so.

package release

The above directory structure and various dependencies are the minimum set of a Qt release Linux environment. You can use the above directory to build packages for various Linux distributions, or directly compress them for distribution. In this way, the application can run on an environment with a low version of Qt or even without Qt installed.

You can also write your own .desktopfile to use myapp.shas an application launch command.

Guess you like

Origin blog.csdn.net/dou3516/article/details/131848699
Recommended