Comments, Code and Qt. Some words about the wonderful world of software engineering

3Jul/1122

Deploying Qt and Qt Quick applications on Windows

I recently had to deploy a Qt Quick application on a Windows machine that did not have Qt installed explicitly on it. I think this is a pretty common use case that can cause quite some headache. You basically have two options if you want to deploy (or install) your Qt or Qt Quick based application to Windows. Either you can use the Windows Installer service directly or use some free or commercial utility to create a MSI based installer application that will deploy your application on Windows. Alternatively or at least as a first step you can package your application into a ZIP, or some other, package together with the necessary libraries that the application depends on. This is what I did and what I am going to explain here. When the package is extracted on the target machine, your Qt or Qt Quick application can be run from that directory just by launching the .exe file. Pretty neat.

Below I will explain some important points on how you want to create the package that you want to distribute your Qt application in. In my case I deployed a Qt Quick application that used Qt/3D and QtWebKit.

Dependency Walker

I first recommend you to install a great tool for figuring out the required .dll files that you need to include in your package: Windows Dependency Walker. It's a neat free utility that will create a hierarchical tree of the .dll dependencies that an application uses. When you run your application, in the machine that has Qt installed on it, through Dependency Walker you can easily see which Qt .dll files it uses and you need to package with your application.If  you are curious, you'll find that Dependency Walker will show you a lot more information about what  methods the application used and from which .dll file, which methods are available in the .dll but were not used and a lot more detailed information about each .dll that the application loaded.

When you run your application through Dependency Walker on the machine that does not have Qt installed on it and when it did not run as expected, you can then see which .dll files your app failed to find. This is really a life saver when it comes to application deployment for Windows.

A word on warning, though. Dependency Walker is really good at finding libraries that your application is dynamically linked against. But it will not spot issues when it comes to Qt plugins. If a plugin is not found, there will not be any trace of it in Dependency Walker since Qt will just inform the app that this plugin is not available. So it is important to understand which plugins Qt will need and Dependency Walker cannot help you here.

Windows dependency walker

Windows dependency walker

Deploying dynamically linked Qt application without plugins

This is the easiest type of application to deploy. It's basically a Qt application that only uses one or more Qt modules (the .dll files) that do not depend on plugins. Such an application could for example be a QWidget based application, but one that is not showing images. You can already guess which Qt .dll files your application needs: each of the Qt modules is one Windows .dll file. So when you type in your .pro file for example

CONFIG += network

to do network programming, you know you have to include QtNetwork4.dll in your package.

Where do I find this file you ask? Well - it's in the Qt installation directory on your machine and in the bin/ directory under it. Go there and copy the required .dll files to your deployment folder that you intend to package.

If you have an application does not use Qt plugins on your hands and you want to deploy on Windows, then it's enough to package the .exe file together with all the dependent .dll files in the same root folder. When you extract the package in a directory and launch your application, Windows will first look for the required .dll files in the same folder as where the application was launched. Since this application does not use any plugins it will find all the required Qt .dll files it depends on in the same folder as the application was launched in (the rest of the .dll files should already be installed on the target machine). As an example I could deploy a QWidget based application that reads something of the network by creating a package that contains the following files:

application.exe
QtCore4.dll
QtGui4.dll
QtNetwork4.dll

Deploying Qt applications with plugins

Even if you didn't utilize a plug-in based architecture for your application Qt uses internally plugins. When you deploy your application you need to make sure the plugins are included in the package. Plug-ins are essentially just .dll files that are loaded at runtime.

When Qt is looking for plug-ins to load, it will look in specific folders for the plug-ins. Each plug-in is categorized based on its function and plug-ins that provide similar functionality will be in the same folder. For example all SQL implementation (driver plugins) are in a folder called sqldrivers so when Qt wants to load a SQL driver it will look into that folder.

But Qt must have a way to find the plug-in category folders. Qt has two ways to do this. First, it will look into a folder called plugins that is part of the Qt installation. More important to you, secondly it will use the current directory where the application was launched. Qt will look inside these two folders for the plug-in category folder.

