Overview

If you’ve already made some dynamic builds in Qt, you’ve probably ran into dependancy hell when you tried to distribute the app you made. Apart from running dependancy walkers and hoping that solves your issues, a better solution is to statically link these dependancies. When you statically link, all the Qt dependancies (this does not include thrid party dependancies) will be bundled in your app. Unsurprisingly, the trade-off for this ease-of-distribution is much larger binary files.

Depending on who you google, statically compiling Qt apps is either not as hard as it sounds or a fucking nightmare. My experience falls into the latter case. I finally managed to build Qt from source (version 5.11.0) after five days of trial and error. While there are brief tutorials out there showing the few lines of code required to run the build, what they tend not to cover is the basic problem solving steps when you hit a bump in the road. Here, I’ll go over the steps I ran to get the build working in addition to the issues I ran into along the road and how I solved them.

Before we start, these steps worked for me on Elementary OS (Loki) which is based on Ubuntu 16.04.

Mise en Place: Qt Source and Dependencies

I used the normal Qt online installer to get the source code.

Getting the source code

The resulting source code was found in the default install folder, in my case ~/Qt5/5.11.0/Src/

If you don’t already have Qt installed on your machine, you probably want to install all the components in this step. Static builds are great for deployments, but static debugging builds can take an enormus amount of space. It’s good practice to test your apps with dynamic builds then just statically build your release version. Now we have the source code, lets try to cover our dependances.

sudo apt install qtbase5-dev qtdeclaratives-dev

Additionally, Qt recommends you get the following packages:

sudo apt install libfontconfig1-dev libfreetype6-dev libx11-dev libxext-dev libxfixes-dev libxi-dev libxrender-dev libxcb1-dev libx11-xcb-dev libxcb-glx0-dev libxcb-keysyms1-dev libxcb-image0-dev libxcb-shm0-dev libxcb-icccm4-dev libxcb-sync0-dev libxcb-xfixes0-dev libxcb-shape0-dev libxcb-randr0-dev libxcb-render-util0-dev 

Hopefully thats all we need… lets move onto the build.

Building Qt

The five days of hell I went through was due to building Qt within the source directory. This can result in some artefacts from previous failed builds that don’t get swept away by make clean. To avoid this, we want to do out-of-source builds. The process is simple… just run configure from your destination directory rather than the source. If anything goes wrong, you can just delete the entire destination directory and start over worry free. This is how I run the build config:

mkdir ~/Q5/5.11.0_Static;cd ~/Q5/5.11.0_Static;sudo ~/Qt5/5.11.0/Src/configure -v -static -prefix "/home/james/Qt/5.11.0_Static" -qt-zlib -qt-pcre -qt-libpng -qt-libjpeg -qt-freetype -qt-xcb -make libs -nomake tools -nomake examples -nomake tests -opensource -confirm-license -egl -opengl es2 -skip wayland

I added the commands mkdir ~/Q5/5.11.0_Static and cd ~/Q5/5.11.0_Static in the same line so that if a build fails I can quickly repeat the configure process by searching back in my terminal for a single line instead of three.

I won’t pretend to completely understand what all these options mean… but I’ll try to sum up what I think I know:

  • It seems quite standard that you don’t compile tools, examples, and tests for static builds.
  • Options formatted with -qt-[module] are referring to third party modules where we’re specifying that we want to use the bundled Qt versions of these rather than our preinstalled system versions. My assumption is that choosing more Qt versions of modules reduces dependancies (as they are bundled in the binary during the static build).
  • If you’re using Ubuntu versions < 17.10, you probably want to incude skip wayland in the config like I did. With 17.10, ubuntu started using wayland as opposed to Xorg as its default display server. On my 16.04-based distro I didn’t have wayland and thus my builds were failing due to some sneaky dependancies that wern’t flagged as errors in the config step. Alternatively, you can install wayland on your system… however, this also needs to be built from source on 16.04, so lets just make life easier and skip it for now.
  • -opensource and -confirm-license are just automatically saying yes the the appropriate promts during config.
  • The -prefix flag may be redundant here since we’re already running config from our destination directory. Regardless… -prefix is used for shadow builds. This lets you output your build results into an external directory form where you are running make. While this sounds similar to an out-of-source build, its not! Both actions result in your compiled program being dropped to an external folder outside your source directory but a key difference is that shadow builds still do some work in your source directory during the build process while an out-of-source build does not. Here’s an example of an out-of-source build without the prefix flag.

If you run into errors during the config process, it’s likely due to missing dependancies. After the necessary googling and apt-installing, try running ~/Qt5/5.11.0/Src/configure --recheck-all to see if the issue has been resolved. If you’ve installed some potentially missing dependancies and you’re still seeing the same error, it may be a good idea to just wipe the destiantion directory and start over. I haven’t see any examples of this being necessary… but better to be over-cautious.

When everything finished properly, config should end with instructions to run make followed by make install. Go ahead and try this when you’re ready:

sudo make
sudo make install

Just because configure ran smooth, this doesn’t mean your out of the woods yet… The make step is where I ran into my wayland dependancy issues. In my case, I forgot to add -skip wayland in my configure and this messed up my make. Even after rerunning configure with the added option I was still getting the same dependancy errors during building. The problem was finally resolved when I wiped my build directory, redownloaded the source code and tried again. I could have saved myself a lot of hassle if I had just used out-of-source builds from the start and wiped my destination directory each time I had a make error. Wiping the destination directory is exactly what is sounds like and in this example just consists of:

sudo rm -R ~/Qt5/5.11.0_Static/

Finally… after a few hours and hopefully no errors, you’ve got a new version of Qt which allows you to run static builds.

Adding the Static Qt Compiler to Qt Creator

Now that you have a new version of Qt, you need to register it in Qt Creator. This process involves two simple steps:

  • Add the new static version of qmake to Qt Creator.
  • Create a new build kit which uses this new compiler.
  1. Go to Tools > Options > Build & Run > Qt Versions.

  2. Press Add and select the qmake binary we just built. In the case of this example, its located at: /home/james/Qt/5.11.0_Static/bin/qmake

Getting the source code

  1. To keep thing organized, modify the version name so you remember that this is the static version.

  2. Now, under the Kits tab, again press Add. Now you can make a new build kit which uses the static version of qmake.

Getting the source code

Running a Static Build

Now you’ve got everything setup, its time to build!

When building, just select that new static build kit we created and let qmake do the rest.

Building Apps

If all is well, your new compiled binary should be much larger that your previous dynamic builds. My 1.9MB binaries now turn into 20MB after using the static build kit. More importantly, now I can distribute apps without having to fully install Qt creater or spend days searching for missing dependancies.

Concluding Thoughts

  • I previously thought, due to seeing many examples including it, that you had to add the flag CONFIG += -static in your .pro file in addition to selecting a qmake binary build with the static flag… but apparently this isn’t the case.
  • If you are running into issues, I strongly reccomend posting on the Qt forums rather than other Q&A sites like stackoverflow. Responses were lightning fast and on point in my experience.