For quite a long time statically built Qt was kind of a mystery to me. I always used dynamic builds and had lots of involuntary sexual intercourses with macdeployqt/windeployqt (perhaps I should write about this too).

But not anymore, because I finally overcame my fears/stupidity/laziness, RTFMed and managed to build Qt statically.

Qt configure

Why build Qt statically

There are 3 main reasons:

  1. Easier deployment;
  2. Smaller binaries size;
  3. Better security.

Deployment of dynamically linked Qt applications always was (is) not a trivial task. While everything works on your development machine, being deployed on another machine your applications most likely will complain about all sorts of missing libraries.

What I did in the past - I just copied the entire set of Qt libraries to the application directory and then application started working. But, first of all, copying just Qt libraries is not enough, there are some other libraries that need to be deployed along, and secondly, the final size of the deployed application can easily exceed a couple of hundreds of megabytes, which is not really okay even for desktop targets, not to say about embedded devices with quite a limited space available.

Having built your application statically linked, you get everything all-in-one - a single executable file which is very easy to deploy and it will have a smaller size comparing with its dynamically linked equivalent.

However, if your deployment target has several Qt-based applications, then static linking is not that attractive in terms of saving space, because in case of dynamic linking every Qt-based application can use the same set of shared Qt libraries, which you need to deploy only once. Here’s a simplified picture about it:

Qt static vs dynamic

As you can see, even though 1 statically linked application takes less space than 1 dynamically linked, but when you have 4 applications, then you can save more space on your disk by using dynamic linking: 620 - 220 = 400 MB of space saved. Not bad indeed, but again - this is just a simplified example, and real numbers probably won’t be that exciting.

Speaking about security - that one usually references to the fact that application relying on shared libraries is easier to hack (because you can replace libraries with the modified ones). But I am not sure if it’s really the case, because if shared libraries are exposed for hacking then it probably means that the whole OS is compromised, so there is no much point to fight the fire in the ashtray when entire building is on fire. And also as far as I know it is possible to sign shared libraries and perform checks before actually calling them.

About Open Source licenses compliance

Be aware, that if you are using Qt under LGPL, then using static linking might make it harder for you to comply with the license terms and keep your code private at the same time.

But if you are using Qt under GPL, then it doesn’t matter to you anyway as your code already belongs to community.

Please note, that I am not a lawyer, and this is just my interpretation of the license text, so don’t make business decisions based only on my comments - consult with a proper legal specialist.

How to build Qt statically

It is actually embarrassingly easy. You only need to run the configure utility with the right set of parameters.

I’ll describe the process for Mac OS (works like a charm), Linux (there are some tiny problems) and Windows (doesn’t fucking work lots of problems).

The first step is the same for all platforms: create a folder for shadow build and run configure command from there:

/path/to/qt/src/configure -static -release -ltcg -optimize-size -no-pch -prefix "/path/to/qt/510-static" -skip webengine -nomake tools -nomake tests -nomake examples

Here’s a description for the options I used:

  • -static - this one tells to build exactly a static version;
  • -release - because I need static build only for publishing my apps, therefore there is no need in static debug build, so it can be skipped. For debugging/profiling I’ll keep using dynamic build;
  • -ltcg - Link-Time Code Generation, optimizes something. I took it from here. I don’t recommend to use it on Windows (you’ll see later why);
  • -optimize-size - optimizes release builds for size instead of speed. I am after smaller builds, so;
  • -no-pch - no precompiled headers, meaning that all the header files (.h) will not be precompiled, so you’ll get all the benefits from #ifdef. Moreover, for some platforms Qt won’t even build with precompiled headers turned on;
  • -prefix "/path/to/qt/510-static" - where to put the result;
  • -skip webengine - I don’t need WebEngine;
  • -nomake tools - I don’t need static tools (Qt Creator, Designer, etc);
  • -nomake tests - I don’t need tests;
  • -nomake examples - I don’t need examples.

The set of options can differ from platform to platform. In my case it was the same for Mac and Linux, but for Windows I had to add two additional ones.

Full list of all possible options you can find in the documentation. Or you can get it from configure itself. Here’s an output from Qt 5.11.1 on Mac OS:

$ /path/to/qt/5.11.1/Src/configure -h
+ cd qtbase
+ /path/to/qt/5.11.1/Src/qtbase/configure -top-level -h
Usage:  configure [options] [assignments]

Configure understands variable assignments like VAR=value on the command line.
Each uppercased library name (obtainable with -list-libraries) supports the
suffixes _INCDIR, _LIBDIR, _PREFIX (INCDIR=PREFIX/include, LIBDIR=PREFIX/lib),
_LIBS, and - on Windows and Darwin - _LIBS_DEBUG and _LIBS_RELEASE. E.g.,
ICU_PREFIX=/opt/icu42 ICU_LIBS="-licui18n -licuuc -licudata".

It is also possible to manipulate any QMAKE_* variable, to amend the values
from the mkspec for the build of Qt itself, e.g., QMAKE_CXXFLAGS+=-g3.

Note that the *_LIBS* and QMAKE_* assignments manipulate lists, so items
containing meta characters (spaces in particular) need to be quoted according
to qmake rules. On top of that, the assignments as a whole need to be quoted
according to shell rules. It is recommended to use single quotes for the inner
quoting and double quotes for the outer quoting.

Top-level installation directories:
  -prefix <dir> ...... The deployment directory, as seen on the target device.
                       [/usr/local/Qt-$QT_VERSION, $PWD if -developer-build]
  -extprefix <dir> ... The installation directory, as seen on the host machine.
                       [SYSROOT/PREFIX]
  -hostprefix [dir] .. The installation directory for build tools running on
                       the host machine. If [dir] is not given, the current
                       build directory will be used. [EXTPREFIX]
  -external-hostbindir <path> ... Path to Qt tools built for this machine.
                       Use this when -platform does not match the current
                       system, i.e., to make a Canadian Cross Build.

Fine tuning of installation directory layout. Note that all directories
except -sysconfdir should be located under -prefix/-hostprefix:

  -bindir <dir> ......... Executables [PREFIX/bin]
  -headerdir <dir> ...... Header files [PREFIX/include]
  -libdir <dir> ......... Libraries [PREFIX/lib]
  -archdatadir <dir> .... Arch-dependent data [PREFIX]
  -plugindir <dir> ...... Plugins [ARCHDATADIR/plugins]
  -libexecdir <dir> ..... Helper programs [ARCHDATADIR/bin on Windows,
                          ARCHDATADIR/libexec otherwise]
  -importdir <dir> ...... QML1 imports [ARCHDATADIR/imports]
  -qmldir <dir> ......... QML2 imports [ARCHDATADIR/qml]
  -datadir <dir> ........ Arch-independent data [PREFIX]
  -docdir <dir> ......... Documentation [DATADIR/doc]
  -translationdir <dir> . Translations [DATADIR/translations]
  -sysconfdir <dir> ..... Settings used by Qt programs [PREFIX/etc/xdg]
  -examplesdir <dir> .... Examples [PREFIX/examples]
  -testsdir <dir> ....... Tests [PREFIX/tests]

  -hostbindir <dir> ..... Host executables [HOSTPREFIX/bin]
  -hostlibdir <dir> ..... Host libraries [HOSTPREFIX/lib]
  -hostdatadir <dir> .... Data used by qmake [HOSTPREFIX]

Conventions for the remaining options: When an option's description is
followed by a list of values in brackets, the interpretation is as follows:
'yes' represents the bare option; all other values are possible prefixes to
the option, e.g., -no-gui. Alternatively, the value can be assigned, e.g.,
--gui=yes. Values are listed in the order they are tried if not specified;
'auto' is a shorthand for 'yes/no'. Solitary 'yes' and 'no' represent binary
options without auto-detection.

Configure meta:

  -help, -h ............ Display this help screen
  -verbose, -v ......... Print verbose messages during configuration
  -continue ............ Continue configure despite errors
  -redo ................ Re-configure with previously used options.
                         Additional options may be passed, but will not be
                         saved for later use by -redo.
  -recheck [test,...] .. Discard cached negative configure test results.
                         Use this after installing missing dependencies.
                         Alternatively, if tests are specified, only their
                         results are discarded.
  -recheck-all ......... Discard all cached configure test results.

  -feature-<feature> ... Enable <feature>
  -no-feature-<feature>  Disable <feature> [none]
  -list-features ....... List available features. Note that some features
                         have dedicated command line options as well.

  -list-libraries ...... List possible external dependencies.

