Table of Content
Building Qt Installers
Developing software is only the first step in getting your great ideas into the hands of users. It is equally important for the software to be easy to install on the users’ systems. This is where installers, or packages, enter the picture.
A Qt application generally consists of a number of files. These can be divided into three groups:
1. The executable, the program that the user runs.
2. Dynamic libraries (dll or so files), usually a couple of Qt modules (QtCore, QtGui and friends) and plug-ins
3. Support files, such as graphics, translations, documentation, and so on.
When creating an installer, you take these parts and build a package out of them. That package not only contains the needed files, but also instructions on where to place them and what questions the user will have to answer, and so on.
The trouble of having to package and spread dynamic libraries can be solved in two ways. On most Linux distributions, Qt is already packaged. By building your application against a prepackaged version of Qt, you can usually put Qt down as something that your application depends on. Most modern Linux distributions will then offer the user to download and install Qt for them when they try to install your package.
The other approach, which works across all platforms, is to link Qt statically to your application. This requires you to configure and build a static version of Qt. This, however, does mean that you cannot close your source code and reply on the LGPL. Instead, you will either have to open source your code, or acquire a commercial Qt license.
Another downside of static linking is that your executables will be significantly larger, as they have to contain all the Qt modules that you ar relying on. Also, when deploying multiple Qt-based applications, each application will carry its own copy of the Qt libraries, instead of relying on a shared set of dynamic libraries. The problem with large file sizes can be addressed using the UPX [upx.sourceforge.net] tool. It compressed the executables which are then decompressed in RAM when being started and is available from Windows, OS X and Linux (as well as Atari ST and 16-bit DOS).
Something worth mentioning when discussing dynamic libraries are plug-ins. You must deploy and plug-ins that your application relies on. Not including the plugins will not cause your deployed application to fail to start – but just criple the functionality of it.
The third category of files, support files, can also be integrated into the executable. The easiest way to achieve this is to use the Qt resource system [qt-project.org]. It allows you to embedd any file into your executable. This is the logical place for most files used only by the executable and not the user. This can be help documentation, icons and pictures, translations, etc. Files that are hard to place here would be example documents and other files that the user expects to be able to find in the file system.
Building installation packages is, and will probably always be, somewhat a platform specific task. Not only because the platforms are different, but also because the distribution mechanisms differ. You can read more on platform specific issues in the Qt documentation. This text covers the same topics, but in a more hands-on way.
Having built your Qt application on the Windows platform, you need to find the dynamic libraries (dlls) on which your application relies. For this job, you can use the Dependency Walker [dependencywalker.com]. It shows a graphical tree, showing the dlls that the executable relies on, as well as which dlls each dll rely on.
The trick when using the dependency walker is to decide on which dlls that belong to Windows, i.e. are already preinstalled on the users’ computers, or belong to Qt, i.e. needs to be packaged. If you use any third party library, you must also take that into account, potentially adding more dependencies. Another issue to be aware of is that Qt dlls can depend on other Qt dlls. For instance, the Qt3Support module depends on most other Qt modules.
When using MinGW to build your Windows applications, you must also include the mingw10.dll file in your installer package. There are numerous recepies available on the web for how to build Qt without this dependency, as it otherwise hinders the deployment of statically linked executables without any accompanying files.
Having used the dependency walker to put together a list of files needed, the next step is to build an installer out of these files. There are numerous tools available for this task. Some that are known to be easy to operate and work with Qt are listed here:
- InnoSetup [jrsoftware.org] from Jordan Russel. Contains a wizard for creating installer scripts. The scripts are then compiled into the installer. The scripts can also be editied by hand for full control. This tool is used by, for example, the SpeedCrunch [speedcrunch.org] project.
- NSIS [nsis.sourceforge.net] from Nullsoft. An open source installation builder. Also based on scripts that are built into an installer. This tool is used by numerous Qt-based applications.
- Eclipse NSIS [eclipsensis.sourceforge.net] from Nullsoft, too. But this is an Extension for Eclipse with a Wizard which creates the script for you.
When testing an installer, make sure to use a machine without any version of Qt installed onto it. Preferrably, a completely fresh install of Windows, but never a machine with the Qt development environment installed on it. In your installer is missing any dll it will fail to execute with an error message stating which dll that is missing. However, plug-in dlls are not checked when starting, so you need to make sure to test that all functionality provided through plug-ins is present.
There are a number of ways to distribute your application for Linux systems. For open source projects, the easiest approach is to build a source tar-ball. To clean your build environment for this, run make distclean before tar-ing and compressing the directory tree using tar cvfj foobar.tar.bz2 foobar/ (or cvfz for .gz compressed files).
When it comes to building installers, or packages as they are more commonly known as, it all depends on the distribution that you target. There are two main schools for this: rpm and deb. The rpm format has its roots in the RedHat distribution but is used by other distributions such as Fedora, SuSE, Mandriva and MeeGo. The deb format was developed by the Debian project and is found in Ubuntu (and derivates) and Maemo.
The basic principle behind both systems is that you build a recepie for building and installing your application. This recepie includes a list of required dependencies such as Qt, how to build your application from source and which files to include and where to place them. This might sound like a tedious task, but is usually quite straight forward as soon as you have tried it once or twice.
Some things that are good to know is that Qt sometimes comes as multiple packages. For instance, modules may be packaged separately. Take this into account when defining the dependencies for your application.
Further reading for packaging rpms is the RPM HOWTO [tldp.org], in particular the section on building rpms. For debs, the Debian New Maintainers’ Guide [debian.org] is a good place to start. Looking through the specific packagers’ documentation of your target distribution is also recommended.
Not covered – yet.
Multiplatform GUI installers
Also, you can use cross-platform installer:
- InstallJammer [installjammer.com] (no longer being maintained).
- BitRock InstallBuilder [installbuilder.bitrock.com] (actively maintained) : BitRock InstallBuilder for Qt is able to create self-contained installers for all the platforms that Qt supports. The installers can run in GUI, text and unattended modes. It is a commercial tool but it offers free licenses for open source projects and discounts for small development shops.
- IFW [qt-project.org] : Official Qt installer which designed to be Qt developers friendly but it still in earlier stages and currently used by Qt itself for online and offline installers (a primarily manual available on snapshot host [doc-snapshot.qt-project.org] )