Categories
Uncategorised

Building Qt 6.2.4, Static Version, for GNU/Linux, Built on a Docker Container Running Ubuntu 18.04

Building software isn’t easy, and Qt can be especially tricky. I’ll go through the process that took days to get Qt built statically, that is, with static plugins and libraries, except for the runtime dependency on the GNU C runtime library (glibc), which warranted the use of a container running Ubuntu 18.04.

Compared to Windows 10, GNU/Linux is harder to build for because of the myriad of dependency requirements, and no guarantee that it will work on any distribution, so I’ve went with a widely used distribution which provide basic dependencies should be already there on most, namely, glibc. Building Qt for Windows 10 is made easier because the OS is not really as changeable, and because necessary components are bundled as source.

I found this page useful as a guide for picking a GNU/Linux flavor to build on: https://docs.linuxgsm.com/requirements/glibc. My aim was to pick a version that wasn’t too new, nor too old, to maximize compatibility.

It should be understood that due to the licensing requirements of Qt, those who statically link a program against Qt libraries will have to release the source code for their program, otherwise, to comply with the GNU Lesser General Public License, the LGPL, one should dynamically link to separate shared library files, if they wish the source code of their program to remain hidden. I’m OK with releasing the source code for my applications, and it’s assumed that you’re either willing to do so, or else, you’ll need to purchase a commercial license for Qt.

I started off with trying to build it on my host machine. I’m running Ubuntu 22.04, and it didn’t work for reasons I cannot quite recall. Besides, building for Ubuntu 22.04 isn’t a good base to build on to support a wider selection of GNU/Linux distributions because the version of glibc is too new. In fact, the developers of Steam at Valve Software, understand this, and have built their software on quite an older version of Ubuntu. I’m glad I went with 18.04, because the packages are not too old, except for the GNU C and C++ compilers, which I swapped for Clang.

I began working with a new container using the official image for Ubuntu 18.04, and then committed my changes to a new image. I attached a volume for the Qt source directory, and an installation directory in my home directory. Here’s my command line:

docker run -it -v ~/Qt/6.2.4/Src:/qt-6.2.4-src -v ~/qt6.2.4-static-build-ubuntu-18.04:/opt/qt-6.2.3-static-gcc64-linux ubuntu18.04-build-for-qt6 bash

Of course, I had to install packages needed for Qt’s GUI components, especially OpenGL, and, checking my list of installed packages in my container, I installed:

  • libgl1-mesa-dev
  • libgl1
  • libglapi-mesa
  • libglu1-mesa
  • libglu1-mesa-dev

Installing packages was a trial and error process, but at a minimum you should at least have installed what is listed here: https://doc.qt.io/qt-6/linux-requirements.html

These packages, especially those for OpenGL provide headers for symbols to be dynamically loaded, so on the target machine on which the statically linked application will run, will probably need the non-developer versions of the packages that were installed for building. To give an idea of what libraries need be present on the target system, here’s a listing from ldd for my test application:

  • linux-vdso.so.1
  • libdrm.so.2
  • libgbm.so.1
  • libudev.so.1
  • libjpeg.so.8
  • libtiff.so.5
  • libxcb-glx.so.0
  • libX11-xcb.so.1
  • libX11.so.6
  • libEGL.so.1
  • libGLX.so.0
  • libOpenGL.so.0
  • libpng16.so.16
  • libfreetype.so.6
  • libfontconfig.so.1
  • libdbus-1.so.3
  • libz.so.1
  • libglib-2.0.so.0
  • libxkbcommon.so.0
  • libxkbcommon-x11.so.0
  • libxcb-icccm.so.4
  • libxcb-image.so.0
  • libxcb-keysyms.so.1
  • libxcb-randr.so.0
  • libxcb-render-util.so.0
  • libxcb-shm.so.0
  • libxcb-sync.so.1
  • libxcb-xfixes.so.0
  • libxcb-render.so.0
  • libxcb-shape.so.0
  • libxcb-xkb.so.1
  • libxcb.so.1
  • libSM.so.6
  • libICE.so.6
  • libstdc++.so.6
  • libm.so.6
  • libgcc_s.so.1
  • libc.so.6
  • /lib64/ld-linux-x86-64.so.2
  • libwayland-server.so.0
  • libexpat.so.1
  • libwebp.so.7
  • libzstd.so.1
  • liblzma.so.5
  • libjbig.so.0
  • libdeflate.so.0
  • libGLdispatch.so.0
  • libbrotlidec.so.1
  • libuuid.so.1
  • libsystemd.so.0
  • libpcre.so.3
  • libxcb-util.so.1
  • libXau.so.6
  • libXdmcp.so.6
  • libbsd.so.0
  • libffi.so.8
  • libbrotlicommon.so.1
  • liblz4.so.1
  • libcap.so.2
  • libgcrypt.so.20
  • libmd.so.0
  • libgpg-error.so.0

I’ve changed my command line for configure many times, storing each version in a text file. Before re-configuring, it helps to delete existing CMakeCache.txt files:

for x in `find . -name CMakeCache.txt -print`; do
rm $x
done

Here’s the command line I’ve used to build Qt6 in the container (ignore the prefix, it’s my idiosyncrasy, possibly after doing it many times):

QMAKE_INCDIR_OPENGL=/usr/include/GL ./configure -bundled-xcb-xinput -opensource -confirm-license -nomake tests -nomake examples -static -no-icu -prefix "/opt/qt-6.2.3-static-gcc64-linux/" -- -DCMAKE_CXX_COMPILER=/usr/bin/clang++-10 -DCMAKE_C_COMPILER=/usr/bin/clang-10

After that I tried to use the installation prefix inside Qt creator, by adding as a kit, but this failed, so I either build my CMake project in Release mode with my Qt installation path for static linking, and for testing, I use Qt Creator with the same version of Qt but with shared libraries being used.

Lastly, I should add that I had trouble with mtdev, a library for multitouch device support, so in another round of building Qt, I added -no-mtdev to my command line and -no-icu:

QMAKE_INCDIR_OPENGL=/usr/include/GL ./configure -bundled-xcb-xinput -opensource -confirm-license -nomake tests -nomake examples -static -no-icu -no-mtdev -prefix "/opt/qt-6.2.3-static-gcc64-linux/" -- -DCMAKE_CXX_COMPILER=/usr/bin/clang++-10 -DCMAKE_C_COMPILER=/usr/bin/clang-10

So, now I’ve built it, I also tried it with an application I’m working on called ciphertools, and can confirm it works on my host machine running Ubuntu 22.04.

If someone wants my build, please let me know in the comments below. This took a few days, and I’m currently unemployed, but I really don’t mind giving back to the community.

Leave a Reply

Your email address will not be published.