Build options:

  -opensource .......... Build the Open-Source Edition of Qt
  -commercial .......... Build the Commercial Edition of Qt
  -confirm-license ..... Automatically acknowledge the license

  -release ............. Build Qt with debugging turned off [yes]
  -debug ............... Build Qt with debugging turned on [no]
  -debug-and-release ... Build two versions of Qt, with and without
                         debugging turned on [yes] (Apple and Windows only)
  -optimize-debug ...... Enable debug-friendly optimizations in debug builds
                         [auto] (Not supported with MSVC or Clang toolchains)
  -optimize-size ....... Optimize release builds for size instead of speed [no]
  -optimized-tools ..... Build optimized host tools even in debug build [no]
  -force-debug-info .... Create symbol files for release builds [no]
  -separate-debug-info . Split off debug information to separate files [no]
  -gdb-index ........... Index the debug info to speed up GDB
                         [no; auto if -developer-build with debug info]
  -strip ............... Strip release binaries of unneeded symbols [yes]
  -force-asserts ....... Enable Q_ASSERT even in release builds [no]
  -developer-build ..... Compile and link Qt for developing Qt itself
                         (exports for auto-tests, extra checks, etc.) [no]

  -shared .............. Build shared Qt libraries [yes] (no for UIKit)
  -static .............. Build static Qt libraries [no] (yes for UIKit)
  -framework ........... Build Qt framework bundles [yes] (Apple only)

  -platform <target> ... Select host mkspec [detected]
  -xplatform <target> .. Select target mkspec when cross-compiling [PLATFORM]
  -device <name> ....... Cross-compile for device <name>
  -device-option <key=value> ... Add option for the device mkspec

  -appstore-compliant .. Disable code that is not allowed in platform app stores.
                         This is on by default for platforms which require distribution
                         through an app store by default, in particular Android,
                         iOS, tvOS, watchOS, and Universal Windows Platform. [auto]

  -qtnamespace <name> .. Wrap all Qt library code in 'namespace <name> {...}'.
  -qtlibinfix <infix> .. Rename all libQt5*.so to libQt5*<infix>.so.

  -testcocoon .......... Instrument with the TestCocoon code coverage tool [no]
  -gcov ................ Instrument with the GCov code coverage tool [no]

  -trace [backend] ..... Enable instrumentation with tracepoints.
                         Currently supported backends are 'etw' (Windows) and
                         'lttng' (Linux), or 'yes' for auto-detection. [no]

  -sanitize {address|thread|memory|undefined}
                         Instrument with the specified compiler sanitizer.
                         Note that some sanitizers cannot be combined;
                         for example, -sanitize address cannot be combined with
                         -sanitize thread.

  -c++std <edition> .... Select C++ standard <edition> [c++1z/c++14/c++11]
                         (Not supported with MSVC)

  -sse2 ................ Use SSE2 instructions [auto]
  -sse3/-ssse3/-sse4.1/-sse4.2/-avx/-avx2/-avx512
                         Enable use of particular x86 instructions [auto]
                         Enabled ones are still subject to runtime detection.
  -mips_dsp/-mips_dspr2  Use MIPS DSP/rev2 instructions [auto]

  -qreal <type> ........ typedef qreal to the specified type. [double]
                         Note: this affects binary compatibility.

  -R <string> .......... Add an explicit runtime library path to the Qt
                         libraries. Supports paths relative to LIBDIR.
  -rpath ............... Link Qt libraries and executables using the library
                         install path as a runtime library path. Similar to
                         -R LIBDIR. On Apple platforms, disabling this implies
                         using absolute install names (based in LIBDIR) for
                         dynamic libraries and frameworks. [auto]

  -reduce-exports ...... Reduce amount of exported symbols [auto]
  -reduce-relocations .. Reduce amount of relocations [auto] (Unix only)

  -plugin-manifests .... Embed manifests into plugins [no] (Windows only)
  -static-runtime ...... With -static, use static runtime [no] (Windows only)

  -pch ................. Use precompiled headers [auto]
  -ltcg ................ Use Link Time Code Generation [no]
  -use-gold-linker ..... Use the GNU gold linker [auto]
  -incredibuild-xge .... Use the IncrediBuild XGE [no] (Windows only)
  -ccache .............. Use the ccache compiler cache [no] (Unix only)
  -make-tool <tool> .... Use <tool> to build qmake [nmake] (Windows only)
  -mp .................. Use multiple processors for compilation (MSVC only)

  -warnings-are-errors . Treat warnings as errors [no; yes if -developer-build]
  -silent .............. Reduce the build output so that warnings and errors
                         can be seen more easily

Build environment:

  -sysroot <dir> ....... Set <dir> as the target sysroot
  -gcc-sysroot ......... With -sysroot, pass --sysroot to the compiler [yes]

  -pkg-config .......... Use pkg-config [auto] (Unix only)

  -D <string> .......... Pass additional preprocessor define
  -I <string> .......... Pass additional include path
  -L <string> .......... Pass additional library path
  -F <string> .......... Pass additional framework path (Apple only)

  -sdk <sdk> ........... Build Qt using Apple provided SDK <sdk>. The argument
                         should be one of the available SDKs as listed by
                         'xcodebuild -showsdks'.
                         Note that the argument applies only to Qt libraries
                         and applications built using the target mkspec - not
                         host tools such as qmake, moc, rcc, etc.

  -android-sdk path .... Set Android SDK root path [$ANDROID_SDK_ROOT]
  -android-ndk path .... Set Android NDK root path [$ANDROID_NDK_ROOT]
  -android-ndk-platform  Set Android platform
  -android-ndk-host .... Set Android NDK host (linux-x86, linux-x86_64, etc.)
                         [$ANDROID_NDK_HOST]
  -android-arch ........ Set Android architecture (armeabi, armeabi-v7a,
                         arm64-v8a, x86, x86_64, mips, mips64)
  -android-toolchain-version ... Set Android toolchain version
  -android-style-assets  Automatically extract style assets from the device at
                         run time. This option makes the Android style behave
                         correctly, but also makes the Android platform plugin
                         incompatible with the LGPL2.1. [yes]

Component selection:

  -skip <repo> ......... Exclude an entire repository from the build.
  -make <part> ......... Add <part> to the list of parts to be built.
                         Specifying this option clears the default list first.
                         [libs and examples, also tools if not cross-building,
                         also tests if -developer-build]
  -nomake <part> ....... Exclude <part> from the list of parts to be built.
  -compile-examples .... When unset, install only the sources of examples [yes]
  -gui ................. Build the Qt GUI module and dependencies [yes]
  -widgets ............. Build the Qt Widgets module and dependencies [yes]
  -no-dbus ............. Do not build the Qt D-Bus module
                         [default on Android and Windows]
  -dbus-linked ......... Build Qt D-Bus and link to libdbus-1 [auto]
  -dbus-runtime ........ Build Qt D-Bus and dynamically load libdbus-1 [no]
  -accessibility ....... Enable accessibility support [yes]
                         Note: Disabling accessibility is not recommended.

Qt comes with bundled copies of some 3rd party libraries. These are used
by default if auto-detection of the respective system library fails.

Core options:

  -doubleconversion .... Select used double conversion library [system/qt/no]
                         No implies use of sscanf_l and snprintf_l (imprecise).
  -glib ................ Enable Glib support [no; auto on Unix]
  -eventfd ............. Enable eventfd support
  -inotify ............. Enable inotify support
  -iconv ............... Enable iconv(3) support [posix/sun/gnu/no] (Unix only)
  -icu ................. Enable ICU support [auto]
  -pcre ................ Select used libpcre2 [system/qt]
  -pps ................. Enable PPS support [auto] (QNX only)
  -zlib ................ Select used zlib [system/qt]

  Logging backends:
    -journald .......... Enable journald support [no] (Unix only)
    -syslog ............ Enable syslog support [no] (Unix only)
    -slog2 ............. Enable slog2 support [auto] (QNX only)

Network options:

  -ssl ................. Enable either SSL support method [auto]
  -no-openssl .......... Do not use OpenSSL [default on Apple and WinRT]
  -openssl-linked ...... Use OpenSSL and link to libssl [no]
  -openssl-runtime ..... Use OpenSSL and dynamically load libssl [auto]
  -securetransport ..... Use SecureTransport [auto] (Apple only)

  -sctp ................ Enable SCTP support [no]

  -libproxy ............ Enable use of libproxy [no]
  -system-proxies ...... Use system network proxies by default [yes]

