The fun is over, you’ve written your Qt 5.x application, compiled it for Ubuntu and it is time to deploy your software to a vanilla box (a PC without any Qt libraries on it), how do you go about it?
I spent quite some time struggling with this problem so now that I have finally got it working (for XML Mill at least), I decided to share my experience.
With regards to my setup, although I build Qt from source myself, I don’t believe what follows will differ much if you installed Qt from a binary package. Of further importance is that I do not build Qt statically due to the LGPL licensing restrictions (which is why I have to go through the library distribution process in the first place) and, finally, my current Ubuntu platform is 12.04.3.
Since most of what you will need to know is already discussed at length in the two reference articles at the bottom of this post I won’t go into the details of how to determine which dependencies your application has, etc, but will rather tell you how I did it. After copying all relevant dependencies and platform plugins to their respective folders, I ended up with a directory structure that looked like this:
I will get to the “fonts” directory in a bit since that is not addressed in the referenced articles, but the “platforms” directory is discussed and the “sqldrivers” directory is included due to the fact that this application makes use of the Qt SQLite plugin. I also prefer not having all my dependencies in the same directory as the application as I personally find this neater, hence the inclusion of the “libs” directory.
With the run script set up (once again see the first link below for the necessary concepts), I fired it up and ran into the following error:
Aborted (core dumped)
This surprised me as I was sure I had set up the directory structure correctly and the “libqxcb.so” platform library was definitely there. After some investigation, I realised that the dependencies for this library was missing, resulting in the same error as if the library itself wasn’t there at all. In order to fix this, a user will obviously need root access, but running this script from within the platforms directory (where “libqxcb.so” lives) will resolve all the outstanding dependencies for you (the script will also create another script to uninstall all dependencies installed in this manner in case you wish to undo what you have done).
After I resolved the libqxcb dependencies, I once again tried to run my application on the vanilla box and ran into yet another error:
Aborted (core dumped)
This did not make any sense to me at all since the directory path referenced only existed on my development box…how did this happen and, more importantly, how do I fix it?
It turns out that the reason is that Qt contains hard-coded paths that are set at build time and it was one of these (non-existent on the vanilla box) paths that was being queried by the application and (obviously) found missing, resulting in the error above.
Since the font engine uses QLibraryInfo to find the paths it is apparently possible to prevent this issue by setting the paths from within your application itself (I did not try this as I wasn’t too keen on hard-coding paths within my application myself). Alternatively, one could also use a qt.conf file to override these paths, but there is also a third option which is to set and export a QT_QPA_FONTDIR environment variable in the run script. This was the route I decided to take.
I created the “fonts” directory at the same level of my executable (see the directory structure image above) and copied all the fonts from the directory referenced in the error message across. A quick edit to my run script resulted in the following (I kept it very simple as you can see):
#!/bin/sh export LD_LIBRARY_PATH=`pwd`/libs export QT_QPA_FONTDIR=`pwd`/fonts ./XMLMill
And that was it…finally it worked!
I have written a bash script to do all of the above for me (specifically for XML Mill). This script:
- Creates the “libs”, “platforms”, “sqldrivers” and “fonts” directories.
- Determines which libraries the application depends on and copies these dependencies to the “libs” directory (it may not be necessary to ship all of the dependencies found, but it will be up to you to determine which ones can be excluded after the fact).
- Copies the “libqxcb.so” library to “platforms” (the path to this library is set in the script itself).
- Creates the “fixdep.sh” script (the script mentioned above to resolve “libqxcb.so” dependencies) and copies it to the “platforms” directory.
- Copies the “libsqlite.so” library to “sqldrivers” (this is a specific plugin dependency for XML Mill).
- Copies all fonts (the path is specified in the script itself) to the “fonts” directory.
- Creates the run script in the form “run<appname>.sh”
- Creates a tar ball of all of the above.
The script lives here but please note that you will have to edit the script to suit your needs.
If you need any assistance with this script, feel free to contact me.