Deploying Qt Applications

From QtCentreWiki

Jump to:navigation, search


Deploying Qt Applications

This page contains information about deploying Qt applications to end users by making sure the Qt libraries are linked correctly and possibly bundled with the binary.

Static Linking

Linking static.png

Static linking is the most straight-forward way of making sure that your application will run on the user's system. All Qt-related code will be compiled and hard-wired into your application, which has the following pros and cons:

Pros

  • Usually you just have to deploy a single file to the end user, which reduces the amount of work required to create an installer package.
  • Your application can run independently from the (possibly) already installed version of Qt on the target system.
  • Slightly faster startup-time (on today's CPUs you hardly will notice it)

Cons

  • Your application becomes rather huge, because the Qt code is compiled and linked into it.
  • It is not possible to update/change the Qt libraries used by your application, since they are hardwired. Thus, if bugs are fixed in the Qt libraries, you'll have to re-compile and deploy your application again.
  • Uses more RAM if you start multiple instances of a single executable since the Qt code is loaded for every instance of your application.
  • You can not use QPluginLoader to load plugins at runtime, but you can use QLibrary (which is more complex to use).
  • Static linking is not subject to the new LGPL-licensing, thus you'll have to buy a commercial license if don't want to release your own code under the GPL.

Dynamic Linking

Linking dynamic.png

Most of the time (both for open-source and properitary software) you'll want to use dynamic linking. Dynamic linking is widely used and offers the best possible flexibility for both users and developers.

Pro

  • Your application will be more compact.
  • The Qt libraries can be updated and changed without having to re-compile your application - most Linux package-managers rely on this to provide security updates and fixes, without having to re-install every single application on that system.
  • Less RAM is required to start multiple instances of your application - since the Qt libraries are only loaded once by the dynamic linker.

Cons

  • Deploying a dynamically linked application is usually more work and requires careful testing on "vanilla" systems to make sure everything will work on the target systems, too. But the flexibility gained by dynamic linking is usually worth the extra work.
  • You will have to make sure that all required libraries are available on the target system and offer a fallback-solution if they are not available on the target system.


Linux

The Dynamic Linking Problem

Linking applications dynamically on Linux while making sure that the target machine has the right [versions] of libraries installed can be tricky. Unless you used the same version of Qt that is available through the package manager of the end user's version of Linux, you'll have to make sure that the right Qt runtime is available when your application needs to be started.

To solve this, we have a number of options:

Option A: Installing the required Qt libraries on the system

Another solution is to install the required Qt libraries into the right paths of the target system. Generally this should be done by the target's package management and you never know what a user has installed on his system or if he really wants us to touch his existing setup.

The problem with this approach is that the user might not have the permissions to install libraries into the system paths of the system. Another reason might be that the user simply wants to test the application without taking the risk of breaking the existing installation of libraries.

Option B: Setting the rpath

The rpath is a way to hardwire the search-path for an application at compile time.

Please note that qmake automatically uses this to point to the Qt libraries if they are not installed in a standard path, such as /lib. This makes it possible to install multiple versions of Qt on the same system and still have the application use the right libraries.

The biggest problem with rpath is that it overrides the LD_LIBRARY_PATH environment variable and thus cripples your application once the user moves the libraries somewhere else. It is generally seen as a bad habit to set the rpath for an application and should be avoided if possible.

Option C: Using LD_LIBRARY_PATH

The most flexible solution to the dynamic linking problem is to set the environment variable LD_LIBRARY_PATH, which will tell the dynamic linker where to look for libraries first. In order to set the environment variable before your application is actually started, you will need a small helper script.

A script like this should be sufficient in the most cases, assuming the script will be executed from the same directory the application resides in:

#!/bin/sh
export LD_LIBRARY_PATH=.
./appname $*

When running this script, the environment variable LD_LIBRARY_PATH will be set to "." - this tells the dynamic linker first look for required libraries in the current directory. Of course you can change it to be something else, such as "lib", if you want to keep the libraries out of the user's sight.

To find out which libraries are used by your application, the ldd tool will be of help:

ldd <appname> | grep libQt

Will show something like:

libQtGui.so.4 => /usr/lib/libQtGui.so.4 (0xb7625000)
libQtNetwork.so.4 => /usr/lib/libQtNetwork.so.4 (0xb72f2000)
libQtCore.so.4 => /usr/lib/libQtCore.so.4 (0xb70c4000)

Which means that your application is using the libraries in /usr/lib/. And that we'll have to copy the 3 libraries to our application directory.

This will list all Qt-libraries used by your application. Simply copy them to the same directory your application resides in and run ldd again (with the environment variable set!) to see if the dynamic linker points to the copied libraries in the current directory:

libQtGui.so.4 => ./libQtGui.so.4 (0xb76b4000)
libQtNetwork.so.4 => ./libQtNetwork.so.4 (0xb7347000)
libQtCore.so.4 => ./libQtCore.so.4 (0xb7106000)

If it doesn't, don't panic. Unless you have installed Qt in the default system locations, you'll have to strip the automatically added rpath from your application - read on.

It is generally a good idea to strip a possibly existing rpath entry in the application. In most cases, it has no effect on a target system and is silently ignored, but in some cases the user might have a differently configured version of Qt at the path rpath points to, this might lead to unexpected problems (such as OpenSSL was enabled in the Qt version on the compiling system, but disabled in the target system).

You can use the chrpath tool to clear the rpath (which is available through most package managers):

chrpath -d <appname>
Conclusion

Of all options listed above, the LD_LIBRARY_PATH is the most flexible one for both the developer and the user: It allows the user to choose between the system-wide installed Qt libraries and also offers a fall-back solution if Qt is not installed. Both the rpath solution and the installation of the required Qt libraries into default system paths might be problematic due to missing user privileges and is subject to failure.


Mac OS X

Dynamic linking on Mac OS X can be tricky as well. Applications on Mac OS X are usually wrapped into bundles (special directories that contain the application executable and required resources). In most cases this is a good thing, because everything (including the required Qt libraries) can be within the application bundle, and the user only has to copy a single file (the bundle) to the Applications directory.

The trickiest part of deploying applications to Mac OS X is adding the required Qt libraries to the application bundle. The Qt documentation extensively covers how to copy and re-configure the application binary to use libraries in paths other than the system defaults - but to be honest - it's a pain to do that over and over again.

Happily, some people have written tools to automate the process of finding out which libraries are required by your application, copy them over into the bundle and re-configure the application binary to point to the right paths within the bundle.

  • deployqt (link) is a small C++ application written in Qt that automates the above steps, and produces a application package that is ready to be shipped to the user.
  • The Mac_OS_X_Deployment_Script is also a way to automate the steps required to make a bundle deployable. (BastiBense: Personally I didn't use it yet, so I'm not sure if it works 100%!)
  • Qt 4.5.x for Mac OS X comes with the macdeployqt command-line tool and should be used for preparing distribtion of Mac OS X builds.

Mac OS X 10.3 (Panther) compatibility

In some cases it makes sense to provide not only a universal binary of your application, but also make it work on older versions of Mac OS X. The oldest version which requires little effort to support is Mac OS X 10.3.

In order to support Mac OS X 10.3, add the following lines to your application's .pro file:

macx { 
   QMAKE_CXXFLAGS_RELEASE += -fvisibility=hidden
   QMAKE_CXXFLAGS_DEBUG += -fvisibility=hidden
   QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.3
   QMAKE_MAC_SDK = /Developer/SDKs/MacOSX10.4u.sdk
}

Please note that the 10.3 and 10.4 SDK must be installed in order to be able to compile. This can be enabled during the installation of Xcode.

Windows

Dynamic linking on Windows is a bit less painful than under Linux. Normally Windows' dynamic linker looks into the application directory and loads the libraries found there.

To find out which libraries are required by your application, you can use a tool called Depency Walker (link). It allows you to load your compiled executable and watch which libraries are loaded from where, and if all dependencies are met.

To provide a familiar user experience, you should provide a Setup program (Installer) that places the libraries and applications into the right places on the target system, creates shortcuts to the Start-menu and also provides an uninstaller. There are many tools to create installer programs out there, NSIS (link) is one of the more popular ones.