Gui, printing, widget options:

  -cups ................ Enable CUPS support [auto] (Unix only)

  -fontconfig .......... Enable Fontconfig support [auto] (Unix only)
  -freetype ............ Select used FreeType [system/qt/no]
  -harfbuzz ............ Select used HarfBuzz-NG [system/qt/no]
                         (Not auto-detected on Apple and Windows)

  -gtk ................. Enable GTK platform theme support [auto]

  -lgmon ............... Enable lgmon support [auto] (QNX only)

  -no-opengl ........... Disable OpenGL support
  -opengl <api> ........ Enable OpenGL support. Supported APIs:
                         es2 (default on Windows), desktop (default on Unix),
                         dynamic (Windows only)
  -opengles3 ........... Enable OpenGL ES 3.x support instead of ES 2.x [auto]
  -angle ............... Use bundled ANGLE to support OpenGL ES 2.0 [auto]
                         (Windows only)
  -combined-angle-lib .. Merge LibEGL and LibGLESv2 into LibANGLE (Windows only)

  -qpa <name> .......... Select default QPA backend(s) (e.g., xcb, cocoa, windows)
                         A prioritized list separated by semi-colons.
  -xcb-xlib............. Enable Xcb-Xlib support [auto]

  Platform backends:
    -direct2d .......... Enable Direct2D support [auto] (Windows only)
    -directfb .......... Enable DirectFB support [no] (Unix only)
    -eglfs ............. Enable EGLFS support [auto; no on Android and Windows]
    -gbm ............... Enable backends for GBM [auto] (Linux only)
    -kms ............... Enable backends for KMS [auto] (Linux only)
    -linuxfb ........... Enable Linux Framebuffer support [auto] (Linux only)
    -mirclient ......... Enable Mir client support [no] (Linux only)
    -xcb ............... Select used xcb-* libraries [system/qt/no]
                         (-qt-xcb still uses system version of libxcb itself)

  Input backends:
    -libudev............ Enable udev support [auto]
    -evdev ............. Enable evdev support [auto]
    -imf ............... Enable IMF support [auto] (QNX only)
    -libinput .......... Enable libinput support [auto]
    -mtdev ............. Enable mtdev support [auto]
    -tslib ............. Enable tslib support [auto]
    -xinput2 ........... Enable XInput2 support [auto]
    -xkbcommon-x11 ..... Select xkbcommon used in combination with xcb
                         [system/qt/no]
    -xkbcommon-evdev ... Enable X-less xkbcommon in combination with libinput
                         [auto]

  Image formats:
    -gif ............... Enable reading support for GIF [auto]
    -ico ............... Enable support for ICO [yes]
    -libpng ............ Select used libpng [system/qt/no]
    -libjpeg ........... Select used libjpeg [system/qt/no]

Database options:

  -sql-<driver> ........ Enable SQL <driver> plugin. Supported drivers:
                         db2 ibase mysql oci odbc psql sqlite2 sqlite tds
                         [all auto]
  -sqlite .............. Select used sqlite3 [system/qt]

Qt3D options:

  -assimp .............. Select used assimp library [system/qt/no]
  -qt3d-profile-jobs ... Enable jobs profiling [no]
  -qt3d-profile-gl ..... Enable OpenGL profiling [no]
  -qt3d-simd ........... Select level of SIMD support [no/sse2/avx2]
  -qt3d-render ......... Enable the Qt3D Render aspect [yes]
  -qt3d-input .......... Enable the Qt3D Input aspect [yes]
  -qt3d-logic .......... Enable the Qt3D Logic aspect [yes]
  -qt3d-extras ......... Enable the Qt3D Extras aspect [yes]
  -qt3d-animation....... Enable the Qt3D Animation aspect [yes]

Multimedia options:

  -pulseaudio .......... Enable PulseAudio support [auto] (Unix only)
  -alsa ................ Enable ALSA support [auto] (Unix only)
  -no-gstreamer ........ Disable support for GStreamer
  -gstreamer [version] . Enable GStreamer support [auto]
                         With no parameter, 1.0 is tried first, then 0.10.
  -mediaplayer-backend <name> ... Select media player backend (Windows only)
                                  Supported backends: directshow (default), wmf

Webengine options:
  -webengine-alsa ................ Enable ALSA support [auto] (Linux only)
  -webengine-pulseaudio .......... Enable PulseAudio support [auto]
                                   (Linux only)
  -webengine-embedded-build ...... Enable Linux embedded build [auto]
                                   (Linux only)
  -webengine-icu ................. Use system ICU libraries [system/qt]
                                   (Linux only)
  -webengine-ffmpeg .............. Use system FFmpeg libraries [system/qt]
                                   (Linux only)
  -webengine-opus ................ Use system Opus libraries [system/qt]
                                   (Linux only)
  -webengine-webp ................ Use system WebP libraries [system/qt]
                                   (Linux only)
  -webengine-pepper-plugins ...... Enable use of Pepper Flash and Widevine
                                   plugins [auto]
  -webengine-printing-and-pdf .... Enable use of printing and output to PDF
                                   [auto]
  -webengine-proprietary-codecs .. Enable support for proprietary codecs [no]
  -webengine-spellchecker ........ Enable support for spellchecker [yes]
  -webengine-native-spellchecker . Enable support for native spellchecker [no]
                                   (macOS only)
  -webengine-webrtc .............. Enable support for WebRTC [auto]

Core options section refers to 3rd-party libraries, and quite often I see in different places people putting options like -qt-zlib, -qt-libpng and so on for configure. Although, if you won’t set them, it doesn’t mean that you won’t have those libraries in your build - they just will be included with default values: some with Qt implementations and some with system ones. You can check which ones exactly are set in the configure summary output (after you run it).

Also note, that if you built Qt in past, then you should clean out the old build first:

make -j8 distclean

In case of shadow build it is enough to simply delete the “shadow” folder (and the one you’ve set with -prefix).

Mac OS

So, you ran configure and now it asks you which edition you would like to build and also if you accept the license (these two are also available as options for configure):

Creating qmake...
.Done.

Selecting Qt Edition.

Type 'c' if you want to use the Commercial Edition.
Type 'o' if you want to use the Open Source Edition.

Which edition of Qt do you want to use? c
This is the Qt Enterprise Edition.

You are licensed to use this software under the terms of following license(s):
Qt Enterprise License Agreement

Type '?' to view the license offer.
Type 'y' to accept this license offer.
Type 'n' to decline this license offer.

Do you accept the terms of the license(s)?
y

After that it will generate configuration summary and perform some checks:

Running configuration tests...
Done running configuration tests.

Configure summary:

Build type: macx-clang (x86_64, CPU features: cx16 mmx sse sse2 sse3 ssse3)
Configuration: sse2 aesni sse3 ssse3 sse4_1 sse4_2 avx avx2 avx512f avx512bw avx512cd avx512dq avx512er avx512ifma avx512pf avx512vbmi avx512vl compile_examples f16c largefile ltcg optimize_size rdrnd shani release c++11 c++14 c++1z concurrent dbus no-pkg-config reduce_exports static stl
Build options:
  Mode ................................... release
  Optimize release build for size ........ yes
  Building shared libraries .............. no
  Using C++ standard ..................... C++1z
  Using ccache ........................... no
  Using gold linker ...................... no
  Using precompiled headers .............. no
  Using LTCG ............................. yes
  Target compiler supports:
    SSE .................................. SSE2 SSE3 SSSE3 SSE4.1 SSE4.2
    AVX .................................. AVX AVX2
    AVX512 ............................... F ER CD PF DQ BW VL IFMA VBMI
    Other x86 ............................ AES F16C RDRAND SHA
  Build parts ............................ libs
  App store compliance ................... no
Qt modules and options:
  Qt Concurrent .......................... yes
  Qt D-Bus ............................... yes
  Qt D-Bus directly linked to libdbus .... no
  Qt Gui ................................. yes
  Qt Network ............................. yes
  Qt Sql ................................. yes
  Qt Testlib ............................. yes
  Qt Widgets ............................. yes
  Qt Xml ................................. yes
Support enabled for:
  Using pkg-config ....................... no
  QML debugging .......................... yes
  udev ................................... no
  Using system zlib ...................... yes
Qt Core:
  DoubleConversion ....................... yes
    Using system DoubleConversion ........ no
  GLib ................................... no
  iconv .................................. no
  ICU .................................... no
  Logging backends:
    journald ............................. no
    syslog ............................... no
    slog2 ................................ no
  Using system PCRE2 ..................... no
Qt Network:
  CoreWLan ............................... yes
  getifaddrs() ........................... yes
  IPv6 ifname ............................ yes
  libproxy ............................... no
  SecureTransport ........................ yes
  OpenSSL ................................ no
    Qt directly linked to OpenSSL ........ no
  SCTP ................................... no
  Use system proxies ..................... yes
Qt Gui:
  Accessibility .......................... yes
  FreeType ............................... yes
    Using system FreeType ................ no
  HarfBuzz ............................... yes
    Using system HarfBuzz ................ no
  Fontconfig ............................. no
  Image formats:
    GIF .................................. yes
    ICO .................................. yes
    JPEG ................................. yes
      Using system libjpeg ............... no
    PNG .................................. yes
      Using system libpng ................ no
  EGL .................................... no
  OpenVG ................................. no
  OpenGL:
    Desktop OpenGL ....................... yes
    OpenGL ES 2.0 ........................ no
    OpenGL ES 3.0 ........................ no
    OpenGL ES 3.1 ........................ no
    OpenGL ES 3.2 ........................ no
  Vulkan ................................. no
  Session Management ..................... yes
Features used by QPA backends:
  evdev .................................. no
  libinput ............................... no
  INTEGRITY HID .......................... no
  mtdev .................................. no
  tslib .................................. no
  xkbcommon-evdev ........................ no