This is why, when you deploy your application, remember to put the plugins into their respective category folder and the category folder on the root level in your package.

So if I want to use QtWebKit to show a webpage in my application, I would need to include the .dll files that QtWebKit depends on and also the runtime plugins that it depends on to show GIF and JPEG images. I would create the following hierarchy in my deployment package:

imageformats/qgif4.dll    //<< QtWebKit depends on this
imageformats/qjpeg4.dll   //<< QtWebKit depends on this
application.exe
QtCore4.dll
QtWebKit4.dll
QtNetwork4.dll            //<< QtWebKit depends on this
QtScript4.dll             //<< QtWebKit depends on this
QtScriptTools.dll         //<< QtWebKit depends on this
phonon4.dll               //<< QtWebKit depends on this

Deploying Qt Quick applications with plugins

First I must say that if you deploy and application that doesn't use Qt Quick plugins you can deploy it as the example above shows. But if your application uses Qt Quick plugins (you know, for example the import QtWebKit 1.0 line in your QML file if you use WebView) then you need to be aware how Qt loads Qt Quick plugins.

Qt has some good documentation on Qt Quick modules and import paths so I try to be brief about it. But what you need to know is that when you write import in your QML file, Qt will always look for a runtime module in a folder that you specified on that line. So when you write import QtWebKit 1.0, what Qt is actually doing is looking for a folder named QtWebKit. Important for deployment is that Qt will do so in the directory where you launched your application.

In this folder, Qt Quick will look for a file called qmldir. It's a file containing meta-information such as available plugins that represent the component I want to import. If I wanted to use the WebView element in Qt Quick, I would then create a qmldir file and put in a folder called QtWebKit in the root folder of my package. The content of the file would be as follows:

plugin qmlwebkitplugin

This will tell Qt Quick that the QtQuick 1.0 plugin (that you specified on the import line) is available in a plugin file (a .dll file) called qmlwebkitplugin. Qt will now look for a suitable plugin with the name qmlwebkitplugin - on Windows that plugin is in a file called, unsurprisingly, qmlwebkitplugin.dll in the same folder as the qmldir file.

Summary

As I stated in the beginning, I used Qt/3D, Qt Quick and QtWebkit components in my application. To be able to use all of these components and to satisfy the dependencies, my deployment package looks something like this (directory with QML files omitted):

imageformats/qgif4.dll
imageformats/qjpeg4.dll
sceneformats/qsceneai4.dll
QtWebKit/qmldir
QtWebKit/qmlwebkitplugin.dll
application.exe
Qt3D.dll
Qt3DQuick.dll
QtCore4.dll
QtDeclarative.dll
QtGui4.dll
QtNetwork4.dll
QtOpenGL4.dll
QtScript4.dll
QtScriptTools4.dll
QtWebKit4.dll
QtXml4.dll
QtXmlPatterns4.dll

I can run my application on any machine even without Qt installed when the package is extracted and the application.exe is launched.  On the downside the deployment package is rather big because of all the dependencies. QtWebKit module alone is a huge package: almost 17 megabytes. My application doesn't do much fancy and it does not include any images or other multimedia files. Still my deployment package is 52 megabytes big when it's extracted. Qt is actively working on splitting the modules into smaller pieces and Qt5 will deliver an even more plug-in based architecture that will cut down the size of individual modules and eventually your deployment package.