QPA backends:
  DirectFB ............................... no
  EGLFS .................................. no
  LinuxFB ................................ no
  VNC .................................... no
  Mir client ............................. no
Qt Widgets:
  GTK+ ................................... no
  Styles ................................. Fusion macOS Windows
Qt PrintSupport:
  CUPS ................................... yes
Qt Sql:
  DB2 (IBM) .............................. no
  InterBase .............................. no
  MySql .................................. no
  OCI (Oracle) ........................... no
  ODBC ................................... no
  PostgreSQL ............................. no
  SQLite2 ................................ no
  SQLite ................................. yes
    Using system provided SQLite ......... no
  TDS (Sybase) ........................... no
Qt SerialBus:
  Socket CAN ............................. no
  Socket CAN FD .......................... no
QtXmlPatterns:
  XML schema support ..................... yes
Qt QML:
  QML interpreter ........................ yes
  QML network support .................... yes
Qt Quick:
  Direct3D 12 ............................ no
  AnimatedImage item ..................... yes
  Canvas item ............................ yes
  Support for Qt Quick Designer .......... yes
  Flipable item .......................... yes
  GridView item .......................... yes
  ListView item .......................... yes
  Path support ........................... yes
  PathView item .......................... yes
  Positioner items ....................... yes
  ShaderEffect item ...................... yes
  Sprite item ............................ yes
Qt Gamepad:
  SDL2 ................................... no
Qt 3D:
  Assimp ................................. yes
  System Assimp .......................... no
  Output Qt3D Job traces ................. no
  Output Qt3D GL traces .................. no
  Use SSE2 instructions .................. yes
  Use AVX2 instructions .................. no
  Aspects:
    Render aspect ........................ yes
    Input aspect ......................... yes
    Logic aspect ......................... yes
    Animation aspect ..................... yes
    Extras aspect ........................ yes
Qt 3D GeometryLoaders:
  Autodesk FBX ........................... no
Qt Wayland Client ........................ no
Qt Wayland Compositor .................... no
Qt Bluetooth:
  BlueZ .................................. no
  BlueZ Low Energy ....................... no
  Linux Crypto API ....................... no
  WinRT Bluetooth API (desktop & UWP) .... no
Qt Sensors:
  sensorfw ............................... no
Qt Quick Controls 2:
  Styles ................................. Default Fusion Imagine Material Universal
Qt Quick Templates 2:
  Hover support .......................... yes
  Multi-touch support .................... yes
Qt Positioning:
  Gypsy GPS Daemon ....................... no
  WinRT Geolocation API .................. no
Qt Location:
  Geoservice plugins:
    OpenStreetMap ........................ yes
    HERE ................................. yes
    Esri ................................. yes
    Mapbox ............................... yes
    MapboxGL ............................. yes
    Itemsoverlay ......................... yes
Qt Multimedia:
  ALSA ................................... no
  GStreamer 1.0 .......................... no
  GStreamer 0.10 ......................... no
  Video for Linux ........................ no
  OpenAL ................................. yes
  PulseAudio ............................. no
  Resource Policy (libresourceqt5) ....... no
  AVFoundation ........................... yes
  Windows Audio Services ................. no
  DirectShow ............................. no
  Windows Media Foundation ............... no

Note: Using static linking will disable the use of dynamically
loaded plugins. Make sure to import all needed static plugins,
or compile needed modules into the library.

Note: No wayland-egl support detected. Cross-toolkit compatibility disabled.

Qt is now configured for building. Just run 'make'.
Once everything is built, you must run 'make install'.
Qt will be installed into '/path/to/qt/510-static'.

Prior to reconfiguration, make sure you remove any leftovers from
the previous build.

Now you need to actually build it. It is done by running make command, and it is important to note that it will be doing it for ages, because by default it doesn’t parallelize the process. So, if you, like me, have 8 cores in your CPU (4 physical and 4 logical), you can run it like that:

make -j8

With -j8 provided, it took 32 minutes to build Qt statically on my MacBookPro with 2.8 GHz Intel Core i7.

However, if there will be any error, the only output you’ll get will be:

make[1]: *** [sub-src-make_first] Error 2
make: *** [module-qtbase-make_first] Error 2

And to see the errors you’ll have to run make without -j8.

Last step is to “install” your new static Qt:

make -j8 install

That will take couple more minutes, and then you can go to /path/to/qt/510-static to see the result.

Linux

All the same as for Mac OS, but I encountered 2 problems.

First one was missing g++, which is fixed by installing build tools:

apt-get install build-essential

Second one was this:

ERROR The OpenGL functionality tests failed

Which is fixed by installing Mesa libraries:

apt-get install libgl1-mesa-dev

And actually documentation says about that, but I didn’t notice at first.

Note here, that even after you install the missing stuff, configure won’t know about it, because it performs all the checks only once, and after that it relies on the generated config.cache, so every time you change something - delete config.cache before launching configure again.

I have Linux on Lenovo T540p laptop with 2.5 GHz Intel Core i7, and there it takes 43 minutes (with make -j8) to built Qt statically.

After executing the last step (make -j8 install) you will get your static Qt in the folder specified with prefix parameter.

Windows

I was trying to build Qt on Windows from time to time, and usually it fails, but sometimes it actually does build.

Qt 5.10.1, Windows 10 and MinGW x32

I have Windows 10 running on the same Lenovo laptop, and there I use Qt (d:\Programs\Qt) with MinGW (you should have \path\to\Qt\Tools\mingw530_32\bin in your PATH).

First I tried to do it with Qt 5.10, but it failed with some error about dummy platforms. I wanted to investigate that, but then suddenly Qt 5.10.1 was released, so I tried with this version and this time it didn’t give me that error.

But I got another error anyway, and it was about OpenGL:

WARNING: Using OpenGL ES 2.0 on Windows without ANGLE.
The build will most likely fail.
Specify -opengl desktop to use regular OpenGL.

So I added -opengl desktop to the list of configure options. In addition to that, in some article I read about the option -platform win32-g++, which apparently would have fixed the dummy platform error. So, the final command line now looks like this:

configure.bat -release -static -ltcg -no-pch -optimize-size -opengl desktop -platform win32-g++ -prefix "\path\to\Qt\510-static" -skip webengine -nomake tools -nomake tests -nomake examples

I executed it and after a while (like, 10 times slower than on Linux) I got the following output:

Running configuration tests...
Checking for valid makespec... yes
Checking for target architecture... i386
Checking for SSE2 instructions... yes
Checking for AES new instructions... yes
Checking for alloca() in alloca.h... no
Checking for alloca() in malloc.h... yes
Checking for SSE3 instructions... yes
Checking for SSSE3 instructions... yes
Checking for SSE4.1 instructions... yes
Checking for SSE4.2 instructions... yes
Checking for AVX instructions... yes
Checking for AVX2 instructions... yes
Checking for AVX512 F instructions... yes
Checking for AVX512 BW instructions... yes
Checking for AVX512 CD instructions... yes
Checking for AVX512 DQ instructions... yes
Checking for AVX512 ER instructions... yes
Checking for AVX512 IFMA instructions... yes
Checking for AVX512 PF instructions... yes
Checking for AVX512 VBMI instructions... yes
Checking for AVX512 VL instructions... yes
Checking for C++14 support... yes
Checking for C++1z support... yes
Checking for D-Bus >= 1.2... no
Checking for F16C instructions... yes
Checking for D-Bus >= 1.2 (host)... yes
Checking for IncrediBuild... no
Checking for udev... no
Checking for POSIX fallocate()... no
Checking for RDRAND instruction... yes
Checking for SHA new instructions... yes
Checking for STL compatibility... yes
Checking for zlib... yes
Checking for C++11 <future>... yes
Checking for eventfd... no
Checking for inotify... no
Checking for slog2... no
Checking for 64 bit atomics... yes
Checking for DoubleConversion... no
Checking for PCRE2... no
Checking for O_CLOEXEC... no
Checking for C++11 <random>... yes
Checking for working std::atomic for function pointers... yes
Checking for getifaddrs()... no
Checking for IPv6 ifname... no
Checking for OpenSSL Headers... no
Checking for OpenSSL v. 1.1 support... no
Checking for XCB >= 1.5 (core)... no
Checking for Direct 2D... no
Checking for DirectWrite... yes
Checking for DirectWrite 2... no
Checking for Desktop OpenGL... yes
Checking for EGL... no
Checking for evdev... no
Checking for GBM... no
Checking for KMS... no
Checking for LinuxFB... no
Checking for mtdev... no
Checking for OpenVG... no
Checking for default QPA platform... windows
Checking for libjpeg... no
Checking for libpng... no
Checking for tslib... no
Checking for Vulkan... no
Checking for xkbcommon... no
Checking for XLib... no
Checking for uxtheme.h... yes
Checking for CUPS... no
Checking for DB2 (IBM)... no
Checking for InterBase... no
Checking for MySQL... no
Checking for OCI (Oracle)... no
Checking for ODBC... yes
Checking for PostgreSQL... no
Checking for SQLite (version 2)... no
Checking for TDS (Sybase)... no
Checking for Direct3D 12... no
Checking for SDL2... no
Checking for Assimp... no
Checking for Autodesk FBX... no
Checking for Wayland EGL library... no
Checking for BlueZ... no
Checking for WinRT Bluetooth API... no
Checking for sensorfw... no
Checking for Gypsy... no
Checking for WinRT Geolocation API... no
Checking for DirectShow... yes
Checking for evr.h... yes
Checking for GStreamer 1.0... no
Checking for GStreamer 0.10... no
Checking for OpenAL... no
Checking for libresourceqt5... no
Checking for Windows Audio Services... no
Checking for WMF... no
Checking for wmsdk.h... no
Checking for WShellItem... yes
Done running configuration tests.

Configure summary:

Build type: win32-g++ (i386, CPU features: <none>)
Configuration: sse2 aesni sse3 ssse3 sse4_1 sse4_2 avx avx2 avx512f avx512bw avx512cd avx512dq avx512er avx512ifma avx512pf avx512vbmi avx512vl compile_examples f16c largefile ltcg optimize_size rdrnd shani release c++11 c++14 c++1z concurrent dbus no-pkg-config static stl
Build options:
  Mode ................................... release
  Optimize release build for size ........ yes
  Building shared libraries .............. no
  Using C++ standard ..................... C++1z
  Using gold linker ...................... no
  Using precompiled headers .............. no
  Using LTCG ............................. yes
  Target compiler supports:
    SSE .................................. SSE2 SSE3 SSSE3 SSE4.1 SSE4.2
    AVX .................................. AVX AVX2
    AVX512 ............................... F ER CD PF DQ BW VL IFMA VBMI
    Other x86 ............................ AES F16C RDRAND SHA
  Build parts ............................ libs
  App store compliance ................... no
Qt modules and options:
  Qt Concurrent .......................... yes
  Qt D-Bus ............................... yes
  Qt D-Bus directly linked to libdbus .... no
  Qt Gui ................................. yes
  Qt Network ............................. yes
  Qt Sql ................................. yes
  Qt Testlib ............................. yes
  Qt Widgets ............................. yes
  Qt Xml ................................. yes
Support enabled for:
  Using pkg-config ....................... no
  QML debugging .......................... yes
  udev ................................... no
  Using system zlib ...................... yes
Qt Core:
  DoubleConversion ....................... yes
    Using system DoubleConversion ........ no
  GLib ................................... no
  iconv .................................. no
  ICU .................................... no
  Logging backends:
    journald ............................. no
    syslog ............................... no
    slog2 ................................ no
  Using system PCRE2 ..................... no
Qt Network:
  getifaddrs() ........................... no
  IPv6 ifname ............................ no
  libproxy ............................... no
  OpenSSL ................................ no
    Qt directly linked to OpenSSL ........ no
  SCTP ................................... no
  Use system proxies ..................... yes
Qt Gui:
  Accessibility .......................... yes
  FreeType ............................... yes
    Using system FreeType ................ no
  HarfBuzz ............................... yes
    Using system HarfBuzz ................ no
  Fontconfig ............................. no
  Image formats:
    GIF .................................. yes
    ICO .................................. yes
    JPEG ................................. yes
      Using system libjpeg ............... no
    PNG .................................. yes
      Using system libpng ................ no
  EGL .................................... no
  OpenVG ................................. no
  OpenGL:
    ANGLE ................................ no
    Desktop OpenGL ....................... yes
    Dynamic OpenGL ....................... no
    OpenGL ES 2.0 ........................ no
    OpenGL ES 3.0 ........................ no
    OpenGL ES 3.1 ........................ no
    OpenGL ES 3.2 ........................ no
  Vulkan ................................. no
  Session Management ..................... yes
Features used by QPA backends:
  evdev .................................. no
  libinput ............................... no
  INTEGRITY HID .......................... no
  mtdev .................................. no
  tslib .................................. no
  xkbcommon-evdev ........................ no
QPA backends:
  DirectFB ............................... no
  EGLFS .................................. no
  LinuxFB ................................ no
  VNC .................................... no
  Mir client ............................. no
  Windows:
    Direct 2D ............................ no
    DirectWrite .......................... yes
    DirectWrite 2 ........................ no
Qt Widgets:
  GTK+ ................................... no
  Styles ................................. Fusion Windows WindowsVista
Qt PrintSupport:
  CUPS ................................... no
Qt Sql:
  DB2 (IBM) .............................. no
  InterBase .............................. no
  MySql .................................. no
  OCI (Oracle) ........................... no
  ODBC ................................... yes
  PostgreSQL ............................. no
  SQLite2 ................................ no
  SQLite ................................. yes
    Using system provided SQLite ......... no
  TDS (Sybase) ........................... no
Qt SerialBus:
  Socket CAN ............................. no
  Socket CAN FD .......................... no
QtXmlPatterns:
  XML schema support ..................... yes
Qt QML:
  QML interpreter ........................ yes
  QML network support .................... yes
Qt Quick:
  Direct3D 12 ............................ no
  AnimatedImage item ..................... yes
  Canvas item ............................ yes
  Support for Qt Quick Designer .......... yes
  Flipable item .......................... yes
  GridView item .......................... yes
  ListView item .......................... yes
  Path support ........................... yes
  PathView item .......................... yes
  Positioner items ....................... yes
  ShaderEffect item ...................... yes
  Sprite item ............................ yes
Qt Gamepad:
  SDL2 ................................... no
Qt 3D:
  Assimp ................................. yes
  System Assimp .......................... no
  Output Qt3D Job traces ................. no
  Output Qt3D GL traces .................. no
  Use SSE2 instructions .................. no
  Use AVX2 instructions .................. no
  Aspects:
    Render aspect ........................ yes
    Input aspect ......................... yes
    Logic aspect ......................... yes
    Animation aspect ..................... yes
    Extras aspect ........................ yes
Qt 3D GeometryLoaders:
  Autodesk FBX ........................... no
Qt Wayland Client ........................ no
Qt Wayland Compositor .................... no
Qt Bluetooth:
  BlueZ .................................. no
  BlueZ Low Energy ....................... no
  Linux Crypto API ....................... no
  WinRT Bluetooth API (desktop & UWP) .... no
Qt Sensors:
  sensorfw ............................... no
Qt Quick Controls 2:
  Styles ................................. Default Fusion Imagine Material Universal
Qt Quick Templates 2:
  Hover support .......................... yes
  Multi-touch support .................... yes
Qt Positioning:
  Gypsy GPS Daemon ....................... no
  WinRT Geolocation API .................. no
Qt Location:
  Geoservice plugins:
    OpenStreetMap ........................ yes
    HERE ................................. yes
    Esri ................................. yes
    Mapbox ............................... yes
    MapboxGL ............................. yes
    Itemsoverlay ......................... yes
Qt Multimedia:
  ALSA ................................... no
  GStreamer 1.0 .......................... no
  GStreamer 0.10 ......................... no
  Video for Linux ........................ no
  OpenAL ................................. no
  PulseAudio ............................. no
  Resource Policy (libresourceqt5) ....... no
  Windows Audio Services ................. no
  DirectShow ............................. yes
  Windows Media Foundation ............... no
  Media player backend ................... DirectShow

Note: Using static linking will disable the use of dynamically
loaded plugins. Make sure to import all needed static plugins,
or compile needed modules into the library.

Note: No wayland-egl support detected. Cross-toolkit compatibility disabled.

Qt is now configured for building. Just run 'mingw32-make'.
Once everything is built, you must run 'mingw32-make install'.
Qt will be installed into 'D:\programs\Qt\510-static'.

Prior to reconfiguration, make sure you remove any leftovers from
the previous build.

Next step was to run make:

mingw32-make -j8

But it failed:

...
\ccUClyLX.ltrans22.ltrans.o:<artificial>:(.text+0x20d): undefined reference to `QByteArray::QByteArray(int, Qt::Initialization)'
\ccUClyLX.ltrans22.ltrans.o:<artificial>:(.text+0x244): undefined reference to `QByteArray::resize(int)'
collect2.exe: error: ld returned 1 exit status
Makefile.Release:86: recipe for target '..\..\..\bin\moc.exe' failed
mingw32-make[4]: *** [..\..\..\bin\moc.exe] Error 1
mingw32-make[4]: Leaving directory 'd:/programs/Qt/5.10.1/Src/qtbase/src/tools/moc'
Makefile:36: recipe for target 'release' failed
mingw32-make[3]: *** [release] Error 2
mingw32-make[3]: Leaving directory 'd:/programs/Qt/5.10.1/Src/qtbase/src/tools/moc'
Makefile:93: recipe for target 'sub-moc-make_first' failed
mingw32-make[2]: *** [sub-moc-make_first] Error 2
mingw32-make[2]: Leaving directory 'd:/programs/Qt/5.10.1/Src/qtbase/src'
Makefile:44: recipe for target 'sub-src-make_first' failed
mingw32-make[1]: *** [sub-src-make_first] Error 2
mingw32-make[1]: Leaving directory 'd:/programs/Qt/5.10.1/Src/qtbase'
Makefile:78: recipe for target 'module-qtbase-make_first' failed
mingw32-make: *** [module-qtbase-make_first] Error 2