Technorati Tags: , , ,

  • Cristian Adam

    On the other hand you can compile everything statically. You might have to hack Qt a bit, but I’ve seen Qt Quick applications on Windows statically build, without WebKit and Qt 3D though.

    • http://www.johanpaul.com/blog/ Johan Paul

      True, but:

      - If you link Qt statically, then your application too becomes LGPL licensed
      - QtWebKit cannot be used if Qt is statically linked.

      • Steve

        Static linking does not make your application LGPL, just a lot more difficult to distribute. The point of the LGPL is that you have to allow someone to re-link your program against a later / bug-fix version of Qt. Using DLLs are the easiest way to do this, but providing object files and linker instructions is also allowed.

        • http://www.johanpaul.com/blog/ Johan Paul

           Technically yes, practically no-one will do this, hence dynamic linking remains the only feasible alternative.

  • http://twitter.com/jodyfanning Jody Fanning

    I suggest that, if you want to write real Windows MSI based installation packages (and who wouldn’t), you ignore everything else and use WiX.

    http://wix.sourceforge.net/

    WiX is written by mostly MS guys and exposes all of the important Windows Installer stuff through a relatively simple XML format. Plus it is open source.

    • http://www.johanpaul.com/blog/ Johan Paul

      Thanks for the tip! I’ve never looked deeper into Windows installer stuff, but WiX looks really good. I will keep this in mind if I have a need of creating a installation package for real.

  • Sysad

    Am I the only one that has noticed that, if you ” package together with the necessary libraries that the application depends on” or “build statically”, etc –> every time Qt has a security update… you have to update your distributed program and make everyone update your program?

    • Sysad

      I mean that, for example, if you “package your application into a ZIP” with the “QtCore4.dll” file inside, every time that “QtCore4.dll” file has a security update, you have to update your official ZIP file and also have all the users update your program, even if it has not changed.

      A similar thing happens if you compile statically.

      Is this way?

      • http://www.johanpaul.com/blog/ Johan Paul

        Yes, this would be the case. The same situation is with any application that depends on a 3rd party library – only that some platforms deal with 3rd party library updates better than Windows. On Windows nothing encourages the user to update Qt even if the libraries are installed from an official distribution separately.

        • Sysad

          Uf, this reminds me of why I am writing this using Kubuntu :-)

  • Philipp Tkachev

    I think, NSIS installer also working very well.
    http://nsis.sourceforge.net/Features
    NSIS Editor also is very useful
    http://hmne.sourceforge.net/

  • Philipp Tkachev

    In addition to summary: you must put your SQL Drivers to “sqldrivers” folder.
    For example:
    path_to_your_application_root/application.exe
    path_to_your_application_root/sqldrivers/qsqlite4.dll

    • http://www.johanpaul.com/blog/ Johan Paul

      Yes. In general, for any yet to be seen Qt plugin, Dependency Walker is your friend to discover where Qt tries to load the runtime libraries from.

  • http://twitter.com/ptbw2000 Phil Willis

    Thanks for this. The fact that JPG’s refused to show in my application on Windows was that I was missing the imageformat directory and qtjpeg4.dll out of 100′s of posts on the net with this problem, yours was the only one I have found that fixes it.

    • http://www.johanpaul.com/blog/ Johan Paul

      Nice to hear I was able to be of assistance! Thanks for reading.

  • Alexander Bartz

    Johan, thank you a lot for your great description! It’s the best I have found on this topic. Now I’m having trouble to deploy a Qt Quick application that is using WebKit under Qt 5.0. Since phonon is no longer part of Qt (as far as I know) I can’t use your list of dependencies 1:1. Do you have knowledge about that scenario you can share?

    • http://www.johanpaul.com/blog/ Johan Paul

      First of all, thank you for the nice words! :) But the less nice thing is that since writing the blog post, I’ve moved on and I am not actively working with Qt5 stuff. Hence, I can’t give you any insight in this matter, I am afraid.

      But I do hope you can solve the issue – and then maybe add a comment here about :) IRC and the FreeNode channel #qt is at least one great place to ask for help.

      • Alexander Bartz

        Thanks nevertheless! I’ll post the solution here if I find one…

  • hicham

    شكراً

  • Brent Jiang

    thanks very much for your great post, I successfully deployed my Qt Quick 1.1 application with QtQuickControls (pull out from qt4 branch) plugin.

  • maverick

    Thanks for the neat write up. I have one question….is it possible to distribute an exe which was created when the qt app was run in debug mode ?

  • Seravee

    Thank you very much. I have been looking for this for some time.