I tried setting flags in qmake.conf like it is said here, but that didn’t help (I found the actual reason later).

Okay then, let’s try another computer - who knows, maybe my environment is messed up somehow. So I installed Qt to another machine with Windows and tried to perform configure. There it gave me a different type of error:

Cannot detect host toolchain. Please use -platform. Aborting.

Okay, I provided -platform win32-g++ (and -opengl desktop) and relaunched configure. It asked me about edition, I chose commercial, and…

Which edition of Qt do you want to use? c
Error: Insufficient command line arguments for licheck (configure)
ERROR: You are not licensed to use this software.

But I do have a commercial license! And the license file is where it should be. But okay, let’s try Open Source option:

Which edition of Qt do you want to use? o
Running configuration tests...
Checking for valid makespec... ERROR: Cannot compile a minimal program. The toolchain or QMakeSpec is broken.

Yeah, fuck this shit.

Qt 5.11.1, Windows 7 and MSVC2015 x64

After quite a while I gave it another shot as I needed to build static Qt for Windows 7 with MSVC2015.

So, here are the steps.

Install DirectX and DirectX SDK. Most likely it is not required, but I would do it just in case;

Install Python (I took 3.7), Perl and make sure that both are added to PATH. Thank you, Qt documentation, for not mentioning Python and Perl at all, because I discovered it by getting the following error:

Makefile [module-qtdeclarative-install_subtargets] Error 3

Which does not explain anything, but having googled it, I found out that it’s exactly due to the missing Python and Perl.

Install .NET 4.6, which is needed for Visual Studio installer. Choose the following components from VS:

Visual Studio Installer

Yes, even though you’re on Windows 7, install Windows 8.1 SDK. Although, it could be that only UCRT component is needed.

Now install Qt:

Qt installer

It is actually not required to install pre-built MSVC Qt (you only need Sources), but I wanted to compare dynamic with static, so I installed it.

Get jom and add it to PATH. If you won’t do this, Qt will be built with nmake, which will take ages as it cannot use more than one CPU core (no -j option).

Create a folder for shadow build, launch VS2015 x64 Native Tools Command Prompt from your Start menu and go to this folder. Then build Qt from there:

configure.bat -release -static -no-pch -optimize-size -opengl desktop -platform win32-msvc -prefix "C:\Qt\511-static" -skip webengine -nomake tools -nomake tests -nomake examples
time /t >> time.txt & jom -j8 & time /t >> time.txt
jom -j8 install

It took 35 minutes (on the same Lenovo laptop) to build 487 MB of binaries, and then it took a 1 hour and 40 minutes to perform install, which resulted in 560 MB. I don’t know why it takes so long to perform install, but what’s more amusing is that sometimes it takes just a couple of minutes as it should - no idea what Windows “magic” is behind that.

Note that I don’t have -ltcg option this time. I actually had it, but it resulted in something ridiculous: the build itself occupied fucking 46 GB of space, and after install command I got another 22 GB. What is the actual fuck. Apparently, it has something to do with the compiler (hello, Microsoft), because the .lib files were matching the .obj folder (someone told me that, I’ve no idea what it means).

During both build and install phases I got several occasional freezes of my PC when it became totally unresponsive so I had to hard-reset the machine and start over. Windows is definitely my favorite development platform.

But okay, most importantly thing is that it has successfully built and that it works.

Also note, that I haven’t set any special flags which you can find being mentioned all over the internet (QMAKE_CFLAGS_X and others) and didn’t edit any configs - everything just builds as it is with out-of-the-box configuration.

Qt 5.11.1, Windows 10 and MSVC2017 x64

Just in case I decided to try Windows 10 and MSVC2017.

Again, it’s all the same: Python and Perl in your PATH, Visual Studio installed but this time with MSVC2017, you launched VS2017 x64 Native Tools Command Prompt.

configure.bat -release -static -no-pch -optimize-size -opengl desktop -platform win32-msvc -prefix "\path\to\Qt\511-static" -skip webengine -nomake tools -nomake tests -nomake examples
time /t >> time.txt & jom -j8 & time /t >> time.txt
jom -j8 install

And again, with -ltcg option it produced 14.5 GB after build, then increased that to 52.6 GB, having installed 25.7 GB of static Qt. Compilation took 18 minutes, and installation was going for 59 minutes.

Without -ltcg it produced 480 MB after build, increased that to 1.34 GB and installed 606 MB of static Qt. Compilation took 15 minutes, and installation was going for 44 minutes.

Qt 5.11.2, Windows 10 and MinGW x32

After I succeeded building Qt with MSVC, I decided to try MinGW again with just released Qt 5.11.2.

It’s all the same as for Windows 7, except for installed Python and Perl.

Configuration went okay, but mingw32-make failed literally within a couple of minutes:

C:\Users\vasya\AppData\Local\Temp\ccj6NtVh.ltrans2.ltrans.o:<artificial>:(.text+0x232a): undefined reference to
 `QMapDataBase::recalcMostLeftNode()'
C:\Users\vasya\AppData\Local\Temp\ccj6NtVh.ltrans2.ltrans.o:<artificial>:(.text.unlikely+0x21): undefined refer
ence to `QAbstractConcatenable::appendLatin1To(char const*, int, QChar*)'
C:\Users\vasya\AppData\Local\Temp\ccj6NtVh.ltrans2.ltrans.o:<artificial>:(.text$_ZN8SubArrayC4EPKc.lto_priv.53.
lto_priv.106[_ZN8SubArrayC4EPKc.lto_priv.53.lto_priv.106]+0xd): undefined reference to `QByteArray::QByteArray(
char const*, int)'
C:\Users\vasya\AppData\Local\Temp\ccj6NtVh.ltrans2.ltrans.o:<artificial>:(.text$_ZN11FunctionDefC4ERKS_.lto_pri
v.67.lto_priv.128[_ZN11FunctionDefC4ERKS_.lto_priv.67.lto_priv.128]+0xbb): undefined reference to `QArrayData::
allocate(unsigned long long, unsigned long long, unsigned long long, QFlags<QArrayData::AllocationOption>)'
C:\Users\vasya\AppData\Local\Temp\ccj6NtVh.ltrans2.ltrans.o:<artificial>:(.text$_ZN11FunctionDefC4ERKS_.lto_pri
v.67.lto_priv.128[_ZN11FunctionDefC4ERKS_.lto_priv.67.lto_priv.128]+0xdb): undefined reference to `QArrayData::
allocate(unsigned long long, unsigned long long, unsigned long long, QFlags<QArrayData::AllocationOption>)'
C:\Users\vasya\AppData\Local\Temp\ccj6NtVh.ltrans2.ltrans.o:<artificial>:(.text$_ZN7QVectorI11FunctionDefEC4ERK
S1_.lto_priv.65.lto_priv.132[_ZN7QVectorI11FunctionDefEC4ERKS1_.lto_priv.65.lto_priv.132]+0x46): undefined refe
rence to `QArrayData::allocate(unsigned long long, unsigned long long, unsigned long long, QFlags<QArrayData::A
llocationOption>)'
C:\Users\vasya\AppData\Local\Temp\ccj6NtVh.ltrans2.ltrans.o:<artificial>:(.text$_ZN7QVectorI11FunctionDefEC4ERK
S1_.lto_priv.65.lto_priv.132[_ZN7QVectorI11FunctionDefEC4ERKS1_.lto_priv.65.lto_priv.132]+0x65): undefined refe
rence to `QArrayData::allocate(unsigned long long, unsigned long long, unsigned long long, QFlags<QArrayData::A
llocationOption>)'
collect2.exe: error: ld returned 1 exit status
Makefile.Release:86: recipe for target '..\..\..\bin\moc.exe' failed
mingw32-make[4]: *** [..\..\..\bin\moc.exe] Error 1
mingw32-make[4]: Leaving directory 'c:/Qt/5.11.1/5111/qtbase/src/tools/moc'
Makefile:36: recipe for target 'release' failed
mingw32-make[3]: *** [release] Error 2
mingw32-make[3]: Leaving directory 'c:/Qt/5.11.1/5111/qtbase/src/tools/moc'
Makefile:92: recipe for target 'sub-moc-make_first' failed
mingw32-make[2]: *** [sub-moc-make_first] Error 2
mingw32-make[2]: Leaving directory 'c:/Qt/5.11.1/5111/qtbase/src'
Makefile:44: recipe for target 'sub-src-make_first' failed
mingw32-make[1]: *** [sub-src-make_first] Error 2
mingw32-make[1]: Leaving directory 'c:/Qt/5.11.1/5111/qtbase'
Makefile:78: recipe for target 'module-qtbase-make_first' failed
mingw32-make: *** [module-qtbase-make_first] Error 2

I almost cursed everything forever, but then suddenly I decided to… try without -ltcg option. And it fucking worked! Hallelujah.

Although, in case of MinGW there is one more thing you should know about - its runtime doesn’t link statically by default. Surprise! So having deployed your statically linked Qt application to some other computer, you can get the following error:

Qt, missing MinGW runtime

In order to link MinGW runtime too, you need to set yet another option: -static-runtime.

So, the final configure options for building static Qt with MinGW on Windows is the following:

configure.bat -release -static -static-runtime -no-pch -optimize-size -opengl desktop -platform win32-g++ -prefix "\path\to\qt\511-static" -skip webengine -nomake tools -nomake tests -nomake examples

Building took 1 hour and 14 minutes and 1.02 GB. Installing took 8 minutes and resulted in 460 MB.

Now I can finally state that MinGW static builds of Qt do actually work. By the way, contrary to many manuals from the internet, I haven’t used any additional scripts or MSYS environment - everything just works within regular cmd.

Ну что сказать. Я просто труба тех шатал, кто писал документацию на тему. Ни хера нормально не расписано, пердолься сам до посинения, собирай инфу по кусочкам со всего интернета, может чего и получится. Понятно, что Шиндошс не в почёте, и реальные пацаны сидят на Линупсе, но это же документация коммерческого продукта, можно наверное ради такого дела отодвинуть ненадолго в сторону свою оконную непереносимость? Пиздец.

How to use static Qt

You need to add static Qt in your Qt Creator settings:

Qt Creator, versions
Qt Creator, kits

After that you just need to add this kit to your existing project and build with it:

Qt Creator, build target

How exactly static build is different

Let’s see how to use static Qt in your projects and also let’s compare some metrics between dynamic and static builds. I took Cinematic Experience demo for experiments.

No more shared libraries

You can see for yourself that dynamically linked applications have dependency on Qt shared libraries and statically linked ones do not.

Mac OS

Dynamic:

otool -L cinematic-demo.app/Contents/MacOS/cinematic-demo

cinematic-demo.app/Contents/MacOS/cinematic-demo:
  @rpath/QtQuick.framework/Versions/5/QtQuick (compatibility version 5.10.0, current version 5.10.1)
  @rpath/QtQml.framework/Versions/5/QtQml (compatibility version 5.10.0, current version 5.10.1)
  @rpath/QtNetwork.framework/Versions/5/QtNetwork (compatibility version 5.10.0, current version 5.10.1)
  @rpath/QtCore.framework/Versions/5/QtCore (compatibility version 5.10.0, current version 5.10.1)
  /System/Library/Frameworks/DiskArbitration.framework/Versions/A/DiskArbitration (compatibility version 1.0.0, current version 1.0.0)
  /System/Library/Frameworks/IOKit.framework/Versions/A/IOKit (compatibility version 1.0.0, current version 275.0.0)
  @rpath/QtGui.framework/Versions/5/QtGui (compatibility version 5.10.0, current version 5.10.1)
  /System/Library/Frameworks/OpenGL.framework/Versions/A/OpenGL (compatibility version 1.0.0, current version 1.0.0)
  /System/Library/Frameworks/AGL.framework/Versions/A/AGL (compatibility version 1.0.0, current version 1.0.0)
  /usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 400.9.0)
  /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.0.0)

Static:

otool -L cinematic-demo.app/Contents/MacOS/cinematic-demo

cinematic-demo.app/Contents/MacOS/cinematic-demo:
  /System/Library/Frameworks/AppKit.framework/Versions/C/AppKit (compatibility version 45.0.0, current version 1561.20.106)
  /System/Library/Frameworks/Carbon.framework/Versions/A/Carbon (compatibility version 2.0.0, current version 158.0.0)
  /System/Library/Frameworks/IOKit.framework/Versions/A/IOKit (compatibility version 1.0.0, current version 275.0.0)
  /System/Library/Frameworks/QuartzCore.framework/Versions/A/QuartzCore (compatibility version 1.2.0, current version 1.11.0)
  /usr/lib/libcups.2.dylib (compatibility version 2.0.0, current version 2.12.0)
  /System/Library/Frameworks/DiskArbitration.framework/Versions/A/DiskArbitration (compatibility version 1.0.0, current version 1.0.0)
  /System/Library/Frameworks/Foundation.framework/Versions/C/Foundation (compatibility version 300.0.0, current version 1450.15.0)
  /System/Library/Frameworks/CoreServices.framework/Versions/A/CoreServices (compatibility version 1.0.0, current version 822.19.0)
  /System/Library/Frameworks/ApplicationServices.framework/Versions/A/ApplicationServices (compatibility version 1.0.0, current version 50.0.0)
  /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 1450.15.0)
  /System/Library/Frameworks/CoreGraphics.framework/Versions/A/CoreGraphics (compatibility version 64.0.0, current version 1129.5.0)
  /System/Library/Frameworks/OpenGL.framework/Versions/A/OpenGL (compatibility version 1.0.0, current version 1.0.0)
  /System/Library/Frameworks/AGL.framework/Versions/A/AGL (compatibility version 1.0.0, current version 1.0.0)
  /System/Library/Frameworks/CoreText.framework/Versions/A/CoreText (compatibility version 1.0.0, current version 1.0.0)
  /System/Library/Frameworks/ImageIO.framework/Versions/A/ImageIO (compatibility version 1.0.0, current version 1.0.0)
  /System/Library/Frameworks/Security.framework/Versions/A/Security (compatibility version 1.0.0, current version 58286.31.2)
  /System/Library/Frameworks/SystemConfiguration.framework/Versions/A/SystemConfiguration (compatibility version 1.0.0, current version 963.30.1)
  /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.0.0)
  /usr/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.11)
  /usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 400.9.0)
  /System/Library/Frameworks/CFNetwork.framework/Versions/A/CFNetwork (compatibility version 1.0.0, current version 893.13.1)
  /usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)

I’ve no idea why why it has a much longer list of some other stuff.

Linux

On Linux it makes more sense.

Dynamic:

ldd cinematic-demo

  linux-vdso.so.1 =>  (0x00007ffff63e3000)
  libQt5Gui.so.5 => /path/to/qt/5.10.1/gcc_64/lib/libQt5Gui.so.5 (0x00007f54fbd1f000)
  libQt5Qml.so.5 => /path/to/qt/5.10.1/gcc_64/lib/libQt5Qml.so.5 (0x00007f54fb6ee000)
  libQt5Core.so.5 => /path/to/qt/5.10.1/gcc_64/lib/libQt5Core.so.5 (0x00007f54faf9e000)
  libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f54fabff000)
  libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f54fa9e9000)
  libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f54fa61f000)
  libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f54fa401000)
  libGL.so.1 => /usr/lib/x86_64-linux-gnu/mesa/libGL.so.1 (0x00007f54fa18e000)
  libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007f54f9f74000)
  libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f54f9c6a000)
  libQt5Network.so.5 => /path/to/qt/5.10.1/gcc_64/lib/libQt5Network.so.5 (0x00007f54f98d4000)
  librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f54f96cc000)
  libicui18n.so.56 => /path/to/qt/5.10.1/gcc_64/lib/libicui18n.so.56 (0x00007f54f9232000)
  libicuuc.so.56 => /path/to/qt/5.10.1/gcc_64/lib/libicuuc.so.56 (0x00007f54f8e7a000)
  libicudata.so.56 => /path/to/qt/5.10.1/gcc_64/lib/libicudata.so.56 (0x00007f54f7496000)
  libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f54f7292000)
  libgthread-2.0.so.0 => /usr/lib/x86_64-linux-gnu/libgthread-2.0.so.0 (0x00007f54f7090000)
  libglib-2.0.so.0 => /lib/x86_64-linux-gnu/libglib-2.0.so.0 (0x00007f54f6d7f000)
  /lib64/ld-linux-x86-64.so.2 (0x0000562cf8cce000)
  libexpat.so.1 => /lib/x86_64-linux-gnu/libexpat.so.1 (0x00007f54f6b55000)
  libxcb-dri3.so.0 => /usr/lib/x86_64-linux-gnu/libxcb-dri3.so.0 (0x00007f54f6952000)
  libxcb-present.so.0 => /usr/lib/x86_64-linux-gnu/libxcb-present.so.0 (0x00007f54f674e000)
  libxcb-sync.so.1 => /usr/lib/x86_64-linux-gnu/libxcb-sync.so.1 (0x00007f54f6547000)
  libxshmfence.so.1 => /usr/lib/x86_64-linux-gnu/libxshmfence.so.1 (0x00007f54f6344000)
  libglapi.so.0 => /usr/lib/x86_64-linux-gnu/libglapi.so.0 (0x00007f54f6113000)
  libXext.so.6 => /usr/lib/x86_64-linux-gnu/libXext.so.6 (0x00007f54f5f01000)
  libXdamage.so.1 => /usr/lib/x86_64-linux-gnu/libXdamage.so.1 (0x00007f54f5cfe000)
  libXfixes.so.3 => /usr/lib/x86_64-linux-gnu/libXfixes.so.3 (0x00007f54f5af7000)
  libX11-xcb.so.1 => /usr/lib/x86_64-linux-gnu/libX11-xcb.so.1 (0x00007f54f58f5000)
  libX11.so.6 => /usr/lib/x86_64-linux-gnu/libX11.so.6 (0x00007f54f55bb000)
  libxcb-glx.so.0 => /usr/lib/x86_64-linux-gnu/libxcb-glx.so.0 (0x00007f54f53a1000)
  libxcb-dri2.so.0 => /usr/lib/x86_64-linux-gnu/libxcb-dri2.so.0 (0x00007f54f519c000)
  libxcb.so.1 => /usr/lib/x86_64-linux-gnu/libxcb.so.1 (0x00007f54f4f7a000)
  libXxf86vm.so.1 => /usr/lib/x86_64-linux-gnu/libXxf86vm.so.1 (0x00007f54f4d73000)
  libdrm.so.2 => /usr/lib/x86_64-linux-gnu/libdrm.so.2 (0x00007f54f4b62000)
  libpcre.so.3 => /lib/x86_64-linux-gnu/libpcre.so.3 (0x00007f54f48f1000)
  libXau.so.6 => /usr/lib/x86_64-linux-gnu/libXau.so.6 (0x00007f54f46ed000)
  libXdmcp.so.6 => /usr/lib/x86_64-linux-gnu/libXdmcp.so.6 (0x00007f54f44e6000)

Static:

ldd cinematic-demo

  linux-vdso.so.1 =>  (0x00007ffda1b9f000)
  libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f9b02744000)
  libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f9b0252e000)
  libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f9b02164000)
  libxcb-glx.so.0 => /usr/lib/x86_64-linux-gnu/libxcb-glx.so.0 (0x00007f9b01f4a000)
  libX11-xcb.so.1 => /usr/lib/x86_64-linux-gnu/libX11-xcb.so.1 (0x00007f9b01d48000)
  libX11.so.6 => /usr/lib/x86_64-linux-gnu/libX11.so.6 (0x00007f9b01a0e000)
  libxcb.so.1 => /usr/lib/x86_64-linux-gnu/libxcb.so.1 (0x00007f9b017eb000)
  libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f9b015e7000)
  libGL.so.1 => /usr/lib/x86_64-linux-gnu/mesa/libGL.so.1 (0x00007f9b01374000)
  libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f9b01156000)
  libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f9b00e4d000)
  /lib64/ld-linux-x86-64.so.2 (0x00005583c34ae000)
  libXau.so.6 => /usr/lib/x86_64-linux-gnu/libXau.so.6 (0x00007f9b00c49000)
  libXdmcp.so.6 => /usr/lib/x86_64-linux-gnu/libXdmcp.so.6 (0x00007f9b00a42000)
  libexpat.so.1 => /lib/x86_64-linux-gnu/libexpat.so.1 (0x00007f9b00819000)
  libxcb-dri3.so.0 => /usr/lib/x86_64-linux-gnu/libxcb-dri3.so.0 (0x00007f9b00616000)
  libxcb-present.so.0 => /usr/lib/x86_64-linux-gnu/libxcb-present.so.0 (0x00007f9b00412000)
  libxcb-sync.so.1 => /usr/lib/x86_64-linux-gnu/libxcb-sync.so.1 (0x00007f9b0020b000)
  libxshmfence.so.1 => /usr/lib/x86_64-linux-gnu/libxshmfence.so.1 (0x00007f9b00008000)
  libglapi.so.0 => /usr/lib/x86_64-linux-gnu/libglapi.so.0 (0x00007f9affdd7000)
  libXext.so.6 => /usr/lib/x86_64-linux-gnu/libXext.so.6 (0x00007f9affbc5000)
  libXdamage.so.1 => /usr/lib/x86_64-linux-gnu/libXdamage.so.1 (0x00007f9aff9c2000)
  libXfixes.so.3 => /usr/lib/x86_64-linux-gnu/libXfixes.so.3 (0x00007f9aff7bb000)
  libxcb-dri2.so.0 => /usr/lib/x86_64-linux-gnu/libxcb-dri2.so.0 (0x00007f9aff5b6000)
  libXxf86vm.so.1 => /usr/lib/x86_64-linux-gnu/libXxf86vm.so.1 (0x00007f9aff3b0000)
  libdrm.so.2 => /usr/lib/x86_64-linux-gnu/libdrm.so.2 (0x00007f9aff19e000)

Windows

On Windows there is no out of the box tool to track dependencies, so I used Dependency Walker.

And it’s worth to mention that MSVC and MinGW builds have different set of dependencies.

Dynamic MSVC:

Dependency Walker, MSVC dynamic Qt build

Static MSVC:

Dependency Walker, MSVC static Qt build

Dynamic MinGW:

Dependency Walker, MinGW dynamic Qt build

Oh, by the way, in case of dynamic linking it’s not a trivial task to gather all the required Qt libraries based on what Dependency Walker shows you. For instance, here we can see that only 3 Qt libraries are required, but after I deployed those, my application complained about one more, and when I added that one, it stopped complaining, however having launched it I never saw its window, even though application was present among the running processes at Task Manager. And only after a set of tests and trials I’ve managed to collect the full pack:

release
├── Qt5Core.dll
├── Qt5Gui.dll
├── Qt5Network.dll
├── Qt5Qml.dll
├── Qt5Quick.dll
├── Qt5QuickControls2.dll
├── Qt5QuickParticles.dll
├── Qt5QuickTemplates2.dll
├── Qt5QuickWidgets.dll
├── cinematic-demo.exe
├── libgcc_s_dw2-1.dll
├── libstdc++-6.dll
└── libwinpthread-1.dll

From that perspective MinGW static linking on Windows is really a savior:

Dependency Walker, MinGW static Qt build

If you are confused by longer list for static builds - this whole bunch of system libraries is actually from the SHELL32.DLL tree, and you can find them in dynamic build too by expanding its node. What matters is that there are no Qt libraries (and no MinGW runtime) among dependencies anymore.

Smaller builds

Naturally, static build gives you smaller size for your application binary.

On Mac OS:

  • dynamic (with all required Qt libraries): 33.4 MB;
  • static: 26.1 MB.

On Windows (MinGW):

  • dynamic (with all required Qt libraries and MinGW runtime): 28.2 MB;
  • static: 19.9 MB.

Less RAM

I saw people claiming that RAM consumption is different too. On Mac it’s not really the case:

  • dynamic: 118.7 MB;
  • static: 116.8 MB.
Qt static vs dynamic, RAM, Mac OS

Windows (MinGW) has some difference, but not that big:

  • dynamic: 168.9 MB;
  • static: 160.7 MB.
Qt static vs dynamic, RAM, Windows

And there is some notable difference on Linux:

  • dynamic: 141.0 MB;
  • static: 115.2 MB.
Qt static vs dynamic, RAM, Linux

Slower building

But there is also a trade-off in terms of compilation time (measured on Mac OS):

  • dynamic: 5 seconds;
  • static: 210 seconds.

Problems

There could be all sorts of problems along the road. And those are not necessarily your fault - on the contrary, in most cases it will be Qt bugs, which you should definitely report at Qt’s bug-tracker. Seriously, do that, because they give highest priority to that kind of issues (especially if it’s reported against a pre-release version) and fix those pretty fast.

Now about the problems I’ve encountered myself.

Shadow builds

Sometimes, shadow builds are broken “by default” - meaning that it is impossible to built a particular Qt version using shadow build, so you have to do it from the Src directory. Report that at bug-tracker, but as most likely it will be fixed only for the next version, you’ll have to build the one you have without shadow build.

Trailing backslash in prefix

Having a trailing \ in prefix on Windows can cause the following problem:

Running configuration tests...
Checking for valid makespec... ERROR: Cannot compile a minimal program. The toolchain or QMakeSpec is broken.

Check config.log for details.

Remove the trailing \ and try again. So:

  • -prefix "d:\programs\qt\5122-static\" - fails;
  • -prefix "d:\programs\qt\5122-static" - works.

Fonts

One of the issues you might encounter with your applications built with static Qt is the absent of fonts for your GUI. Literally, all the text controls will have no text at all. The reason might be that path to system fonts is lost somehow.

One way to fix this is to embed fonts into your application: add font file into resources and “activate” it in main.cpp:

...
#include <QFontDatabase>
#include <QFont>

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);

    int id = QFontDatabase::addApplicationFont(":/fonts/TitilliumWeb-Regular.ttf");
    app.setFont(QFont(QFontDatabase::applicationFontFamilies(id).at(0)));
    
    ...
}