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

Although the article is (mostly) about making a static build, it also covers building Qt from sources in general and other related activities (such as linking with the resulting build, deploying applications and so on).

TLDR

The article has really exploded in volume over the years, so here are some general commands for configuration and building static Qt.

On Windows:

> cd d:\path\to\qt\src
> mkdir build
> cd build
> ..\configure.bat -static -release -no-pch -prefix "d:\path\to\qt\5.15.2-static" -skip qtwebengine -nomake tests -nomake examples
> jom -j8
> jom -j8 install

On GNU/Linux:

$ cd /path/to/qt/src
$ mkdir build && cd $_
$ ../configure -static -release -no-pch -prefix "/path/to/qt/5.15.2-static" -skip qtwebengine -nomake tests -nomake examples -fontconfig
$ make -j8
$ make -j8 install

On Mac OS:

$ cd /path/to/qt/src
$ mkdir build && cd $_
$ ../configure -static -release -no-pch -prefix "/path/to/qt/5.15.2-static" -skip qtwebengine -nomake tests -nomake examples
$ make -j8
$ make -j8 install

Also note that this article was written when Qt 5.x was the latest version available, so it doesn’t account for all the peculiarities of building Qt 6.x or newer (although the process is mostly the same). But here is a more recent partly related article about installing Qt without official installer, which covers Qt 6.x too.

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 refers 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 in flames. And also as far as I know it is possible to sign shared libraries and perform checks before actually loading 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

Configuration

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:

$ cd /path/to/qt/sources
$ mkdir build && cd $_
$ ../configure -static -release -no-pch -prefix "/path/to/qt/510-static" -skip webengine -nomake tools -nomake tests -nomake examples

Note how configure doesn’t care about short/long options and just has a single - for everything.

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;
  • -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).

Optimization options

Qt build can be configured with so-called optimization options:

  • -ltcg - Link-Time Code Generation, optimizes something. I took it from here
  • -optimize-size - seems to be optimizing release builds in terms of resulting binaries size (by sacrificing build time)

To see the actual effect of such optimization, I built Qt 5.12.3 on Mac OS twice, first time with these options:

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

and second time without them:

$ ../configure -static -release -no-pch -prefix "/path/to/qt/5123-static" -skip webengine -nomake tools -nomake tests -nomake examples

Results are here:

Qt
build
time
Qt
build
size
Qt
installation
size
Application
build
time
Application
size
With optimisation options 00:31:53 1.15 GB 519.3 MB 00:03:28 27.0 MB
Without optimisation options 00:21:35 835.7 MB 381.5 MB 00:00:04 31.2 MB

So, indeed, -optimize-size does provide smaller application binaries, but at the same time you lose in Qt build time, its size and also applications build time.

What -ltcg actually does - that I still don’t know and have no idea how to measure it.

I had these options enabled for most of the builds described below, and on Windows it caused certain problems, so perhaps I would recommend not to set those in your builds.

Cleaning the build directory

Note, that if you were building Qt before, then you should clean out the old build first (and the folder you’ve set with -prefix):

$ make -j8 distclean

or:

$ rm -r ./*; rm .config.notes; rm .qmake.*

Platforms

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 should take a couple of minutes (usually less than a minute), and then you can go to /path/to/qt/510-static to see the result. If installation runs for more than 5 minutes, than it likely means that something is wrong and it might actually fail. This concerns not only Mac OS but other platforms too.

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:

$ sudo apt install build-essential

Second one was this:

ERROR The OpenGL functionality tests failed

Which is fixed by installing Mesa libraries:

$ sudo apt 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.

MSVC

Dynamic MSVC:

Dependency Walker, MSVC dynamic Qt build

Static MSVC:

Dependency Walker, MSVC static Qt build

MinGW

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.

Possible 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 not working

Sometimes, shadow builds just get broken, meaning that it is impossible to built a particular Qt version using shadow build, whatever the reason might be, and so you’ll have to do it right in the Src directory.

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.

Text is not visible, because there are no fonts

One of the issues you might encounter with your applications built with static Qt is the absence of fonts for your GUI. Literally, all the text controls will have no text at all. Also, your application will print the following to the console:

QFontDatabase: Cannot find font directory /path/to/qt/5.15.2-static/lib/fonts.
Note that Qt no longer ships fonts. Deploy some (from https://dejavu-fonts.github.io/ for example) or switch to fontconfig.

As I understood, that happens on GNU/Linux only.

There are several ways of fixing this. First, obviously, it might be enough to just deploy some fonts to /path/to/qt/5.15.2-static/lib/fonts folder.

Second option would be to “embed” a font into your application - add a font file to 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)));

    ...
}

Finally, you can re-configure (and rebuild) Qt with -fontconfig option. First, install these packages just in case:

$ sudo apt install libfreetype6 libfreetype6-dev libfreetype-dev
$ sudo apt install libfontconfig1 libfontconfig1-dev

and then configure Qt (having deleted the old build and cache files):

$ ../configure -static -release -no-pch -prefix "/path/to/qt/5.15.2-static" \
    -fontconfig -skip qtwebengine -nomake tests -nomake examples

You should see the following in the configuration output:

Qt Gui:
  Accessibility .......................... yes
  FreeType ............................... yes
    Using system FreeType ................ yes
  HarfBuzz ............................... yes
    Using system HarfBuzz ................ no
  Fontconfig ............................. yes

Non-existent module or unknown command line option

Sometimes you might get this error trying to run configure:

Project ERROR: -skip command line argument used with non-existent module 'qtwebengine'.

or even this one:

ERROR: Unknown command line option '-release'.

I’ve got both after unpacking Qt sources from a snapshot archive with default Archive Manager application on Elementary OS. I figured it did something wrong during unpacking, and so I unpacked the archive using tar from command line instead, and then the exactly same configure command ran without problems.

QQmlApplicationEngine failed to load component, qtquick2plugin not found

At some point, having built Qt 5.15.2, I got this error, trying to launch my application:

QQmlApplicationEngine failed to load component
qrc:/main.qml:1:1: module "QtQuick" plugin "qtquick2plugin" not found

So the application builds fine, but throws this error on launch.

At first I did not find a solution for this, so I just re-built Qt dynamically (without -static configuration option), and then my application was able to launch.

But then I did some digging and discovered that some Qt plugins/modules (including qtquick2plugin, apparently) require some additional massaging if Qt is built statically, and actually Qt warns about this in the end of the configuration output:

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.

Why cannot it just take care of this on its own, so one could get a working build out of the box - I don’t know, apparently one just can not. Well, actually, if you are using qmake, then it will work out of the box (but here’s also some documentation on the matter, just in case), and you won’t need to change anything in your project file, but with CMake that is not the case.

When using Qt static build and CMake, one needs to call qt5_import_qml_plugins function in his project:

get_target_property(QT_TARGET_TYPE Qt5::Core TYPE)
if(${QT_TARGET_TYPE} STREQUAL "STATIC_LIBRARY")
    find_package(Qt5QmlImportScanner REQUIRED)
    qt5_import_qml_plugins(${CMAKE_PROJECT_NAME})
endif()

Hopefully, there is also qt6_import_qml_plugins in Qt 6, at least it is mentioned in QTBUG-86827.

This function is available only from Qt 5.14, but for versions older than 5.14 there seems to be nothing for that in the official resources, but fortunately there is this external CMake module. I did some modifications to it, and here’s how I used it in my project:

get_target_property(QT_TARGET_TYPE Qt${QT_VERSION_MAJOR}::Core TYPE)
if(${QT_TARGET_TYPE} STREQUAL "STATIC_LIBRARY")
    message(STATUS "This Qt is static")

    # from 5.14 there is a standard function for this
    set(QT_VERSION_WITH_QML_IMPORTS 5.14)
    if(${QT_VERSION} VERSION_EQUAL ${QT_VERSION_WITH_QML_IMPORTS}
        OR ${QT_VERSION} VERSION_GREATER ${QT_VERSION_WITH_QML_IMPORTS}
    )
        message(STATUS "This Qt version (${QT_VERSION}) is newer than ${QT_VERSION_WITH_QML_IMPORTS}")
        find_package(Qt5QmlImportScanner REQUIRED)
        qt5_import_qml_plugins(${CMAKE_PROJECT_NAME})
    else() # use a custom module
        message(STATUS "This Qt version (${QT_VERSION}) is older than ${QT_VERSION_WITH_QML_IMPORTS}")
        include(QtStaticPlugins)
        # this adds lots of unused modules and actually is not needed at all, as it seems
        #qt_generate_plugin_import(${CMAKE_PROJECT_NAME}
        #    OUTPUT "${CMAKE_PROJECT_NAME}_plugin_import.cpp"
        #    OUTPUT_DIR "${PROJECT_BINARY_DIR}"
        #    #VERBOSE
        #)
        qt_generate_qml_plugin_import(${CMAKE_PROJECT_NAME}
            QML_DIR "${QT_HOME}/qml"
            QML_SRC "${CMAKE_CURRENT_SOURCE_DIR}"
            OUTPUT "${CMAKE_PROJECT_NAME}_qml_plugin_import.cpp"
            OUTPUT_DIR "${PROJECT_BINARY_DIR}"
            #VERBOSE
        )
    endif()

    if(TARGET Qt${QT_VERSION_MAJOR}::QmlWorkerScript)
        target_link_libraries(${CMAKE_PROJECT_NAME}
            PRIVATE
                Qt${QT_VERSION_MAJOR}::QmlWorkerScript
        )
    endif()
endif()

The last bit about linking to QmlWorkerScript is a required crutch, otherwise you’ll get the following error on linking:

Undefined symbols for architecture x86_64:
  "qml_register_types_QtQml_WorkerScript()", referenced from:
      qt_plugin_instance_QtQmlWorkerScriptPlugin() in libworkerscriptplugin.a(plugin.o)
  "QQmlWorkerScriptModule::registerQuickTypes()", referenced from:
      QtQuick2Plugin::registerTypes(char const*) in libqtquick2plugin.a(plugin.o)
      non-virtual thunk to QtQuick2Plugin::registerTypes(char const*) in libqtquick2plugin.a(plugin.o)

With my glorious Color Corners application as an example, both the standard function and this module produced identical .cpp files in the build directory:

#include <QtPlugin>

Q_IMPORT_PLUGIN(QtQuick2Plugin)
Q_IMPORT_PLUGIN(QtQuick2WindowPlugin)
Q_IMPORT_PLUGIN(QtQuickLayoutsPlugin)
Q_IMPORT_PLUGIN(QtQmlPlugin)
Q_IMPORT_PLUGIN(QtQmlModelsPlugin)
Q_IMPORT_PLUGIN(QtQmlWorkerScriptPlugin)

Plus certain linking instructions were added.

If you are curious to see where this list of plugins originates from, you can inspect your application imports with qmlimportscanner tool yourself:

$ /path/to/qt/5.15.2-static/bin/qmlimportscanner \
    -rootPath /path/to/your/project/qml/sources \
    -importPath /path/to/qt/5.15.2-static/qml

For me it was the following:

[
    {
        "classname": "QtQuick2Plugin",
        "name": "QtQuick",
        "path": "/path/to/qt/5.15.2-static/qml/QtQuick.2",
        "plugin": "qtquick2plugin",
        "relativePath": "QtQuick.2",
        "type": "module",
        "version": "2.15"
    },
    {
        "classname": "QtQuick2WindowPlugin",
        "name": "QtQuick.Window",
        "path": "/path/to/qt/5.15.2-static/qml/QtQuick/Window.2",
        "plugin": "windowplugin",
        "relativePath": "QtQuick/Window.2",
        "type": "module",
        "version": "2.15"
    },
    {
        "classname": "QtQuickLayoutsPlugin",
        "name": "QtQuick.Layouts",
        "path": "/path/to/qt/5.15.2-static/qml/QtQuick/Layouts",
        "plugin": "qquicklayoutsplugin",
        "relativePath": "QtQuick/Layouts",
        "type": "module",
        "version": "1.15"
    },
    {
        "classname": "QtQmlPlugin",
        "name": "QtQml",
        "path": "/path/to/qt/5.15.2-static/qml/QtQml",
        "plugin": "qmlplugin",
        "relativePath": "QtQml",
        "type": "module",
        "version": "2.15"
    },
    {
        "classname": "QtQmlModelsPlugin",
        "name": "QtQml.Models",
        "path": "/path/to/qt/5.15.2-static/qml/QtQml/Models.2",
        "plugin": "modelsplugin",
        "relativePath": "QtQml/Models.2",
        "type": "module",
        "version": "2.15"
    },
    {
        "classname": "QtQmlWorkerScriptPlugin",
        "name": "QtQml.WorkerScript",
        "path": "/path/to/qt/5.15.2-static/qml/QtQml/WorkerScript.2",
        "plugin": "workerscriptplugin",
        "relativePath": "QtQml/WorkerScript.2",
        "type": "module",
        "version": "2.15"
    }
]

Which matches the generated list of imports.

Could not find the Qt platform plugin XCB

On Linux, even though the Qt builds fine, and even your applications build fine, you might get the following error, trying to launch them:

qt.qpa.plugin: Could not find the Qt platform plugin "xcb" in ""
This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.

Available platform plugins are: eglfs, linuxfb, minimal, minimalegl, offscreen, vnc, webgl.

There is a one kilometer long thread on Qt’s forum, where you might find an absolutely retarded advice (что за уебан догадался такое посоветовать) to remove libqt5gui5 from the system - don’t do that, not only it won’t help, but it will actually pretty much ruin your system.

Some replies there and also here say that installing/reinstalling libxcb-xinerama0 resolved the problem for them, but it didn’t for me.

There is also a shorter thread on a similar topic here, and this one did point to this comment, which finally got me to the right place - Qt wiki, which had the full list of packets that you need to install:

$ sudo apt install '^libxcb.*-dev' libx11-xcb-dev libglu1-mesa-dev libxrender-dev libxi-dev libxkbcommon-dev libxkbcommon-x11-dev

Qt’s documentation also provides a list of those, but it’s not as full as the one from wiki, and installing only the ones listed in documentation was not enough in my case.

Anyway, here’s how your Qt configuration output might look like without required XCB packages installed:

...
Features used by QPA backends:
  evdev .................................. yes
  libinput ............................... no
  INTEGRITY HID .......................... no
  mtdev .................................. no
  tslib .................................. no
  xkbcommon .............................. no
  X11 specific:
    XLib ................................. no
    XCB Xlib ............................. no
    EGL on X11 ........................... no
    xkbcommon-x11 ........................ no
QPA backends:
  DirectFB ............................... no
  EGLFS .................................. yes
  EGLFS details:
    EGLFS OpenWFD ........................ no
    EGLFS i.Mx6 .......................... no
    EGLFS i.Mx6 Wayland .................. no
    EGLFS RCAR ........................... no
    EGLFS EGLDevice ...................... no
    EGLFS GBM ............................ no
    EGLFS VSP2 ........................... no
    EGLFS Mali ........................... no
    EGLFS Raspberry Pi ................... no
    EGLFS X11 ............................ no
  LinuxFB ................................ yes
  VNC .................................... yes
...

here’s the resulting platform plugins folder contents:

$ ls -L1 ~/programs/qt/5152-static/plugins/platforms
libqeglfs.a
libqeglfs.prl
libqlinuxfb.a
libqlinuxfb.prl
libqminimal.a
libqminimal.prl
libqminimalegl.a
libqminimalegl.prl
libqoffscreen.a
libqoffscreen.prl
libqvnc.a
libqvnc.prl
libqwebgl.a
libqwebgl.prl

That’s how you know that your applications will build but will not launch. Pretty amazing how you can get get a Qt build, which did not complain about anything neither during configuration nor during the build, succeeded without errors, and yet it ended up being actually useless for you.

And here’s a Qt configuration output when all the required XCB packages are installed:

...
Features used by QPA backends:
  evdev .................................. yes
  libinput ............................... no
  INTEGRITY HID .......................... no
  mtdev .................................. no
  tslib .................................. no
  xkbcommon .............................. yes
  X11 specific:
    XLib ................................. yes
    XCB Xlib ............................. yes
    EGL on X11 ........................... yes
    xkbcommon-x11 ........................ yes
QPA backends:
  DirectFB ............................... no
  EGLFS .................................. yes
  EGLFS details:
    EGLFS OpenWFD ........................ no
    EGLFS i.Mx6 .......................... no
    EGLFS i.Mx6 Wayland .................. no
    EGLFS RCAR ........................... no
    EGLFS EGLDevice ...................... no
    EGLFS GBM ............................ no
    EGLFS VSP2 ........................... no
    EGLFS Mali ........................... no
    EGLFS Raspberry Pi ................... no
    EGLFS X11 ............................ yes
  LinuxFB ................................ yes
  VNC .................................... yes
  XCB:
    Using system-provided xcb-xinput ..... yes
    Native painting (experimental) ....... no
    GL integrations:
      GLX Plugin ......................... yes
        XCB GLX .......................... yes
      EGL-X11 Plugin ..................... yes
...

and resulting platform plugins folder contents:

$ ls -L1 ~/programs/qt/5152-static/plugins/platforms
libqeglfs.a
libqeglfs.prl
libqlinuxfb.a
libqlinuxfb.prl
libqminimal.a
libqminimal.prl
libqminimalegl.a
libqminimalegl.prl
libqoffscreen.a
libqoffscreen.prl
libqvnc.a
libqvnc.prl
libqwebgl.a
libqwebgl.prl
libqxcb.a
libqxcb.prl

So now libqxcb plugin is in place, and your applications will not only build but also actually work.

d3d12.dll is missing

Having built your application with static Qt, you can get this error trying to launch the application on a different computer:

Отсутствует d3d12.dll d3d12.dll is missing
Запуск программы невозможен, так как на компьютере отсутствует d3d12.dll. Попробуйте переустановить программу.

The program can't start because d3d12.dll is missing from your computer. Try reinstalling the program to fix this problem.

That could be because you might have built Qt on a system with DirectX 12, but this other computer might not have it. To avoid this problem you’ll need to re-configure Qt with -no-feature-d3d12 and re-build it.

Cannot open compiler generated file

That one I got trying to build Qt 5.15.2 on Windows 10, and this problem seems to be specific to Windows only, as it cannot handle paths longer than certain length. The error message is not very descriptive, though:

D:\path\to\qt-everywhere-src-5.15.2\qtbase\src\3rdparty\angle\src\libANGLE\renderer\d3d\d3d11\texture_format_table_autogen.cpp : fatal error C1083: Cannot open compiler generated file: '': Invalid argument

The solution for this is to have sources and build folder somewhere closer to the disk root, such as d:\qt\build.

Variable has incomplete type struct stat64

I got this one trying to build Qt 5.15.2 on Mac OS 11.2 with Apple silicon processor (so my configuration command had QMAKE_APPLE_DEVICE_ARCHS=arm64):

In file included from /path/to/qt-everywhere-src-5.15.2/qt3d/src/3rdparty/assimp/contrib/zip/src/zip.c:12:
/path/to/qt-everywhere-src-5.15.2/qt3d/src/3rdparty/assimp/contrib/zip/src/miniz.h:3075:30: error: variable has incomplete type 'struct stat64'
  struct MZ_FILE_STAT_STRUCT file_stat;
                             ^

I did not find a solution for this, so I just disabled 3D stuff with -skip qt3d -skip qtquick3d (I don’t use it anyway). Probably later Qt versions already have a fix for this, but for now I only found this bugreport, and it is still open.

Cannot open input file qwebp.lib

I got this one trying to build Qt 5.15.6 on Windows 11 with MSVC 143 (VS 2022). But I think I also had this problem with 5.15.2 on Windows 10 with MSVC 142 (VS 2019):

fatal error LNK1181: cannot open input file 'D:\path\to\qt\src\5.15.6\build\qtimageformats\plugins\imageformats\qwebp.lib'

I don’t know why it happens and how to resolve it, so I just disabled WebP (yeah, fuck WebP anyway) with -no-webp configuration option.

Unknown type name CGColorSpaceRef

Got this one trying to build Qt 6.2.0:

In file included from /path/to/qt/src/6.2.0/qtbase/src/plugins/platforms/cocoa/qiosurfacegraphicsbuffer.mm:40:
/path/to/qt/src/6.2.0/qtbase/src/plugins/platforms/cocoa/qiosurfacegraphicsbuffer.h:56:32: error: unknown type name 'CGColorSpaceRef'; did you mean 'QColorSpace'?
    void setColorSpace(QCFType<CGColorSpaceRef> colorSpace);
                               ^~~~~~~~~~~~~~~
                               QColorSpace

The fix is to edit /path/to/qt/src/6.2.0/qtbase/src/plugins/platforms/cocoa/qiosurfacegraphicsbuffer.h and add missing header CoreGraphics/CGColorSpace.h:

diff --git a/src/plugins/platforms/cocoa/qiosurfacegraphicsbuffer.h b/src/plugins/platforms/cocoa/qiosurfacegraphicsbuffer.h
index 5d4b6d6a71..cc7193d8b7 100644
--- a/src/plugins/platforms/cocoa/qiosurfacegraphicsbuffer.h
+++ b/src/plugins/platforms/cocoa/qiosurfacegraphicsbuffer.h
@@ -43,6 +43,7 @@
 #include <qpa/qplatformgraphicsbuffer.h>
 #include <private/qcore_mac_p.h>
 
+#include <CoreGraphics/CGColorSpace.h>
 #include <IOSurface/IOSurface.h>
 
 QT_BEGIN_NAMESPACE

Undefined symbols GSSAPI

Started to get this one all of the sudden even with versions that were for sure building fine before:

Undefined symbols for architecture x86_64:
  "___gss_c_nt_hostbased_service_oid_desc", referenced from:
      qGSsapiGetServiceName(QStringView) in libQt6Network.a(qauthenticator.cpp.o)

That turned out to be caused by vcpkg that I had installed at some point. Apparently, something collides or overlaps somewhere with the things found in VCPKG_ROOT path. So the workaround is to unset this variable before building Qt (and do a clean build, if you have remains from the previous build):

$ pwd
/path/to/qt/src/6.4.2/build
$ rm -r ./*; rm -r .qt; rm .ninja_*; ls -lah
$ echo $VCPKG_ROOT
/path/to/programs/vcpkg
$ unset VCPKG_ROOT
$ echo $VCPKG_ROOT

$ ../configure -static -release AND-SO-ON

Updates

2021-11-12 | Некоторый итог

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

Да ладно Шиндошс, там и на других платформах полно неочевидных проблем, особенно на ЖМУ/Пинусе. Пытаться собрать статический Qt я начал ну наверное году в 2012, к 2018 у меня это стало в основном получаться и я написал эту статью, но сейчас 2021 год, а я до сих натыкаюсь на проблемы, решение которых надо выискивать по всем интернетам, потому что документация о них скромно умалчивает. Ну и конечно с появлением новых версий Qt появляются новые проблемы со сборкой.

Пиздец нахуй блядь!

2023-09-19 | Qt 5.15.2, Windows 10/11, MinGW x32 from MSYS2

All of a sudden today I needed to do something horrible: I needed to build static Qt 5.15.2 on Windows 10 (and then on Windows 11) x64 host using MinGW x32 toolchain. The Qt version, MinGW and x32 target were strict requirements, so I had to make it work with exactly those.

MSVC x32

First I tried to build static Qt 5.15.2 with MSVC 143 (VS 2022) x32, just to check that it does build at all:

> call "E:\tools\vs\vs2022\VC\Auxiliary\Build\vcvars32.bat"
**********************************************************************
** Visual Studio 2022 Developer Command Prompt v17.5.5
** Copyright (c) 2022 Microsoft Corporation
**********************************************************************
[vcvarsall.bat] Environment initialized for: 'x86'

> cd e:\tools\qt
> mkdir 5.15.2-static-x32

> cd e:\tools\qt\src\5.15.2
> rmdir /Q /S build
> mkdir build
> cd build

> ..\configure.bat -static -release -no-pch -prefix "e:\tools\qt\5.15.2-static-x32" -skip qtwebengine -nomake tests -nomake examples
> jom
> jom install

> dumpbin ..\..\..\5.15.2-static-x32\lib\Qt5Core.lib /headers | findstr machine
14C machine (x86)

The build went just fine out of the box, I didn’t need to touch the original sources at all.

MinGW x32

And then I started my in-and-out-twenty-minutes-adventure of building static Qt with MinGW.

The very first issue I’ve stumbled upon is: where does one get the MinGW from? Before I was getting it from Qt installer, but I stopped using that anal probe some years ago, so this isn’t an option anymore.

Long story short, I didn’t find a MinGW that would work, as apparently just MinGW alone is not enough, because I was getting errors like:

error: 'KEY_WOW64_32KEY' was not declared in this scope
error: '_popen' was not declared in this scope
error: '_pclose' was not declared in this scope

And so apparently one needs to have some environment for it to run in, and one such environment is MSYS2. I do have Git BASH too, but there was something still missing there.

So, download MSYS2 installer, install it and, as we are targeting x32 build, launch /path/to/msys2/mingw32.exe. Then, based on these instructions, update the system packages:

$ pacman -Syu

Yes, to my surprise, it uses a proper package manager (that being pacman), which certainly helps with getting the right stuff.

That command will eventually close the MSYS2 terminal during the update, so launch it again (/path/to/msys2/mingw32.exe) and repeat the last command to finish the update.

Then install MinGW x32 toolchain (if you’ll later need x64 toolchain, that one is available as mingw-w64-x86_64-toolchain):

$ pacman -S mingw-w64-i686-toolchain
:: There are 19 members in group mingw-w64-i686-toolchain:
:: Repository mingw32
   1) mingw-w64-i686-binutils  2) mingw-w64-i686-crt-git  3) mingw-w64-i686-gcc  4) mingw-w64-i686-gcc-ada  5) mingw-w64-i686-gcc-fortran  6) mingw-w64-i686-gcc-libgfortran  7) mingw-w64-i686-gcc-libs
   8) mingw-w64-i686-gcc-objc  9) mingw-w64-i686-gdb  10) mingw-w64-i686-gdb-multiarch  11) mingw-w64-i686-headers-git  12) mingw-w64-i686-libgccjit  13) mingw-w64-i686-libmangle-git
   14) mingw-w64-i686-libwinpthread-git  15) mingw-w64-i686-make  16) mingw-w64-i686-pkgconf  17) mingw-w64-i686-tools-git  18) mingw-w64-i686-winpthreads-git  19) mingw-w64-i686-winstorecompat-git

I got the following versions after the installation was done:

$ pacman -Qe
base 2022.06-1
filesystem 2023.02.07-1
mingw-w64-i686-binutils 2.41-2
mingw-w64-i686-crt-git 11.0.0.r159.g0605217f5-1
mingw-w64-i686-gcc 13.2.0-2
mingw-w64-i686-gcc-ada 13.2.0-2
mingw-w64-i686-gcc-fortran 13.2.0-2
mingw-w64-i686-gcc-libgfortran 13.2.0-2
mingw-w64-i686-gcc-libs 13.2.0-2
mingw-w64-i686-gcc-objc 13.2.0-2
mingw-w64-i686-gdb 13.2-3
mingw-w64-i686-gdb-multiarch 13.2-3
mingw-w64-i686-headers-git 11.0.0.r159.g0605217f5-1
mingw-w64-i686-libgccjit 13.2.0-2
mingw-w64-i686-libmangle-git 11.0.0.r159.g0605217f5-1
mingw-w64-i686-libwinpthread-git 11.0.0.r159.g0605217f5-1
mingw-w64-i686-make 4.4-2
mingw-w64-i686-pkgconf 1~2.0.3-1
mingw-w64-i686-tools-git 11.0.0.r159.g0605217f5-1
mingw-w64-i686-winpthreads-git 11.0.0.r159.g0605217f5-1
mingw-w64-i686-winstorecompat-git 11.0.0.r159.g0605217f5-1
msys2-runtime 3.4.9-2

Check that the tools are available:

$ gcc --version
gcc.exe (Rev2, Built by MSYS2 project) 13.2.0
Copyright (C) 2023 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ g++ --version
g++.exe (Rev2, Built by MSYS2 project) 13.2.0
Copyright (C) 2023 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ mingw32-make.exe --version
GNU Make 4.4
Built for Windows32
Copyright (C) 1988-2022 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Set an “alias” for make:

$ export MAKE="mingw32-make"

…otherwise it will fail complaining that there is no make available:

You don't seem to have 'make' or 'gmake' in your PATH.
Cannot proceed.

Configure Qt:

$ cd /e/tools/qt
$ mkdir 5.15.2-static-x32-mingw

$ cd /e/tools/qt/src/5.15.2
$ rm -r ./build
$ mkdir build && cd $_

$ ../configure -static -release -no-pch -prefix "e:/tools/qt/5.15.2-static-x32-mingw" \
  -platform win32-g++ -skip qtwebengine -nomake tests -nomake examples

The -platform win32-g++ is important, otherwise you’ll get:

The build script does not currently recognize all
  platforms supported by Qt.
  Rerun this script with a -platform option listed to
  set the system/compiler combination you use.

Anyway, the configuration will fail like this:

In file included from E:/tools/qt/src/5.15.2/qtbase/include/QtCore/qfloat16.h:1,
                 from E:/tools/qt/src/5.15.2/qtbase/src/corelib/global/qendian.h:44,
                 from E:/tools/qt/src/5.15.2/qtbase/include/QtCore/qendian.h:1,
                 from E:/tools/qt/src/5.15.2/qtbase/src/corelib/codecs/qutfcodec.cpp:43:
E:/tools/qt/src/5.15.2/qtbase/src/corelib/global/qfloat16.h:300:7: error: 'numeric_limits' is not a class template
  300 | class numeric_limits<QT_PREPEND_NAMESPACE(qfloat16)> : public numeric_limits<float>

To fix that, add #include <limits> to e:/tools/qt/src/5.15.2/qtbase/src/corelib/global/qfloat16.h and e:/tools/qt/src/5.15.2/qtbase/src/corelib/text/qbytearraymatcher.h and run configuration again. Then it should configure, but there will likely be a warning 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 add that option (-opengl desktop) to the configure command and run it again. Then it should succeed for good. Here’s my configuration output, just in case:

Build type: win32-g++ (i386, CPU features: mmx sse sse2)
Compiler: gcc 13.2.0
Configuration: sse2 aesni sse3 ssse3 sse4_1 sse4_2 avx avx2 avx512f avx512bw avx512cd avx512dq avx512er avx512ifma avx512pf avx512vbmi avx512vl compile_examples f16c largefile rdrnd rdseed shani x86SimdAlways release c++11 c++14 c++17 c++1z concurrent dbus no-pkg-config static stl
Build options:
  Mode ................................... release
  Optimize release build for size ........ no
  Building shared libraries .............. no
  Using C standard ....................... C11
  Using C++ standard ..................... C++17
  Relocatable ............................ no
  Using precompiled headers .............. no
  Using LTCG ............................. no
  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
    Intrinsics without -mXXX option ...... yes
  Build parts ............................ libs tools
  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
  udev ................................... no
  Using system zlib ...................... yes
  Zstandard support ...................... yes
Qt Core:
  DoubleConversion ....................... yes
    Using system DoubleConversion ........ no
  GLib ................................... no
  iconv .................................. no
  ICU .................................... no
  Built-in copy of the MIME database ..... yes
  Tracing backend ........................ <none>
  Logging backends:
    journald ............................. no
    syslog ............................... no
    slog2 ................................ no
  PCRE2 .................................. yes
    Using system PCRE2 ................... no
Qt Network:
  getifaddrs() ........................... no
  IPv6 ifname ............................ no
  libproxy ............................... no
  Schannel ............................... no
  OpenSSL ................................ yes
    Qt directly linked to OpenSSL ........ no
  OpenSSL 1.1 ............................ yes
  DTLS ................................... yes
  OCSP-stapling .......................... yes
  SCTP ................................... no
  Use system proxies ..................... yes
  GSSAPI ................................. no
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
  Text formats:
    HtmlParser ........................... yes
    CssParser ............................ yes
    OdfWriter ............................ yes
    MarkdownReader ....................... yes
      Using system libmd4c ............... no
    MarkdownWriter ....................... yes
  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 ................................. yes
  Session Management ..................... yes
Features used by QPA backends:
  evdev .................................. no
  libinput ............................... no
  INTEGRITY HID .......................... no
  mtdev .................................. no
  tslib .................................. no
  xkbcommon .............................. no
  X11 specific:
    XLib ................................. no
    XCB Xlib ............................. no
    EGL on X11 ........................... no
    xkbcommon-x11 ........................ no
QPA backends:
  DirectFB ............................... no
  EGLFS .................................. no
  LinuxFB ................................ no
  VNC .................................... no
  Windows:
    Direct 2D ............................ yes
    DirectWrite .......................... yes
    DirectWrite 2 ........................ yes
Qt Sql:
  SQL item models ........................ yes
Qt Widgets:
  GTK+ ................................... no
  Styles ................................. Fusion Windows WindowsVista
Qt PrintSupport:
  CUPS ................................... no
Qt Sql Drivers:
  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 Testlib:
  Tester for item models ................. yes
Serial Port:
  ntddmodm ............................... yes
Qt SerialBus:
  Socket CAN ............................. no
  Socket CAN FD .......................... no
  SerialPort Support ..................... yes
Further Image Formats:
  JasPer ................................. no
  MNG .................................... no
  TIFF ................................... yes
    Using system libtiff ................. no
  WEBP ................................... yes
    Using system libwebp ................. no
Qt QML:
  QML network support .................... yes
  QML debugging and profiling support .... yes
  QML just-in-time compiler .............. yes
  QML sequence object .................... yes
  QML XML http request ................... yes
  QML Locale ............................. yes
Qt QML Models:
  QML list model ......................... yes
  QML delegate model ..................... yes
Qt Quick:
  Direct3D 12 ............................ yes
  AnimatedImage item ..................... yes
  Canvas item ............................ yes
  Support for Qt Quick Designer .......... yes
  Flipable item .......................... yes
  GridView item .......................... yes
  ListView item .......................... yes
  TableView item ......................... yes
  Path support ........................... yes
  PathView item .......................... yes
  Positioner items ....................... yes
  Repeater item .......................... yes
  ShaderEffect item ...................... yes
  Sprite item ............................ yes
QtQuick3D:
  Assimp ................................. yes
  System Assimp .......................... no
Qt Scxml:
  ECMAScript data model for QtScxml ...... yes
Qt Gamepad:
  SDL2 ................................... no
Qt 3D:
  Assimp ................................. yes
  System Assimp .......................... 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 Renderers:
  OpenGL Renderer ........................ yes
  RHI Renderer ........................... no
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
  Native Win32 Bluetooth ................. no
  WinRT Bluetooth API (desktop & UWP) .... no
  WinRT advanced bluetooth low energy 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:
  Qt.labs.location experimental QML plugin . yes
  Geoservice plugins:
    OpenStreetMap ........................ yes
    HERE ................................. yes
    Esri ................................. yes
    Mapbox ............................... yes
    MapboxGL ............................. yes
    Itemsoverlay ......................... yes
QtXmlPatterns:
  XML schema support ..................... 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 ............... yes
Qt TextToSpeech:
  Flite .................................. no
  Flite with ALSA ........................ no
  Speech Dispatcher ...................... no
Qt Tools:
  Qt Assistant ........................... yes
  Qt Designer ............................ yes
  Qt Distance Field Generator ............ yes
  kmap2qmap .............................. yes
  Qt Linguist ............................ yes
  Mac Deployment Tool .................... no
  makeqpf ................................ yes
  pixeltool .............................. yes
  qdbus .................................. yes
  qev .................................... yes
  Qt Attributions Scanner ................ yes
  qtdiag ................................. yes
  qtpaths ................................ yes
  qtplugininfo ........................... yes
  Windows deployment tool ................ yes
  WinRT Runner Tool ...................... no
Qt Tools:
  QDoc ................................... 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.

WARNING: QDoc will not be compiled, probably because libclang could not be located. This means that you cannot build the Qt documentation.

Either ensure that llvm-config is in your PATH environment variable, or set LLVM_INSTALL_DIR to the location of your llvm installation.
On Linux systems, you may be able to install libclang by installing the libclang-dev or libclang-devel package, depending on your distribution.
On macOS, you can use Homebrew's llvm package.
On Windows, you must set LLVM_INSTALL_DIR to the installation path.

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 'e:\tools\qt\5.15.2-static-x32-mingw'.

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

You can now try to build it:

$ mingw32-make -j 16

But soon enough it will fail with this:

E:/tools/qt/src/5.15.2/qtactiveqt/src/activeqt/control/qaxfactory.h:85:32:E:/tools/qt/src/5.15.2/qtdeclarative/src/3rdparty/masm/yarr/Yarr.h:46:44:  note: error:   by ''virtual const QMetaObject* QAxFactory::numeric_limitsmetaObject' is not a member of '(const QString&) conststd'
   85 |     virtual const QMetaObject *'
   46 | static const unsigned offsetNoMatch = std::metaObjectnumeric_limits(const QString &key) const = 0;
      |                                <unsigned>::max();
      |                                            ^~~~~~~~~~^~~~~~~~~~~~~~

E:/tools/qt/src/5.15.2/qtdeclarative/src/3rdparty/masm/yarr/Yarr.h:46:59: error: expected primary-expression before 'unsigned'
   46 | static const unsigned offsetNoMatch = std::numeric_limits<unsigned>::max();
      |                                                           ^~~~~~~~

You can try to reconfigure Qt with -c++std c++11 (and check that it now has C++11 in the configuration summary) and try building again. I’d actually recommend to use exactly C++11 standard, since it’s a rather old Qt version, and probably it is to be expected to encounter more errors trying to compile with C++17.

With C++11 standard the error will still be there, but a little bit different:

E:/tools/qt/src/5.15.2/qtdeclarative/src/3rdparty/masm/yarr/Yarr.h:46:44: error: 'numeric_limits' is not a member of 'std'
   46 | static const unsigned offsetNoMatch = std::numeric_limits<unsigned>::max();
      |                                            ^~~~~~~~~~~~~~
E:/tools/qt/src/5.15.2/qtdeclarative/src/3rdparty/masm/yarr/Yarr.h:46:59: error: expected primary-expression before 'unsigned'
   46 | static const unsigned offsetNoMatch = std::numeric_limits<unsigned>::max();
      |                                                           ^~~~~~~~

…which is actually the same error that we already saw during configuration, so add #include <limits> to /e/tools/qt/src/5.15.2/qtdeclarative/src/3rdparty/masm/yarr/Yarr.h too and… except that it is already there. But actually it’s not, because it’s wrong: you need to replace #include <limits.h> with #include <limits>. Then try building again.

It will proceed, but will fail with a different error later:

mingw32-make[6]: Entering directory 'E:/tools/qt/src/5.15.2/build/qtdeclarative/src/plugins/scenegraph/d3d12'
fxc.exe /nologo /E VS_VertexColor /T vs_5_0 /Fh vs_vertexcolor.hlslh E:/tools/qt/src/5.15.2/qtdeclarative/src/plugins/scenegraph/d3d12/shaders/vertexcolor.hlsl
process_begin: CreateProcess(NULL, fxc.exe /nologo /E VS_VertexColor /T vs_5_0 /Fh vs_vertexcolor.hlslh E:/tools/qt/src/5.15.2/qtdeclarative/src/plugins/scenegraph/d3d12/shaders/vertexcolor.hlsl, ...) failed.
make (e=2): The system cannot find the file specified.

This one is about not finding fxc.exe, as it seems, which you should have somewhere in your variant of e:\Windows Kits\10\bin\10.0.20348.0\x86\fxc.exe (use the x86 version, since we are in x32). So add it to PATH and try again:

$ export PATH=/e/Windows\ Kits/10/bin/10.0.20348.0/x86:$PATH
$ mingw32-make -j 16

And indeed, that helps it to proceed further. But then I got this weird error on Windows 11:

E:/tools/qt/src/5.15.2/build/qtdeclarative/src/imports/testlib/qmltyperegistrar_wrapper.sh: line 6: E:\tools\qt\src\5.15.2\build\qtdeclarative\bin\qmltyperegistrar.exe: Bad address
E:/tools/qt/src/5.15.2/build/qtdeclarative/src/imports/testlib/qmltyperegistrar_wrapper.sh: line 6: E:\tools\qt\src\5.15.2\build\qtdeclarative\bin\qmltyperegistrar.exe: No error
mingw32-make[5]: *** [Makefile.Release:145: qmltestplugin_qmltyperegistrations.cpp] Error 126

What the fuck is this shit. And I didn’t get it on Windows 10, by the way. I googled for that one and found the following workaround:

$ export MSYS2_ARG_CONV_EXCL='*'

Then the build continues. But! When I needed to build the whole thing again after cleaning the build folder, the configuration suddenly failed like this:

Preparing build tree...
Creating qmake....................................................................................................Done.
Cannot find file: \e\tools\qt\src\5.15.2.

Good thing I remembered exporting this variable, so I unset it:

$ unset MSYS2_ARG_CONV_EXCL

and re-run the configuration, and then it succeeded. And then I exported that variable again, since it does resolve the qmltyperegistrar error.

Anyway, coming back to the build at hand, after that it failed with several other errors:

E:/tools/qt/src/5.15.2/qtdeclarative/src/plugins/scenegraph/d3d12/qsgd3d12engine.cpp:241:60: error: '_uuidof' was not declared in this scope
  241 |         if (SUCCEEDED(D3D12CreateDevice(adapter.Get(), fl, _uuidof(ID3D12Device), nullptr))) {
      |                                                            ^~~~~~~
E:/tools/qt/src/5.15.2/qtdeclarative/src/plugins/scenegraph/d3d12/qsgd3d12shadereffectnode.cpp: In member function 'virtual void QSGD3D12ShaderCompileTask::run()':
E:/tools/qt/src/5.15.2/qtdeclarative/src/plugins/scenegraph/d3d12/qsgd3d12shadereffectnode.cpp:785:54: warning: format '%x' expects argument of type 'unsigned int', but argument 3 has type 'HRESULT' {aka 'long int'} [-Wformat=]
  785 |         qWarning("HLSL shader compilation failed: 0x%x", hr);
      |                                                     ~^   ~~
      |                                                      |   |
      |                                                      |   HRESULT {aka long int}
      |                                                      unsigned int
      |                                                     %lx
E:/tools/qt/src/5.15.2/qtdeclarative/src/plugins/scenegraph/d3d12/qsgd3d12shadereffectnode.cpp: In member function 'bool QSGD3D12GuiThreadShaderEffectManager::reflect(QSGGuiThreadShaderEffectManager::ShaderInfo*)':
E:/tools/qt/src/5.15.2/qtdeclarative/src/plugins/scenegraph/d3d12/qsgd3d12shadereffectnode.cpp:857:52: warning: format '%x' expects argument of type 'unsigned int', but argument 3 has type 'HRESULT' {aka 'long int'} [-Wformat=]
  857 |         qWarning("D3D shader reflection failed: 0x%x", hr);
      |                                                   ~^   ~~
      |                                                    |   |
      |                                                    |   HRESULT {aka long int}
      |                                                    unsigned int
      |                                                   %lx
E:/tools/qt/src/5.15.2/qtdeclarative/src/plugins/scenegraph/d3d12/qsgd3d12engine.cpp: In member function 'void QSGD3D12EnginePrivate::initialize(WId, const QSize&, float, int, bool)':
E:/tools/qt/src/5.15.2/qtdeclarative/src/plugins/scenegraph/d3d12/qsgd3d12engine.cpp:758:16: error: 'ID3D12Debug' was not declared in this scope; did you mean 'ID3D10Debug'?
  758 |         ComPtr<ID3D12Debug> debugController;
      |                ^~~~~~~~~~~
      |                ID3D10Debug
E:/tools/qt/src/5.15.2/qtdeclarative/src/plugins/scenegraph/d3d12/qsgd3d12engine.cpp:758:27: error: template argument 1 is invalid
  758 |         ComPtr<ID3D12Debug> debugController;
      |                           ^
E:/tools/qt/src/5.15.2/qtdeclarative/src/plugins/scenegraph/d3d12/qsgd3d12engine.cpp:759:46: error: invalid type argument of unary '*' (have 'int')
  759 |         if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debugController))))
      |                                              ^~~~~~~~~~~~
E:/tools/qt/src/5.15.2/qtdeclarative/src/plugins/scenegraph/d3d12/qsgd3d12engine.cpp:759:46: error: no matching function for call to '__mingw_uuidof<<expression error> >()'
  759 |         if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debugController))))
      |                                              ^~~~~~~~~~~~

To fix those edit e:\tools\qt\src\5.15.2\qtdeclarative\src\plugins\scenegraph\d3d12\qsgd3d12engine.cpp:

// ...

#include <d3d12sdklayers.h>

// ...

//HRESULT hr = D3D12CreateDevice(adapter.Get(), fl, _uuidof(ID3D12Device), nullptr);
HRESULT hr = D3D12CreateDevice(adapter.Get(), fl, __uuidof(ID3D12Device), nullptr);

//if (SUCCEEDED(D3D12CreateDevice(adapter.Get(), fl, _uuidof(ID3D12Device), nullptr))) {
if (SUCCEEDED(D3D12CreateDevice(adapter.Get(), fl, __uuidof(ID3D12Device), nullptr))) {

// ...

…or you could probably just reconfigure Qt with -no-feature-d3d12, especially if you or/and your users will be building applications for running on machines without DirectX 12.

Trying to continue the build, you’ll get this one again:

E:/tools/qt/src/5.15.2/qtdeclarative/src/qmldebug/qqmlprofilerevent_p.h:314:65: error: 'numeric_limits' is not a member of std

Add #include <limits> to e:/tools/qt/src/5.15.2/qtdeclarative/src/qmldebug/qqmlprofilerevent_p.h too.

Then it will proceed, but will fail with something else later:

E:/tools/qt/src/5.15.2/qtconnectivity/src/bluetooth/qbluetoothservicediscoveryagent_win.cpp:276:43: error: invalid conversion from 'BOOL (*)(ULONG, LPBYTE, ULONG, LPVOID)' {aka 'int (*)(long unsigned int, unsigned char*, long unsigned in
 {aka 'int (__attribute__((stdcall)) *)(long unsigned int, unsigned char*, long unsigned int, void*)'} [-fpermissive]
  276 |                                           bluetoothSdpCallback,
      |                                           ^~~~~~~~~~~~~~~~~~~~
      |                                           |
      |                                           BOOL (*)(ULONG, LPBYTE, ULONG, LPVOID) {aka int (*)(long unsigned int, unsigned char*, long unsigned int, void*)}

Patch for that problem is here. I would have never figured it out on my own. Apply the changes and continue the build.

Next error will be this:

E:/tools/qt/src/5.15.2/qtmultimedia/src/plugins/wmf/player/mfvideorenderercontrol.cpp:2334:68: error: 'virtual void {anonymous}::MediaStream::customEvent(QEvent*)' is protected within this context
 2334 |         static_cast<MediaStream*>(childEvent->child())->customEvent(event);
      |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~

Patch for this problem is here. Again, it is very unlikely that I would ever be able to figure it out myself. Apply the changes and continue.

And then it fucking finally builds to the end! To make sure that it did in fact succeed, check the exit code:

$ echo $?
0

If it is non-zero but the build has finished without printing any errors in the end, run the build again, first with -j and check the exit code, and if it is still non-zero, then try yet again but this time without -j, so it would stop on the first error without spamming the output with other jobs leftovers.

Anyway, mine has succeeded, but at some point later I realized that I forgot to add configuration option for the static runtime, so I needed to reconfigure and rebuild again. And so the final configure command with all the additions is now this:

$ ../configure -static -release -no-pch -prefix "e:/tools/qt/5.15.2-static-x32-mingw" \
  -platform win32-g++ -skip qtwebengine -nomake tests -nomake examples \
  -opengl desktop -c++std c++11 -static-runtime -no-feature-d3d12

And also just in case here’s a diff output for all the changes to the original Qt sources that I had to make in order to build static Qt 5.15.2 with MinGW.

If you are curious, the build time on Intel Core i9-9900K CPU with 8/16 cores was about 31 minute (30:47).

Using the MinGW build in Qt Creator

Let’s now add this build to Qt Creator and try to use it.

First add C and C++ compilers (note the ABI value, it should auto-detect when you’ll browse for gcc and g++ executables):

Qt Creator, MinGW, C compiler

Qt Creator, MinGW, C++ compiler

Then debugger:

Qt Creator, MinGW, debugger

Then the Qt version that you’ve just built:

Qt Creator, Qt version

And finally the kit:

Qt Creator, kit

As for the application to be built with this kit, of course we’ll take Color Corners.

With qmake

First I tried to build it with qmake (by the way, just look at how big that project file is (4 lines) in comparison with CMake (bloody 157 lines)).

Configuration and build output:

15:06:27: Running steps for project color-corners...
15:06:27: Starting: "E:\tools\qt\5.15.2-static-x32-mingw\bin\qmake.exe" E:\code\color-corners\color-corners.pro -spec win32-g++ "CONFIG+=qtquickcompiler"
Info: creating stash file E:\code\color-corners\build\color-corners-Qt_5_15_2_x32_MinGW-Release\.qmake.stash
15:06:28: The process "E:\tools\qt\5.15.2-static-x32-mingw\bin\qmake.exe" exited normally.
15:06:28: Starting: "E:\tools\msys2\mingw32\bin\mingw32-make.exe" -f E:/code/color-corners/build/color-corners-Qt_5_15_2_x32_MinGW-Release/Makefile qmake_all
mingw32-make: Nothing to be done for 'qmake_all'.
15:06:28: The process "E:\tools\msys2\mingw32\bin\mingw32-make.exe" exited normally.
15:06:28: Starting: "E:\tools\msys2\mingw32\bin\mingw32-make.exe" -j16
E:/tools/msys2/mingw32/bin/mingw32-make.exe -f Makefile.Release
mingw32-make[1]: Entering directory 'E:/code/color-corners/build/color-corners-Qt_5_15_2_x32_MinGW-Release'
g++ -c -fno-keep-inline-dllexport -O2 -Wall -Wextra -Wextra -ffunction-sections -fdata-sections -fexceptions -mthreads -DUNICODE -D_UNICODE -DWIN32 -DMINGW_HAS_SECURE_API=1 -DQT_NO_DEBUG -DQT_QUICK_LIB -DQT_GUI_LIB -DQT_QMLMODELS_LIB -DQT_QML_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_NEEDS_QMAIN -I../../../color-corners -I. -I../../../../tools/qt/5.15.2-static-x32-mingw/include -I../../../../tools/qt/5.15.2-static-x32-mingw/include/QtQuick -I../../../../tools/qt/5.15.2-static-x32-mingw/include/QtGui -I../../../../tools/qt/5.15.2-static-x32-mingw/include/QtQmlModels -I../../../../tools/qt/5.15.2-static-x32-mingw/include/QtQml -I../../../../tools/qt/5.15.2-static-x32-mingw/include/QtNetwork -I../../../../tools/qt/5.15.2-static-x32-mingw/include/QtCore -Irelease -IE:/tools/vulkan-sdk/include -I../../../../tools/qt/5.15.2-static-x32-mingw/mkspecs/win32-g++  -o release/main.o ../../main.cpp
g++ -c -fno-keep-inline-dllexport -O2 -Wall -Wextra -Wextra -ffunction-sections -fdata-sections -fexceptions -mthreads -DUNICODE -D_UNICODE -DWIN32 -DMINGW_HAS_SECURE_API=1 -DQT_NO_DEBUG -DQT_QUICK_LIB -DQT_GUI_LIB -DQT_QMLMODELS_LIB -DQT_QML_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_NEEDS_QMAIN -I../../../color-corners -I. -I../../../../tools/qt/5.15.2-static-x32-mingw/include -I../../../../tools/qt/5.15.2-static-x32-mingw/include/QtQuick -I../../../../tools/qt/5.15.2-static-x32-mingw/include/QtGui -I../../../../tools/qt/5.15.2-static-x32-mingw/include/QtQmlModels -I../../../../tools/qt/5.15.2-static-x32-mingw/include/QtQml -I../../../../tools/qt/5.15.2-static-x32-mingw/include/QtNetwork -I../../../../tools/qt/5.15.2-static-x32-mingw/include/QtCore -Irelease -IE:/tools/vulkan-sdk/include -I../../../../tools/qt/5.15.2-static-x32-mingw/mkspecs/win32-g++  -o release/color-corners_plugin_import.o E:/code/color-corners/build/color-corners-Qt_5_15_2_x32_MinGW-Release/color-corners_plugin_import.cpp
g++ -c -fno-keep-inline-dllexport -O2 -Wall -Wextra -Wextra -ffunction-sections -fdata-sections -fexceptions -mthreads -DUNICODE -D_UNICODE -DWIN32 -DMINGW_HAS_SECURE_API=1 -DQT_NO_DEBUG -DQT_QUICK_LIB -DQT_GUI_LIB -DQT_QMLMODELS_LIB -DQT_QML_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_NEEDS_QMAIN -I../../../color-corners -I. -I../../../../tools/qt/5.15.2-static-x32-mingw/include -I../../../../tools/qt/5.15.2-static-x32-mingw/include/QtQuick -I../../../../tools/qt/5.15.2-static-x32-mingw/include/QtGui -I../../../../tools/qt/5.15.2-static-x32-mingw/include/QtQmlModels -I../../../../tools/qt/5.15.2-static-x32-mingw/include/QtQml -I../../../../tools/qt/5.15.2-static-x32-mingw/include/QtNetwork -I../../../../tools/qt/5.15.2-static-x32-mingw/include/QtCore -Irelease -IE:/tools/vulkan-sdk/include -I../../../../tools/qt/5.15.2-static-x32-mingw/mkspecs/win32-g++  -o release/color-corners_qml_plugin_import.o E:/code/color-corners/build/color-corners-Qt_5_15_2_x32_MinGW-Release/color-corners_qml_plugin_import.cpp
'E:\tools\qt\5.15.2-static-x32-mingw\bin\qmlcachegen.exe' --resource=E:/code/color-corners/qml.qrc -o release/main_qml.cpp ../../main.qml
'E:\tools\qt\5.15.2-static-x32-mingw\bin\qmlcachegen.exe' --resource-file-mapping=E:/code/color-corners/qml.qrc=E:/code/color-corners/build/color-corners-Qt_5_15_2_x32_MinGW-Release/qml_qmlcache.qrc -o release/qmlcache_loader.cpp ../../qml.qrc
'E:\tools\qt\5.15.2-static-x32-mingw\bin\rcc.exe' -name qml_qmlcache qml_qmlcache.qrc -o release/qrc_qml_qmlcache.cpp
g++ -c -fno-keep-inline-dllexport -O2 -Wall -Wextra -Wextra -ffunction-sections -fdata-sections -fexceptions -mthreads -DUNICODE -D_UNICODE -DWIN32 -DMINGW_HAS_SECURE_API=1 -DQT_NO_DEBUG -DQT_QUICK_LIB -DQT_GUI_LIB -DQT_QMLMODELS_LIB -DQT_QML_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_NEEDS_QMAIN -I../../../color-corners -I. -I../../../../tools/qt/5.15.2-static-x32-mingw/include -I../../../../tools/qt/5.15.2-static-x32-mingw/include/QtQuick -I../../../../tools/qt/5.15.2-static-x32-mingw/include/QtGui -I../../../../tools/qt/5.15.2-static-x32-mingw/include/QtQmlModels -I../../../../tools/qt/5.15.2-static-x32-mingw/include/QtQml -I../../../../tools/qt/5.15.2-static-x32-mingw/include/QtNetwork -I../../../../tools/qt/5.15.2-static-x32-mingw/include/QtCore -Irelease -IE:/tools/vulkan-sdk/include -I../../../../tools/qt/5.15.2-static-x32-mingw/mkspecs/win32-g++  -o release/main_qml.o release/main_qml.cpp
g++ -c -fno-keep-inline-dllexport -O2 -Wall -Wextra -Wextra -ffunction-sections -fdata-sections -fexceptions -mthreads -DUNICODE -D_UNICODE -DWIN32 -DMINGW_HAS_SECURE_API=1 -DQT_NO_DEBUG -DQT_QUICK_LIB -DQT_GUI_LIB -DQT_QMLMODELS_LIB -DQT_QML_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_NEEDS_QMAIN -I../../../color-corners -I. -I../../../../tools/qt/5.15.2-static-x32-mingw/include -I../../../../tools/qt/5.15.2-static-x32-mingw/include/QtQuick -I../../../../tools/qt/5.15.2-static-x32-mingw/include/QtGui -I../../../../tools/qt/5.15.2-static-x32-mingw/include/QtQmlModels -I../../../../tools/qt/5.15.2-static-x32-mingw/include/QtQml -I../../../../tools/qt/5.15.2-static-x32-mingw/include/QtNetwork -I../../../../tools/qt/5.15.2-static-x32-mingw/include/QtCore -Irelease -IE:/tools/vulkan-sdk/include -I../../../../tools/qt/5.15.2-static-x32-mingw/mkspecs/win32-g++  -o release/qmlcache_loader.o release/qmlcache_loader.cpp
g++ -c -fno-keep-inline-dllexport -O2 -Wall -Wextra -Wextra -ffunction-sections -fdata-sections -fexceptions -mthreads -DUNICODE -D_UNICODE -DWIN32 -DMINGW_HAS_SECURE_API=1 -DQT_NO_DEBUG -DQT_QUICK_LIB -DQT_GUI_LIB -DQT_QMLMODELS_LIB -DQT_QML_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_NEEDS_QMAIN -I../../../color-corners -I. -I../../../../tools/qt/5.15.2-static-x32-mingw/include -I../../../../tools/qt/5.15.2-static-x32-mingw/include/QtQuick -I../../../../tools/qt/5.15.2-static-x32-mingw/include/QtGui -I../../../../tools/qt/5.15.2-static-x32-mingw/include/QtQmlModels -I../../../../tools/qt/5.15.2-static-x32-mingw/include/QtQml -I../../../../tools/qt/5.15.2-static-x32-mingw/include/QtNetwork -I../../../../tools/qt/5.15.2-static-x32-mingw/include/QtCore -Irelease -IE:/tools/vulkan-sdk/include -I../../../../tools/qt/5.15.2-static-x32-mingw/mkspecs/win32-g++  -o release/qrc_qml_qmlcache.o release/qrc_qml_qmlcache.cpp
g++ -Wl,-s -static -Wl,--gc-sections -Wl,-subsystem,windows -mthreads -o release/color-corners.exe release/main.o release/color-corners_plugin_import.o release/color-corners_qml_plugin_import.o release/main_qml.o release/qmlcache_loader.o release/qrc_qml_qmlcache.o  E:/tools/qt/5.15.2-static-x32-mingw/plugins/platforms/libqwindows.a -ldwmapi -lwinspool -lshlwapi -lwtsapi32 E:/tools/qt/5.15.2-static-x32-mingw/lib/libQt5EventDispatcherSupport.a E:/tools/qt/5.15.2-static-x32-mingw/lib/libQt5FontDatabaseSupport.a E:/tools/qt/5.15.2-static-x32-mingw/lib/libqtfreetype.a -ldwrite -ld2d1 E:/tools/qt/5.15.2-static-x32-mingw/lib/libQt5ThemeSupport.a E:/tools/qt/5.15.2-static-x32-mingw/lib/libQt5AccessibilitySupport.a E:/tools/qt/5.15.2-static-x32-mingw/lib/libQt5VulkanSupport.a E:/tools/qt/5.15.2-static-x32-mingw/lib/libQt5WindowsUIAutomationSupport.a E:/tools/qt/5.15.2-static-x32-mingw/plugins/imageformats/libqgif.a E:/tools/qt/5.15.2-static-x32-mingw/plugins/imageformats/libqicns.a E:/tools/qt/5.15.2-static-x32-mingw/plugins/imageformats/libqico.a E:/tools/qt/5.15.2-static-x32-mingw/plugins/imageformats/libqjpeg.a E:/tools/qt/5.15.2-static-x32-mingw/plugins/imageformats/libqtga.a E:/tools/qt/5.15.2-static-x32-mingw/plugins/imageformats/libqtiff.a E:/tools/qt/5.15.2-static-x32-mingw/plugins/imageformats/libqwbmp.a E:/tools/qt/5.15.2-static-x32-mingw/plugins/imageformats/libqwebp.a E:/tools/qt/5.15.2-static-x32-mingw/plugins/qmltooling/libqmldbg_debugger.a E:/tools/qt/5.15.2-static-x32-mingw/plugins/qmltooling/libqmldbg_inspector.a E:/tools/qt/5.15.2-static-x32-mingw/plugins/qmltooling/libqmldbg_local.a E:/tools/qt/5.15.2-static-x32-mingw/plugins/qmltooling/libqmldbg_messages.a E:/tools/qt/5.15.2-static-x32-mingw/plugins/qmltooling/libqmldbg_native.a E:/tools/qt/5.15.2-static-x32-mingw/plugins/qmltooling/libqmldbg_nativedebugger.a E:/tools/qt/5.15.2-static-x32-mingw/plugins/qmltooling/libqmldbg_preview.a E:/tools/qt/5.15.2-static-x32-mingw/plugins/qmltooling/libqmldbg_profiler.a E:/tools/qt/5.15.2-static-x32-mingw/plugins/qmltooling/libqmldbg_quickprofiler.a E:/tools/qt/5.15.2-static-x32-mingw/plugins/qmltooling/libqmldbg_server.a E:/tools/qt/5.15.2-static-x32-mingw/lib/libQt5PacketProtocol.a E:/tools/qt/5.15.2-static-x32-mingw/plugins/qmltooling/libqmldbg_tcp.a E:/tools/qt/5.15.2-static-x32-mingw/plugins/bearer/libqgenericbearer.a E:/tools/qt/5.15.2-static-x32-mingw/qml/QtQuick.2/libqtquick2plugin.a E:/tools/qt/5.15.2-static-x32-mingw/qml/QtQuick/Window.2/libwindowplugin.a E:/tools/qt/5.15.2-static-x32-mingw/qml/QtQuick/Layouts/libqquicklayoutsplugin.a E:/tools/qt/5.15.2-static-x32-mingw/lib/libQt5Quick.a E:/tools/qt/5.15.2-static-x32-mingw/lib/libQt5Gui.a -ld3d11 -ldxgi -ldxguid E:/tools/qt/5.15.2-static-x32-mingw/lib/libqtlibpng.a E:/tools/qt/5.15.2-static-x32-mingw/lib/libqtharfbuzz.a -lcomdlg32 -loleaut32 -limm32 -lglu32 -lopengl32 -lgdi32 E:/tools/qt/5.15.2-static-x32-mingw/qml/QtQml/libqmlplugin.a E:/tools/qt/5.15.2-static-x32-mingw/qml/QtQml/Models.2/libmodelsplugin.a E:/tools/qt/5.15.2-static-x32-mingw/lib/libQt5QmlModels.a E:/tools/qt/5.15.2-static-x32-mingw/qml/QtQml/WorkerScript.2/libworkerscriptplugin.a E:/tools/qt/5.15.2-static-x32-mingw/lib/libQt5QmlWorkerScript.a E:/tools/qt/5.15.2-static-x32-mingw/lib/libQt5Qml.a E:/tools/qt/5.15.2-static-x32-mingw/lib/libQt5Network.a -ldnsapi -liphlpapi -lcrypt32 E:/tools/qt/5.15.2-static-x32-mingw/lib/libQt5Core.a -lmpr -luserenv -lversion -lz E:/tools/qt/5.15.2-static-x32-mingw/lib/libqtpcre2.a -lzstd -lnetapi32 -lws2_32 -ladvapi32 -lkernel32 -lole32 -lshell32 -luuid -luser32 -lwinmm  -lglu32 -lopengl32 -lgdi32 -luser32 -lmingw32 E:/tools/qt/5.15.2-static-x32-mingw/lib/libqtmain.a -lshell32
mingw32-make[1]: Leaving directory 'E:/code/color-corners/build/color-corners-Qt_5_15_2_x32_MinGW-Release'
15:06:32: The process "E:\tools\msys2\mingw32\bin\mingw32-make.exe" exited normally.
15:06:32: Elapsed time: 00:05.

Resulting application launched fine both from Qt Creator environment and without Qt Creator, and it didn’t require any DLLs. Everything as expected.

Here’s a Dependency Walker report:

Dependency Walker, MinGW x32, qmake
With CMake

Then I tried to build it with CMake.

Configuration output:

Running E:\tools\cmake\bin\cmake.exe -S E:/code/color-corners -B E:/code/color-corners/build/color-corners-Qt_5_15_2_x32_MinGW-Release "-DCMAKE_GENERATOR:STRING=Ninja" "-DCMAKE_BUILD_TYPE:STRING=Release" "-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=E:\code\color-corners\build\color-corners-Qt_5_15_2_x32_MinGW-Release/.qtc/package-manager/auto-setup.cmake" "-DQT_QMAKE_EXECUTABLE:FILEPATH=E:/tools/qt/5.15.2-static-x32-mingw/bin/qmake.exe" "-DCMAKE_PREFIX_PATH:PATH=E:/tools/qt/5.15.2-static-x32-mingw" "-DCMAKE_C_COMPILER:FILEPATH=E:/tools/msys2/mingw32/bin/gcc.exe" "-DCMAKE_CXX_COMPILER:FILEPATH=E:/tools/msys2/mingw32/bin/g++.exe" "-DCMAKE_CXX_FLAGS_INIT:STRING=" in E:\code\color-corners\build\color-corners-Qt_5_15_2_x32_MinGW-Release.
-- The CXX compiler identification is GNU 13.2.0
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: E:/tools/msys2/mingw32/bin/g++.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found Qt 5.15.2: E:/tools/qt/5.15.2-static-x32-mingw
-- This Qt is static
-- This Qt version (5.15.2) is newer than 5.14
-- Running qmlimportscanner to find used QML plugins. 
-- Configuring done
-- Generating done
-- Build files have been written to: E:/code/color-corners/build/color-corners-Qt_5_15_2_x32_MinGW-Release

Build output:

13:36:40: Running steps for project color-corners...
13:36:40: Starting: "E:\tools\cmake\bin\cmake.exe" --build E:/code/color-corners/build/color-corners-Qt_5_15_2_x32_MinGW-Release --target all
[1/28 10.2/sec] Automatic MOC for target color-corners
[2/28 17.4/sec] Generating qrc_qml.cpp
[3/28 16.6/sec] Building CXX object CMakeFiles/color-corners.dir/color-corners_autogen/mocs_compilation.cpp.obj
[4/28 17.8/sec] Building CXX object CMakeFiles/color-corners.dir/qrc_qml.cpp.obj
[5/28 2.7/sec] Building CXX object CMakeFiles/color-corners.dir/Qt5_QmlPlugins_Imports_color-corners.cpp.obj
[6/28 3.2/sec] Building CXX object CMakeFiles/color-corners.dir/E_/tools/qt/5.15.2-static-x32-mingw/lib/cmake/Qt5Network/Qt5Network_QGenericEnginePlugin_Import.cpp.obj
[7/28 3.8/sec] Building CXX object CMakeFiles/color-corners.dir/E_/tools/qt/5.15.2-static-x32-mingw/lib/cmake/Qt5Qml/Qt5Qml_QQmlDebugServerFactory_Import.cpp.obj
[8/28 4.3/sec] Building CXX object CMakeFiles/color-corners.dir/E_/tools/qt/5.15.2-static-x32-mingw/lib/cmake/Qt5Qml/Qt5Qml_QLocalClientConnectionFactory_Import.cpp.obj
[9/28 4.8/sec] Building CXX object CMakeFiles/color-corners.dir/E_/tools/qt/5.15.2-static-x32-mingw/lib/cmake/Qt5Qml/Qt5Qml_QDebugMessageServiceFactory_Import.cpp.obj
[10/28 5.3/sec] Building CXX object CMakeFiles/color-corners.dir/E_/tools/qt/5.15.2-static-x32-mingw/lib/cmake/Qt5Gui/Qt5Gui_QTgaPlugin_Import.cpp.obj
[11/28 5.8/sec] Building CXX object CMakeFiles/color-corners.dir/main.cpp.obj
[12/28 6.4/sec] Building CXX object CMakeFiles/color-corners.dir/E_/tools/qt/5.15.2-static-x32-mingw/lib/cmake/Qt5Gui/Qt5Gui_QTiffPlugin_Import.cpp.obj
[13/28 6.9/sec] Building CXX object CMakeFiles/color-corners.dir/E_/tools/qt/5.15.2-static-x32-mingw/lib/cmake/Qt5Gui/Qt5Gui_QJpegPlugin_Import.cpp.obj
[14/28 7.4/sec] Building CXX object CMakeFiles/color-corners.dir/E_/tools/qt/5.15.2-static-x32-mingw/lib/cmake/Qt5Qml/Qt5Qml_QQmlInspectorServiceFactory_Import.cpp.obj
[15/28 7.9/sec] Building CXX object CMakeFiles/color-corners.dir/E_/tools/qt/5.15.2-static-x32-mingw/lib/cmake/Qt5Gui/Qt5Gui_QGifPlugin_Import.cpp.obj
[16/28 8.4/sec] Building CXX object CMakeFiles/color-corners.dir/E_/tools/qt/5.15.2-static-x32-mingw/lib/cmake/Qt5Gui/Qt5Gui_QICNSPlugin_Import.cpp.obj
[17/28 7.7/sec] Building CXX object CMakeFiles/color-corners.dir/E_/tools/qt/5.15.2-static-x32-mingw/lib/cmake/Qt5Gui/Qt5Gui_QICOPlugin_Import.cpp.obj
[18/28 8.2/sec] Building CXX object CMakeFiles/color-corners.dir/E_/tools/qt/5.15.2-static-x32-mingw/lib/cmake/Qt5Gui/Qt5Gui_QWebpPlugin_Import.cpp.obj
[19/28 8.6/sec] Building CXX object CMakeFiles/color-corners.dir/E_/tools/qt/5.15.2-static-x32-mingw/lib/cmake/Qt5Qml/Qt5Qml_QQmlDebuggerServiceFactory_Import.cpp.obj
[20/28 8.9/sec] Building CXX object CMakeFiles/color-corners.dir/E_/tools/qt/5.15.2-static-x32-mingw/lib/cmake/Qt5Gui/Qt5Gui_QWbmpPlugin_Import.cpp.obj
[21/28 9.3/sec] Building CXX object CMakeFiles/color-corners.dir/E_/tools/qt/5.15.2-static-x32-mingw/lib/cmake/Qt5Gui/Qt5Gui_QWindowsIntegrationPlugin_Import.cpp.obj
[22/28 9.6/sec] Building CXX object CMakeFiles/color-corners.dir/E_/tools/qt/5.15.2-static-x32-mingw/lib/cmake/Qt5Qml/Qt5Qml_QQmlNativeDebugConnectorFactory_Import.cpp.obj
[23/28 7.7/sec] Building CXX object CMakeFiles/color-corners.dir/E_/tools/qt/5.15.2-static-x32-mingw/lib/cmake/Qt5Qml/Qt5Qml_QQuickProfilerAdapterFactory_Import.cpp.obj
[24/28 8.1/sec] Building CXX object CMakeFiles/color-corners.dir/E_/tools/qt/5.15.2-static-x32-mingw/lib/cmake/Qt5Qml/Qt5Qml_QQmlPreviewServiceFactory_Import.cpp.obj
[25/28 8.3/sec] Building CXX object CMakeFiles/color-corners.dir/E_/tools/qt/5.15.2-static-x32-mingw/lib/cmake/Qt5Qml/Qt5Qml_QQmlNativeDebugServiceFactory_Import.cpp.obj
[26/28 8.6/sec] Building CXX object CMakeFiles/color-corners.dir/E_/tools/qt/5.15.2-static-x32-mingw/lib/cmake/Qt5Qml/Qt5Qml_QQmlProfilerServiceFactory_Import.cpp.obj
[27/28 8.9/sec] Building CXX object CMakeFiles/color-corners.dir/E_/tools/qt/5.15.2-static-x32-mingw/lib/cmake/Qt5Qml/Qt5Qml_QTcpServerConnectionFactory_Import.cpp.obj
[28/28 5.5/sec] Linking CXX executable color-corners.exe
13:36:45: The process "E:\tools\cmake\bin\cmake.exe" exited normally.

And I could launch the application from Qt Creator, but surprisingly, trying to launch the executable without Qt Creator, I got an error about missing MinGW runtime DLL, even though Qt was built with -static-runtime:

Missing libgcc DLL

Then I got an error about missing zstd DLL:

Missing zstd DLL

And looks like it will also complain about missing zlib DLL, because here’s what Dependency Walker reports:

Dependency Walker, MinGW x32, CMake

To highlight the imports difference between executables produced by qmake and CMake:

qmake/CMake imports difference

Well, what the fuck.

There is also a big difference in executables sizes:

$ du -s /path/to/qmake-build/color-corners.exe
27404

$ du -s /path/to/cmake-build/color-corners.exe
40520

So CMake-produced executable is so much bigger and yet it is the one failing to launch due to missing DLLs? What is the actual f…

Okay, the MinGW runtime issue can be fixed like this:

set(CMAKE_EXE_LINKER_FLAGS "-static-libgcc -static-libstdc++ -static")

but what about zstd and zlib, where did they come from? And why they are shared libraries in CMake build, while qmake got static variants?

I couldn’t find answers on the internets, so I just inspected the qmake output and I saw that it links to a lot of stuff, out of which the following seemed to be the most relevant: E:/tools/qt/5.15.2-static-x32-mingw/lib/libQt5Core.a, -lzstd and -lz. So I added those to CMake project:

# if you remove QtCore from linking, it will still complain about missing zstd,
# even though -lzstd is present here
target_link_libraries(${CMAKE_PROJECT_NAME}
    PRIVATE
        Qt${QT_VERSION_MAJOR}::Core
        -lz
        -lzstd
)

and then resulting executable was able to launch without Qt Creator environment, as it didn’t require those DLLs anymore.

Just in case, here’s a comparison of imports between executable created with qmake and this new executable from fixed CMake build:

qmake/CMake fixed imports difference

One other change is that executable size got even bigger:

$ du -s /path/to/cmake-build/color-corners.exe
42408

but that’s a minor detail.

So yeah, it is definitely possible to build static Qt with MinGW, but I didn’t fucking enjoy it at all.

2023-10-01 | Qt 6.5.1, Mac OS 13.6, Apple M2 Pro

I got the latest MacBook Pro with Apple M2 Pro processor, and of course I wanted to check how fast it can build Qt and that Qt does build there at all.

My environment:

$ sw_vers -productVersion
13.6

$ sysctl -n machdep.cpu.brand_string
Apple M2 Pro

$ system_profiler SPHardwareDataType | grep Cores:
      Total Number of Cores: 12 (8 performance and 4 efficiency)

$ nproc --all
12

$ clang --version
Apple clang version 15.0.0 (clang-1500.0.40.1)
Target: arm64-apple-darwin22.6.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

$ cmake --version
cmake version 3.27.6

If you have vcpkg installed, unset VCPKG_ROOT environment variable (as it will probably cause troubles with GSSAPI):

$ unset VCPKG_ROOT

And then configure and try building Qt as usual:

$ ../configure -static -release -no-pch -prefix "/Users/vasya/programs/qt/6.5.1-static" \
  -skip qtwebengine -nomake tests -nomake examples
$ cmake --build . --parallel

The build will fail with the following:

[1172/10531] Automatic MOC for target Core
FAILED: qtbase/src/corelib/Core_autogen/timestamp qtbase/src/corelib/Core_autogen/mocs_compilation.cpp /Users/vasya/programs/qt/src/6.5.1/build/qtbase/src/corelib/Core_autogen/timestamp /Users/vasya/programs/qt/src/6.5.1/build/qtbase/src/corelib/Core_autogen/mocs_compilation.cpp
cd /Users/vasya/programs/qt/src/6.5.1/build/qtbase/src/corelib && /opt/homebrew/Cellar/cmake/3.27.6/bin/cmake -E cmake_autogen /Users/vasya/programs/qt/src/6.5.1/build/qtbase/src/corelib/CMakeFiles/Core_autogen.dir/AutogenInfo.json Release && /opt/homebrew/Cellar/cmake/3.27.6/bin/cmake -E touch /Users/vasya/programs/qt/src/6.5.1/build/qtbase/src/corelib/Core_autogen/timestamp && /opt/homebrew/Cellar/cmake/3.27.6/bin/cmake -E cmake_transform_depfile Ninja gccdepfile /Users/vasya/programs/qt/src/6.5.1 /Users/vasya/programs/qt/src/6.5.1/qtbase/src/corelib /Users/vasya/programs/qt/src/6.5.1/build /Users/vasya/programs/qt/src/6.5.1/build/qtbase/src/corelib /Users/vasya/programs/qt/src/6.5.1/build/qtbase/src/corelib/Core_autogen/deps /Users/vasya/programs/qt/src/6.5.1/build/CMakeFiles/d/606731a3a0f1e503548aa7c710455eaf53992e00a8ae745add67869bd2ab1236.d

AutoMoc subprocess error
------------------------
The moc process failed to compile
  "SRC:/qtbase/src/corelib/io/qfiledevice.h"
into
  "SRC:/build/qtbase/src/corelib/Core_autogen/include/moc_qfiledevice.cpp"
included by
  "SRC:/qtbase/src/corelib/io/qfiledevice.cpp"
Process was terminated by signal 6

Output
------
dyld[53461]: Symbol not found: __ZTVNSt3__13pmr25monotonic_buffer_resourceE
  Referenced from: <844A2EB8-F282-3594-8EC0-4E52F289E557> /Users/vasya/programs/qt/src/6.5.1/build/qtbase/libexec/moc
  Expected in:     <3EE92404-8FC3-374B-A598-D5C9A8CD64B5> /usr/lib/libc++.1.dylib

[1185/10531] Building CXX object qtbase/src/3rdparty/harfbuzz-ng/CMakeFiles/BundledHarfbuzz.dir/src/hb-subset.cc.o
ninja: build stopped: subcommand failed.
$ c++filt -n _ZTVNSt3__13pmr25monotonic_buffer_resourceE
vtable for std::__1::pmr::monotonic_buffer_resource

This one is likely because of missing LLVM. There are probably other ways of fixing this, but I know only one - install LLVM with Homebrew and use that one. And since Homebrew has come up, I noticed that some features were disabled in the configuration output, for instance FFmpeg backend for Multimedia, so yes, let’s try with Homebrew prefix:

$ ../configure -static -release -no-pch -prefix "/Users/vasya/programs/qt/6.5.1-static" \
  -skip qtwebengine -nomake tests -nomake examples \
  -- -DCMAKE_PREFIX_PATH="/opt/homebrew"

That will fail already on configure:

CMake Error at /opt/homebrew/lib/cmake/zstd/zstdTargets.cmake:42 (message):
  Some (but not all) targets in this export set were already defined.

  Targets Defined: zstd::libzstd_static

  Targets not yet defined: zstd::libzstd_shared

Call Stack (most recent call first):
  /opt/homebrew/lib/cmake/zstd/zstdConfig.cmake:1 (include)
  qtbase/cmake/FindWrapZSTD.cmake:24 (find_package)
  /opt/homebrew/Cellar/cmake/3.27.6/share/cmake/Modules/CMakeFindDependencyMacro.cmake:76 (find_package)
  build/qtbase/lib/cmake/Qt6/QtPublicDependencyHelpers.cmake:36 (find_dependency)
  build/qtbase/lib/cmake/Qt6Core/Qt6CoreDependencies.cmake:30 (_qt_internal_find_third_party_dependencies)
  build/qtbase/lib/cmake/Qt6Core/Qt6CoreConfig.cmake:40 (include)
  build/qtbase/lib/cmake/Qt6/Qt6Config.cmake:157 (find_package)
  qtimageformats/CMakeLists.txt:14 (find_package)

I’ve already encountered this one when I was building Qt on Steam Deck, the workaround is to remove zstd::libzstd_shared from /opt/homebrew/lib/cmake/zstd/zstdTargets.cmake. Don’t forget to return it back afterwards.

Try to configure the build again. There will be another error in the end of configure:

CMake Error at qtbase/cmake/QtTargetHelpers.cmake:146 (target_link_libraries):
  Target "QGstreamerMediaPlugin" links to:

    EGL::EGL

  but the target was not found.  Possible reasons include:

    * There is a typo in the target name.
    * A find_package call is missing for an IMPORTED target.
    * An ALIAS target is missing.

Call Stack (most recent call first):
  qtmultimedia/src/plugins/multimedia/gstreamer/CMakeLists.txt:59 (qt_internal_extend_target)

I tried to install Mesa packages:

$ brew install mesa mesa-glu

but that didn’t help. Then I realized that this problem originates in GStreamer backend, so it probably can be just disabled, because FFmpeg is now the default backend anyway:

$ ../configure -static -release -no-pch -prefix "/Users/vasya/programs/qt/6.5.1-static" \
  -skip qtwebengine -nomake tests -nomake examples -no-gstreamer \
  -- -DCMAKE_PREFIX_PATH="/opt/homebrew"

That helped, and Qt has successfully configured. I started building it and got this error:

[680/10313] Building CXX object qtgrpc/src/tools/qtprotoccommon/CMakeFiles/QtProtocCommon.dir/generatorbase.cpp.o
FAILED: qtgrpc/src/tools/qtprotoccommon/CMakeFiles/QtProtocCommon.dir/generatorbase.cpp.o
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ -DPROTOBUF_USE_DLLS -I/Users/vasya/programs/qt/src/6.5.1/qtgrpc/src/tools/qtprotoccommon -isystem /opt/homebrew/include -DNDEBUG -O2 -std=gnu++17 -arch arm64 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.0.sdk -mmacosx-version-min=11.0 -fPIC -Wall -Wextra -MD -MT qtgrpc/src/tools/qtprotoccommon/CMakeFiles/QtProtocCommon.dir/generatorbase.cpp.o -MF qtgrpc/src/tools/qtprotoccommon/CMakeFiles/QtProtocCommon.dir/generatorbase.cpp.o.d -o qtgrpc/src/tools/qtprotoccommon/CMakeFiles/QtProtocCommon.dir/generatorbase.cpp.o -c /Users/vasya/programs/qt/src/6.5.1/qtgrpc/src/tools/qtprotoccommon/generatorbase.cpp
/Users/vasya/programs/qt/src/6.5.1/qtgrpc/src/tools/qtprotoccommon/generatorbase.cpp:8:10: fatal error: 'google/protobuf/stubs/logging.h' file not found
#include <google/protobuf/stubs/logging.h>
         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

I thought this is because I don’t have protobuf installed:

$ brew install protobuf

but no, I did have it. Then I checked what headers it has in /opt/homebrew/include/google/protobuf/stubs/, and logging.h wasn’t there. As it turned out, protobof migrated to a different logger, so I needed to downgrade my protobuf to version 21.12:

$ brew uninstall --ignore-dependencies protobuf
$ brew install protobuf@21
$ brew link protobuf@21

Hopefully, later versions of Qt will switch to newer versions of protobuf. Meanwhile, do keep in mind that you might brake other packages in your environment by force-downgrading with --ignore-dependencies, because they might require exactly the latest protobuf.

Then the build proceeded, and I got that same error about monotonic_buffer_resource:

Output
------
dyld[80989]: Symbol not found: __ZTVNSt3__13pmr25monotonic_buffer_resourceE
  Referenced from: <1F874DB3-B6FE-325D-8E18-58B83A377595> /Users/vasya/programs/qt/src/6.5.1/build/qtbase/libexec/moc
  Expected in:     <3EE92404-8FC3-374B-A598-D5C9A8CD64B5> /usr/lib/libc++.1.dylib

So first I checked that I actually have LLVM installed:

$ brew install llvm

But I did, and then I realized that it is not linked anywhere (it’s a new Mac, I didn’t have time to set it up properly). But probably don’t link it to the main prefix, instead add the following to your ~/.bash_profile (or whichever shell you are using):

export PATH="/opt/homebrew/opt/llvm/bin:$PATH"
export LDFLAGS="-L/opt/homebrew/opt/llvm/lib/c++ -Wl,-rpath,/opt/homebrew/opt/llvm/lib/c++ $LDFLAGS"
export CPPFLAGS="-I/opt/homebrew/opt/llvm/include $CPPFLAGS"

I re-configured Qt again, and it still warns about not finding LLVM for QDoc, so probably you can try adding -DLLVM_INSTALL_DIR="/opt/homebrew/opt/llvm" after -DCMAKE_PREFIX_PATH="..." (or export LLVM_INSTALL_DIR="/opt/homebrew/opt/llvm" in ~/.bash_profile), but it doesn’t matter for the main build.

Just in case, here’s the final configure command:

$ ../configure -static -release -no-pch \
  -prefix "/Users/vasya/programs/qt/6.5.1-static" \
  -skip qtwebengine -nomake tests -nomake examples -no-gstreamer \
  -- -DCMAKE_PREFIX_PATH="/opt/homebrew"

and configuration summary:

-- Configure summary:

Building for: macx-clang (arm64, CPU features: neon crc32 crypto)
Compiler: clang (Apple) 15.0.0.15000040
Build options:
  Mode ................................... release
  Optimize release build for size ........ no
  Fully optimize release builds (-O3) .... no
  Building shared libraries .............. no
  Using C standard ....................... C11
  Using C++ standard ..................... C++17
  Using ccache ........................... no
  Relocatable ............................ no
  Using precompiled headers .............. no
  Using Link Time Optimization (LTCG) .... no
  Using Intel CET ........................ no
  Target compiler supports:
    ARM Extensions ....................... NEON CRC32 AES
  Sanitizers:
    Addresses ............................ no
    Threads .............................. no
    Memory ............................... no
    Fuzzer (instrumentation only) ........ no
    Undefined ............................ no
  Build parts ............................ libs tools
  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 PrintSupport ........................ yes
  Qt Sql ................................. yes
  Qt Testlib ............................. yes
  Qt Widgets ............................. yes
  Qt Xml ................................. yes
Support enabled for:
  Using pkg-config ....................... no
  udev ................................... no
  OpenSSL ................................ yes
    Qt directly linked to OpenSSL ........ no
  OpenSSL 1.1 ............................ no
  OpenSSL 3.0 ............................ yes
  Using system zlib ...................... yes
  Zstandard support ...................... yes
  Thread support ......................... yes
Common build options:
  Linker can resolve circular dependencies  yes
Qt Core:
  backtrace .............................. yes
  DoubleConversion ....................... yes
    Using system DoubleConversion ........ no
  GLib ................................... yes
  ICU .................................... no
  Using system libb2 ..................... yes
  Built-in copy of the MIME database ..... yes
  cpp/winrt base ......................... no
  Tracing backend ........................ <none>
  Logging backends:
    journald ............................. no
    syslog ............................... no
    slog2 ................................ no
  PCRE2 .................................. yes
    Using system PCRE2 ................... yes
  Application permissions ................ yes
Qt Sql:
  SQL item models ........................ yes
Qt Network:
  getifaddrs() ........................... yes
  IPv6 ifname ............................ yes
  libproxy ............................... no
  SecureTransport ........................ yes
  DTLS ................................... yes
  OCSP-stapling .......................... yes
  SCTP ................................... no
  Use system proxies ..................... yes
  GSSAPI ................................. yes
  Brotli Decompression Support ........... yes
  qIsEffectiveTLD() ...................... yes
    Built-in publicsuffix database ....... yes
    System publicsuffix database ......... no
Core tools:
  Android deployment tool ................ yes
  macOS deployment tool .................. yes
  Windows deployment tool ................ no
  qmake .................................. yes
Qt Gui:
  Accessibility .......................... yes
  FreeType ............................... yes
    Using system FreeType ................ yes
  HarfBuzz ............................... yes
    Using system HarfBuzz ................ no
  Fontconfig ............................. no
  Image formats:
    GIF .................................. yes
    ICO .................................. yes
    JPEG ................................. yes
      Using system libjpeg ............... yes
    PNG .................................. yes
      Using system libpng ................ yes
  Text formats:
    HtmlParser ........................... yes
    CssParser ............................ yes
    OdfWriter ............................ yes
    MarkdownReader ....................... yes
      Using system libmd4c ............... no
    MarkdownWriter ....................... yes
  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
  HiRes wheel support in libinput ........ no
  INTEGRITY HID .......................... no
  mtdev .................................. no
  tslib .................................. no
  xkbcommon .............................. no
  X11 specific:
    XLib ................................. no
    XCB Xlib ............................. no
    EGL on X11 ........................... no
    xkbcommon-x11 ........................ no
    xcb-sm ............................... no
QPA backends:
  DirectFB ............................... no
  EGLFS .................................. no
  EGLFS details:
    EGLFS OpenWFD ........................ no
    EGLFS i.Mx6 .......................... no
    EGLFS i.Mx6 Wayland .................. no
    EGLFS RCAR ........................... no
    EGLFS EGLDevice ...................... no
    EGLFS GBM ............................ no
    EGLFS VSP2 ........................... no
    EGLFS Mali ........................... no
    EGLFS Raspberry Pi ................... no
    EGLFS X11 ............................ no
  LinuxFB ................................ no
  VNC .................................... no
  VK_KHR_display ......................... no
  QNX:
    lgmon ................................ no
    IMF .................................. no
  XCB:
    Using system-provided xcb-xinput ..... no
    GL integrations:
      GLX Plugin ......................... no
        XCB GLX .......................... no
      EGL-X11 Plugin ..................... no
  Windows:
    Direct 2D ............................ no
    Direct 2D 1.1 ........................ no
    DirectWrite .......................... no
    DirectWrite 3 ........................ no
Qt Widgets:
  GTK+ ................................... no
  Styles ................................. Fusion macOS Windows
Qt Testlib:
  Tester for item models ................. yes
  Batch tests ............................ no
Qt PrintSupport:
  CUPS ................................... yes
Qt Sql Drivers:
  DB2 (IBM) .............................. no
  InterBase .............................. no
  MySql .................................. yes
  OCI (Oracle) ........................... no
  ODBC ................................... no
  PostgreSQL ............................. yes
  SQLite ................................. yes
    Using system provided SQLite ......... no
Further Image Formats:
  JasPer ................................. yes
  MNG .................................... no
  TIFF ................................... yes
    Using system libtiff ................. yes
  WEBP ................................... yes
    Using system libwebp ................. yes
Qt QML:
  QML network support .................... yes
  QML debugging and profiling support .... yes
  QML just-in-time compiler .............. no
  QML XML http request ................... yes
  QML Locale ............................. yes
Qt QML Models:
  QML list model ......................... yes
  QML delegate model ..................... yes
Qt Quick:
  AnimatedImage item ..................... yes
  Canvas item ............................ yes
  Support for Qt Quick Designer .......... yes
  Flipable item .......................... yes
  GridView item .......................... yes
  ListView item .......................... yes
  TableView item ......................... yes
  TreeView item .......................... yes
  Path support ........................... yes
  PathView item .......................... yes
  Positioner items ....................... yes
  Repeater item .......................... yes
  ShaderEffect item ...................... yes
  Sprite item ............................ yes
Qt Quick Templates 2:
  Hover support .......................... yes
  Multi-touch support .................... yes
  Calendar support ....................... yes
Qt Quick Controls 2:
  Styles ................................. Basic Fusion Imagine iOS Material Universal macOS Windows
QtQuick3D:
  Assimp ................................. yes
  System Assimp .......................... no
Qt Multimedia:
  Spatial Audio .......................... yes
  Spatial Audio (Quick3D) ................ yes
  Low level Audio Backend:
    ALSA (experimental) .................. no
    PulseAudio ........................... no
    MMRenderer ........................... no
    CoreAudio ............................ yes
    Windows Media SDK .................... no
    Open SLES (Android) .................. no
    Web Assembly ......................... no
  Plugin:
    GStreamer 1.0 ........................ no
    FFmpeg ............................... yes
    MMRenderer ........................... no
    AVFoundation ......................... yes
    Windows Media Foundation ............. no
  Hardware acceleration and features:
    Video for Linux ...................... no
    VAAPI support ........................ no
    Linux DMA buffer support ............. no
    VideoToolbox ......................... yes
Qt 3D:
  Assimp ................................. yes
  System Assimp .......................... 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 APIs:
  Vulkan ................................. no
Qt 3D Renderers:
  OpenGL Renderer ........................ yes
  RHI Renderer ........................... yes
Qt3D Geometry Loaders:
  Autodesk FBX ........................... no
Qt 5 Compatibility Libraries:
  iconv .................................. no
Qt Charts Types:
  Area Chart ............................. yes
  Line Chart ............................. yes
  Spline Chart ........................... yes
  Scatter Chart .......................... yes
  Bar Chart .............................. yes
  Pie Chart .............................. yes
  Boxplot Chart .......................... yes
  Candlestick Chart ...................... yes
Qt Axis Types:
  DateTime Axis .......................... yes
Qt Bluetooth:
  BlueZ .................................. no
  BlueZ Low Energy ....................... no
  Linux Crypto API ....................... no
  WinRT Bluetooth API .................... no
Qt Tools:
  Qt Assistant ........................... yes
  QDoc ................................... no
  Clang-based lupdate parser ............. no
  Qt Designer ............................ yes
  Qt Distance Field Generator ............ yes
  Qt Linguist ............................ yes
  pixeltool .............................. yes
  qdbus .................................. yes
  Qt Attributions Scanner ................ yes
  qtdiag ................................. yes
  qtplugininfo ........................... yes
Serial Port:
  ntddmodm ............................... no
Qt Protobuf tools:
  Qt Protobuf generator .................. yes
Qt GRPC:
  gRPC support ........................... yes
  Native gRPC support .................... no
Qt GRPC tools:
  Qt GRPC generator ...................... yes
Qt Opcua:
  Open62541 .............................. yes
  Unified Automation C++ SDK ............. no
  Support for namespace 0 NodeId names ... yes
  Namespace 0 NodeIds generator .......... no
  Open62541 security support ............. yes
  Support for global discovery server .... yes
Qt Remote Objects:
  High Availability Manager (ham) ........ no
Qt Scxml:
  ECMAScript data model for QtScxml ...... yes
Qt Sensors:
Qt SerialBus:
  Socket CAN ............................. no
  Socket CAN FD .......................... no
  SerialPort Support ..................... yes
Qt TextToSpeech:
  Flite .................................. no
  Flite with ALSA ........................ no
  Speech Dispatcher ...................... no
Qt Virtualkeyboard:
  Desktop integration .................... yes
  Built-in layouts ....................... yes
  Key navigation ......................... no
  Retro style as default ................. no
  Sensitive Debug ........................ no
  Cerence ................................ no
    Static Linking ....................... no
    Handwriting .......................... no
      Alphabetic ......................... no
      CJK ................................ no
    XT9 .................................. no
      XT9 Debug .......................... no
      XT9 9-key layouts .................. no
    Bundle resources ..................... no
      Handwriting ........................ no
      XT9 ................................ no
  Hunspell ............................... no
    Using Hunspell copy from 3rdparty/ ... no
  OpenWnn ................................ yes
  MyScript ............................... no
  Language support enabled for:
    Arabic ............................... yes
    Bulgarian ............................ yes
    Czech ................................ yes
    Danish ............................... yes
    German ............................... yes
    Greek ................................ yes
    English GB ........................... yes
    English US ........................... yes
    Spanish .............................. yes
    Spanish Mexico ....................... yes
    Estonian ............................. yes
    Farsi ................................ yes
    Finnish .............................. yes
    French Canada ........................ yes
    French France ........................ yes
    Hebrew ............................... yes
    Hindi ................................ yes
    Croatian ............................. yes
    Hungarian ............................ yes
    Indonesian ........................... yes
    Italian .............................. yes
    Japanese ............................. yes
    Korean ............................... yes
    Malay ................................ yes
    Norwegian ............................ yes
    Dutch ................................ yes
    Polish ............................... yes
    Portuguese Brazil .................... yes
    Portuguese Portugal .................. yes
    Romanian ............................. yes
    Russian .............................. yes
    Slovak ............................... yes
    Slovenian ............................ yes
    Albanian ............................. yes
    Serbian .............................. yes
    Swedish .............................. yes
    Thai ................................. yes
    Turkish .............................. yes
    Ukrainian ............................ yes
    Vietnamese ........................... yes
    Simplified Chinese ................... yes
    Traditional Chinese .................. yes
    HongKong Chinese ..................... no
  Traditional chinese input methods:
    Zhuyin ............................... yes
    Cangjie .............................. yes

So, configuration succeeded, and I started the build again. It passed that problem with monotonic_buffer_resource, but failed later with something different:

/Users/vasya/programs/qt/src/6.5.1/qtmultimedia/src/plugins/multimedia/darwin/camera/avfcamerautility.mm:72:35: error: no template named 'unary_function' in namespace 'std'; did you mean '__unary_function'?
struct FormatHasNoFPSRange : std::unary_function<AVCaptureDeviceFormat *, bool>
                             ~~~~~^~~~~~~~~~~~~~
                                  __unary_function

Apparently, this function was removed from C++17, which means that Qt 6.5.1 doesn’t support C++17? Or at least that is how it is with Xcode 15. I found a seemingly relevant workaround about setting _LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION preprocessor definition. I tried to do that in /path/to/qt/qtmultimedia/src/plugins/multimedia/darwin/CMakeLists.txt:

qt_internal_add_plugin(QDarwinMediaPlugin
    OUTPUT_NAME darwinmediaplugin
    PLUGIN_TYPE multimedia
    SOURCES
        # ...
    INCLUDE_DIRECTORIES
        # ...
    LIBRARIES
        # ...
    DEFINES
        "_LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION"
)

it didn’t help. Then I tried this:

qt_internal_extend_target(QDarwinMediaPlugin CONDITION NOT TVOS
    SOURCES
        # ...
    DEFINES
        "_LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION"
)

it didn’t help either. Then I tried this:

target_compile_definitions(QDarwinMediaPlugin
    PRIVATE
        "_LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION"
)

but that didn’t help either. Then I just edited /path/to/qt/qtmultimedia/src/plugins/multimedia/darwin/camera/avfcamerautility.mm:

-struct FormatHasNoFPSRange : std::unary_function<AVCaptureDeviceFormat *, bool>
+struct FormatHasNoFPSRange : std::__unary_function<AVCaptureDeviceFormat *, bool>

And that did help, the build continued and then succeeded. Installation too:

$ cmake --install .

The entire build (measured from scratch, after all the problems were solved) and installation took… 12 minutes (12:15)!

Girl shocked

Fuck me sideways, it sure is nice to live in the future. For comparison, here are the build times of the same static Qt 6.5.1 on other machines that I have.

The installation size is 851 MB (according to du). Binaries are arm64:

$ lipo -info /Users/vasya/programs/qt/6.5.1-static/lib/libQt6Core.a
Non-fat file: /Users/vasya/programs/qt/6.5.1-static/lib/libQt6Core.a is architecture: arm64

By the way, I didn’t need to provide -DCMAKE_OSX_ARCHITECTURES="arm64" to the configure, as I assumed that it should be the default one. If I wanted to build universal binaries, then yes, I would’ve provided -DCMAKE_OSX_ARCHITECTURES="arm64;x86_64" (some say the order should be exactly x86_64;arm64, because it might be important for Qt somehow).

Right, so let’s add this build to Qt Creator then. The procedure is the same as always, but with one little surprise:

No compiler can produce code for this Qt version. Please define one or more compilers for: 
arm-darwin-generic-mach_o-64bit

So for some reasons it couldn’t auto-detect system compilers, and you’ll need to set them manually.

Here’s C compiler:

/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc
Qt Creator, manually added C compiler on Apple silicon

And here’s C++ compiler:

/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++
Qt Creator, manually added C++ compiler on Apple silicon

The rest goes fine:

Qt Creator, Qt version on Apple silicon

Qt Creator, kit on Apple silicon

Building the greatest application in the world succeeds:

19:31:56: Starting: "/opt/homebrew/Cellar/cmake/3.27.6/bin/cmake" --build /Users/vasya/code/qt/color-corners/build/Qt_6_5_1_static/Release --target all
[1/6 6.2/sec] Automatic MOC for target color-corners
[2/6 10.6/sec] Generating qrc_qml.cpp
[3/6 12.7/sec] Building CXX object CMakeFiles/color-corners.dir/color-corners_autogen/mocs_compilation.cpp.o
[4/6 15.9/sec] Building CXX object CMakeFiles/color-corners.dir/qrc_qml.cpp.o
[5/6 6.6/sec] Building CXX object CMakeFiles/color-corners.dir/main.cpp.o
[6/6 6.5/sec] Linking CXX executable color-corners.app/Contents/MacOS/color-corners
ld: warning: ignoring duplicate libraries: '/Users/vasya/programs/qt/6.5.1-static/./qml/QtQml/Base/libqmlplugin.a', '/Users/vasya/programs/qt/6.5.1-static/./qml/QtQml/Models/libmodelsplugin.a', '/Users/vasya/programs/qt/6.5.1-static/./qml/QtQml/WorkerScript/libworkerscriptplugin.a', '/Users/vasya/programs/qt/6.5.1-static/./qml/QtQml/libqmlmetaplugin.a', '/Users/vasya/programs/qt/6.5.1-static/./qml/QtQuick/libqtquick2plugin.a', '/Users/vasya/programs/qt/6.5.1-static/lib/libQt6Core.a', '/Users/vasya/programs/qt/6.5.1-static/lib/libQt6Qml.a', '/Users/vasya/programs/qt/6.5.1-static/lib/libQt6QmlWorkerScript.a', '/Users/vasya/programs/qt/6.5.1-static/lib/libQt6Quick.a'
19:31:56: The process "/opt/homebrew/Cellar/cmake/3.27.6/bin/cmake" exited normally.
19:31:56: Elapsed time: 00:01.

Not sure what this warning with duplicate libraries is about.

The executable is arm64:

$ cd ~/code/qt/color-corners/build/Qt_6_5_1_static/Release/color-corners.app/Contents/MacOS/
$ lipo -info ./color-corners
Non-fat file: ./color-corners is architecture: arm64

Checking its dependencies shows that there are no Qt libraries:

$ otool -L ./color-corners
./color-corners:
  /System/Library/Frameworks/CoreVideo.framework/Versions/A/CoreVideo (compatibility version 1.2.0, current version 1.5.0)
  /System/Library/Frameworks/IOSurface.framework/Versions/A/IOSurface (compatibility version 1.0.0, current version 1.0.0)
  /System/Library/Frameworks/QuartzCore.framework/Versions/A/QuartzCore (compatibility version 1.2.0, current version 1.11.0)
  /opt/homebrew/opt/jasper/lib/libjasper.7.dylib (compatibility version 7.0.0, current version 7.0.0)
  /opt/homebrew/opt/jpeg-turbo/lib/libjpeg.8.dylib (compatibility version 8.0.0, current version 8.3.2)
  /opt/homebrew/opt/libtiff/lib/libtiff.6.dylib (compatibility version 7.0.0, current version 7.2.0)
  /opt/homebrew/opt/webp/lib/libwebpdemux.2.dylib (compatibility version 3.0.0, current version 3.14.0)
  /opt/homebrew/opt/webp/lib/libwebpmux.3.dylib (compatibility version 4.0.0, current version 4.13.0)
  /opt/homebrew/opt/webp/lib/libwebp.7.dylib (compatibility version 9.0.0, current version 9.8.0)
  /opt/homebrew/opt/webp/lib/libsharpyuv.0.dylib (compatibility version 1.0.0, current version 1.1.0)
  /System/Library/Frameworks/Carbon.framework/Versions/A/Carbon (compatibility version 2.0.0, current version 170.0.0)
  /System/Library/Frameworks/CoreGraphics.framework/Versions/A/CoreGraphics (compatibility version 64.0.0, current version 1774.0.4)
  /System/Library/Frameworks/ImageIO.framework/Versions/A/ImageIO (compatibility version 1.0.0, current version 1.0.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/Metal.framework/Versions/A/Metal (compatibility version 1.0.0, current version 341.16.0)
  /opt/homebrew/opt/libpng/lib/libpng16.16.dylib (compatibility version 57.0.0, current version 57.0.0)
  /usr/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.12)
  /opt/homebrew/opt/freetype/lib/libfreetype.6.dylib (compatibility version 27.0.0, current version 27.1.0)
  /System/Library/Frameworks/IOKit.framework/Versions/A/IOKit (compatibility version 1.0.0, current version 275.0.0)
  /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 2048.1.255)
  /System/Library/Frameworks/Foundation.framework/Versions/C/Foundation (compatibility version 300.0.0, current version 2048.1.255)
  /System/Library/Frameworks/DiskArbitration.framework/Versions/A/DiskArbitration (compatibility version 1.0.0, current version 1.0.0)
  /System/Library/Frameworks/AppKit.framework/Versions/C/AppKit (compatibility version 45.0.0, current version 2483.0.0)
  /System/Library/Frameworks/ApplicationServices.framework/Versions/A/ApplicationServices (compatibility version 1.0.0, current version 64.0.0)
  /System/Library/Frameworks/CoreServices.framework/Versions/A/CoreServices (compatibility version 1.0.0, current version 1226.0.0)
  /System/Library/Frameworks/Security.framework/Versions/A/Security (compatibility version 1.0.0, current version 61040.1.3)
  /opt/homebrew/opt/libb2/lib/libb2.1.dylib (compatibility version 2.0.0, current version 2.4.0)
  /opt/homebrew/opt/pcre2/lib/libpcre2-16.0.dylib (compatibility version 12.0.0, current version 12.2.0)
  /opt/homebrew/opt/glib/lib/libglib-2.0.0.dylib (compatibility version 7801.0.0, current version 7801.0.0)
  /opt/homebrew/opt/glib/lib/libgthread-2.0.0.dylib (compatibility version 7801.0.0, current version 7801.0.0)
  /System/Library/Frameworks/SystemConfiguration.framework/Versions/A/SystemConfiguration (compatibility version 1.0.0, current version 1296.0.1)
  /opt/homebrew/opt/brotli/lib/libbrotlidec.1.dylib (compatibility version 1.0.0, current version 1.1.0)
  /System/Library/Frameworks/GSS.framework/Versions/A/GSS (compatibility version 1.0.0, current version 1.0.0)
  /usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 1600.151.0)
  /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1336.0.0)
  /System/Library/Frameworks/CFNetwork.framework/Versions/A/CFNetwork (compatibility version 1.0.0, current version 1474.0.0)
  /System/Library/Frameworks/ColorSync.framework/Versions/A/ColorSync (compatibility version 1.0.0, current version 3730.0.0)
  /usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)

However, there is one other surprising dependency, because trying to launch the application fails:

$ ./color-corners
dyld[95470]: Symbol not found: __ZNSt3__13pmr15memory_resourceD2Ev
  Referenced from: <15D1042B-EDEF-3DD0-831C-DB3B35972406> /Users/vasya/code/qt/color-corners/build/Qt_6_5_1_static/Release/color-corners.app/Contents/MacOS/color-corners
  Expected in:     <3EE92404-8FC3-374B-A598-D5C9A8CD64B5> /usr/lib/libc++.1.dylib
Abort trap: 6

So all of a sudden it cannot find C++/LLVM runtime library. I don’t know yet, how to link to it statically or how to set the right path to it, but the “workaround” is well known:

$ DYLD_LIBRARY_PATH=/opt/homebrew/opt/llvm/lib/c++ ./color-corners

And then it launches fine.

At the same time, building without Qt Creator produces a different result. Here’s a build from bare CLI:

$ cd ~/code/qt/color-corners/color-corners
$ mkdir build && cd $_
$ cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="/Users/vasya/programs/qt/6.5.1-static" ..
$ cmake --build .
$ ./color-corners.app/Contents/MacOS/color-corners

And it launches just fine without setting DYLD_LIBRARY_PATH. Huh.

I compared otool output for both executables (left one is produced by Qt Creator, right one is built from CLI), and they are the same except for that exact C++ library:

Different C++ runtime dependency with and without Qt Creator

As we can see, basic CMake/Ninja build from CLI is capable of setting the dependencies paths correctly, but Qt Creator build is not. Not to mention Qt Creator’s inability to auto-detect default system C/C++ compilers. Hah, by the way, it still requires manually setting CMAKE_MAKE_PROGRAM to Ninja path for every project, despite it being available in system’s PATH.

Yeah, so much progress has happened in Qt Creator from its last 4.x version in 2021 till the current 11.0.3 version in 2023 - fucking seven major versions in just two years. Not every IDE is developed so rapidly and with so many great new features! Too bad I can’t recall a single such feature that would be worth increasing the major version number.

2024-01-02 | Qt 5.15.12, Mac OS 13.6, Xcode 15

Got these problems trying to build Qt 5.15.12 on Mac OS 13.6.3 (on Apple M2 Pro) with Xcode 15.0.1 (and then 15.1).

Failed to parse default search paths from compiler output

First the configuration failed:

$ cd /Users/vasya/programs/qt
$ mkdir 5.15.12
$ cd ./src/5.15.12
$ mkdir build && cd $_
$ ../configure -static -release -no-pch -prefix "/Users/vasya/programs/qt/5.15.12-static" -skip qtwebengine -nomake tests -nomake examples -nomake tools

...
Creating qmake...
...................................................................................................Done.
Info: creating super cache file /Users/vasya/programs/qt/src/5.15.12/build/.qmake.super
Info: creating cache file /Users/vasya/programs/qt/src/5.15.12/build/.qmake.cache
Info: creating stash file /Users/vasya/programs/qt/src/5.15.12/build/.qmake.stash
Project ERROR: failed to parse default search paths from compiler output

That is because of this bug, which is probably Apple’s fault. The patch (until a newer Qt version is released) is the following (this is supposed to be applied on /path/to/qt/src/5.15.12/qtbase/mkspecs/features/toolchain.prf):

diff --git a/mkspecs/features/toolchain.prf b/mkspecs/features/toolchain.prf
index 0040b6c..bfad10d 100644
--- a/mkspecs/features/toolchain.prf
+++ b/mkspecs/features/toolchain.prf
@@ -288,9 +288,12 @@
                 }
             }
         }
-        isEmpty(QMAKE_DEFAULT_LIBDIRS)|isEmpty(QMAKE_DEFAULT_INCDIRS): \
+        isEmpty(QMAKE_DEFAULT_INCDIRS): \
             !integrity: \
-                error("failed to parse default search paths from compiler output")
+                error("failed to parse default include paths from compiler output")
+        isEmpty(QMAKE_DEFAULT_LIBDIRS): \
+            !integrity:!darwin: \
+                error("failed to parse default library paths from compiler output")
         QMAKE_DEFAULT_LIBDIRS = $$unique(QMAKE_DEFAULT_LIBDIRS)
     } else: ghs {
         cmd = $$QMAKE_CXX $$QMAKE_CXXFLAGS -$${LITERAL_HASH} -o /tmp/fake_output /tmp/fake_input.cpp
@@ -411,7 +414,7 @@
         QMAKE_DEFAULT_INCDIRS = $$split(INCLUDE, $$QMAKE_DIRLIST_SEP)
     }
 
-    unix:if(!cross_compile|host_build) {
+    unix:!darwin:if(!cross_compile|host_build) {
         isEmpty(QMAKE_DEFAULT_INCDIRS): QMAKE_DEFAULT_INCDIRS = /usr/include /usr/local/include
         isEmpty(QMAKE_DEFAULT_LIBDIRS): QMAKE_DEFAULT_LIBDIRS = /lib /usr/lib
     }

Also, even though that was on Apple M2 Pro, I didn’t need to provide QMAKE_APPLE_DEVICE_ARCHS=arm64.

Symbol not found monotonic_buffer_resource

So configuration succeeded, but build failed:

$ time make -j12

...
dyld[36548]: Symbol not found: __ZTVNSt3__13pmr25monotonic_buffer_resourceE
  Referenced from: <1F5B3ABC-7C7F-3A3C-AEC9-14565D629239> /Users/vasya/programs/qt/src/5.15.12/build/qtbase/lib/QtCore.framework/Versions/5/QtCore
  Expected in:     <6866B472-E07D-3405-A9F5-C35EAE010385> /usr/lib/libc++.1.dylib

So it’s missing vtable for std::__1::pmr::monotonic_buffer_resource, for some reason. From the discussions on the internet, it seems to be cause by this new Xcode linker problem, but I did have LDFLAGS="$LDFLAGS -Wl,-ld_classic" in my ~/.bash_profile, so I don’t know what else it needs.

Then I found this bugreport and this patch (which seems to be derived from this one). So you need to patch /path/to/qt/src/5.15.12/qtbase/src/corelib/global/qcompilerdetection.h:

diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h
index 2a48c82..f374c53 100644
--- a/src/corelib/global/qcompilerdetection.h
+++ b/src/corelib/global/qcompilerdetection.h
@@ -1065,6 +1065,11 @@
 // Also disable <atomic>, since it's clearly not there
 #  undef Q_COMPILER_ATOMICS
 # endif
+# if defined(Q_CC_CLANG) && defined(Q_OS_MAC) && defined(__cpp_lib_memory_resource) \
+   && ((defined(__MAC_OS_X_VERSION_MIN_REQUIRED)  && __MAC_OS_X_VERSION_MIN_REQUIRED  < 140000) \
+    || (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 170000))
+#  undef __cpp_lib_memory_resource // Only supported on macOS 14 and iOS 17
+# endif
 # if defined(Q_CC_CLANG) && defined(Q_CC_INTEL) && Q_CC_INTEL >= 1500
 // ICC 15.x and 16.0 have their own implementation of std::atomic, which is activated when in Clang mode
 // (probably because libc++'s <atomic> on OS X failed to compile), but they're missing some

and /path/to/qt/src/5.15.12/qtbase/src/corelib/tools/qduplicatetracker_p.h:

diff --git a/src/corelib/tools/qduplicatetracker_p.h b/src/corelib/tools/qduplicatetracker_p.h
index 8f51751..26e7051 100644
--- a/src/corelib/tools/qduplicatetracker_p.h
+++ b/src/corelib/tools/qduplicatetracker_p.h
@@ -52,7 +52,7 @@
 
 #include <qglobal.h>
 
-#if QT_HAS_INCLUDE(<memory_resource>) && __cplusplus > 201402L
+#ifdef __cpp_lib_memory_resource
 #  include <unordered_set>
 #  include <memory_resource>
 #else

No template named unary_function in namespace std

After patching those two files the build progressed further, but failed with another error:

/Users/vasya/programs/qt/src/5.15.12/qtmultimedia/src/plugins/avfoundation/camera/avfcamerautility.mm:104:35: error: no template named 'unary_function' in namespace 'std'; did you mean '__unary_function'?
struct FormatHasNoFPSRange : std::unary_function<AVCaptureDeviceFormat *, bool>
                             ~~~~~^~~~~~~~~~~~~~
                                  __unary_function
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.2.sdk/usr/include/c++/v1/__functional/unary_function.h:46:1: note: '__unary_function' declared here
using __unary_function = __unary_function_keep_layout_base<_Arg, _Result>;
^
1 error generated.

That one I’ve seen before, you’ll need to edit /path/to/qt/src/5.15.12/qtmultimedia/src/plugins/avfoundation/camera/avfcamerautility.mm:

-struct FormatHasNoFPSRange : std::unary_function<AVCaptureDeviceFormat *, bool>
+struct FormatHasNoFPSRange : std::__unary_function<AVCaptureDeviceFormat *, bool>

No member named move in namespace std

Having fixed the previous problem, I got some other errors later:

/Users/vasya/programs/qt/src/5.15.12/qtlocation/src/3rdparty/mapbox-gl-native/include/mbgl/util/unique_any.hpp:51:31: error: no member named 'move' in namespace 'std'
            vtable->move(std::move(rhs.storage), storage);
                         ~~~~~^
/Users/vasya/programs/qt/src/5.15.12/qtlocation/src/3rdparty/mapbox-gl-native/include/mbgl/util/unique_any.hpp:69:25: error: no member named 'move' in namespace 'std'
        unique_any(std::move(rhs)).swap(*this);
                   ~~~~~^
/Users/vasya/programs/qt/src/5.15.12/qtlocation/src/3rdparty/mapbox-gl-native/include/mbgl/util/unique_any.hpp:91:33: error: no type named 'move' in namespace 'std'
            unique_any tmp(std::move(rhs));
                           ~~~~~^
/Users/vasya/programs/qt/src/5.15.12/qtlocation/src/3rdparty/mapbox-gl-native/include/mbgl/util/unique_any.hpp:94:39: error: no member named 'move' in namespace 'std'
                rhs.vtable->move(std::move(storage), rhs.storage);
                                 ~~~~~^
/Users/vasya/programs/qt/src/5.15.12/qtlocation/src/3rdparty/mapbox-gl-native/include/mbgl/util/unique_any.hpp:98:35: error: no member named 'move' in namespace 'std'
                vtable->move(std::move(tmp.storage), storage);
                             ~~~~~^
/Users/vasya/programs/qt/src/5.15.12/qtlocation/src/3rdparty/mapbox-gl-native/include/mbgl/util/unique_any.hpp:154:41: error: no member named 'move' in namespace 'std'; did you mean simply 'move'?
            new (&dest.stack) ValueType(std::move(reinterpret_cast<ValueType&>(src.stack)));
                                        ^~~~~~~~~
                                        move
/Users/vasya/programs/qt/src/5.15.12/qtlocation/src/3rdparty/mapbox-gl-native/include/mbgl/util/unique_any.hpp:153:14: note: 'move' declared here
        void move(Storage&& src, Storage& dest) override {
             ^
/Users/vasya/programs/qt/src/5.15.12/qtlocation/src/3rdparty/mapbox-gl-native/include/mbgl/util/unique_any.hpp:257:49: error: no member named 'move' in namespace 'std'
    auto retValue = static_cast<ValueType>(std::move(*temp));
                                           ~~~~~^
/Users/vasya/programs/qt/src/5.15.12/qtlocation/src/3rdparty/mapbox-gl-native/include/mbgl/util/unique_any.hpp:259:17: error: no member named 'move' in namespace 'std'
    return std::move(retValue);
           ~~~~~^
8 errors generated.

From these I can only guess that there is still something wrong with C++ runtime detection/discovery, and the way I fixed this particular error is by adding #include <utility> to /path/to/qt/src/5.15.12/qtlocation/src/3rdparty/mapbox-gl-native/include/mbgl/util/unique_any.hpp.

After that the build succeeded. And by the way, it succeeded with Xcode 15.1 too, so I didn’t need to have -Wl,-ld_classic appended to the LDFLAGS environment variable anymore.

2024-06-11 | Even more unknown runtime dependencies with dynamic Qt 6.7.1

With Qt 6.7.1 dynamic build on Windows I noticed that this set of runtime dependencies is no longer(?) correct, and it could have been so for quite some time now.

First of all, since we are all using CMake, right, here’s how one can try to use CMake for collecting all the application’s runtime dependencies:

#get_target_property(QT_TARGET_TYPE Qt${QT_VERSION_MAJOR}::Core TYPE)
if("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows") # `AND NOT ${QT_TARGET_TYPE} STREQUAL "STATIC_LIBRARY"` or `AND ${QT_TARGET_TYPE} STREQUAL "INTERFACE_LIBRARY"`?
    #file(GENERATE OUTPUT debug/dlls.txt CONTENT $<TARGET_RUNTIME_DLLS:${CMAKE_PROJECT_NAME}>)
    if(NOT EXISTS ${CMAKE_INSTALL_PREFIX}/${EXECUTABLE_INSTALLATION_PATH}) # it doesn't exist before the very first installation yet
        #install(DIRECTORY DESTINATION ${CMAKE_INSTALL_PREFIX}/${EXECUTABLE_INSTALLATION_PATH}) # still too late, because add_custom_command() will execute before that
        file(MAKE_DIRECTORY ${CMAKE_INSTALL_PREFIX}/${EXECUTABLE_INSTALLATION_PATH}) # but at least this one will execute before add_custom_command()
    endif()
    add_custom_command(
        TARGET ${CMAKE_PROJECT_NAME}
        POST_BUILD
        COMMAND ${CMAKE_COMMAND} -E copy_if_different
            $<TARGET_RUNTIME_DLLS:${CMAKE_PROJECT_NAME}> # locate DLLs (might discover some redundant ones too)
            ${CMAKE_INSTALL_PREFIX}/${EXECUTABLE_INSTALLATION_PATH} # where to copy them
        COMMAND_EXPAND_LISTS
        COMMENT "Copying runtime dependencies (DLLs)"
    )
endif()

Sadly, it doesn’t always find all the dependencies, and in case of Qt for one of my applications it only copied the following set:

├─Qt6Core.dll
├─Qt6Gui.dll
├─Qt6Network.dll
├─Qt6OpenGL.dll
├─Qt6Qml.dll
├─Qt6QmlModels.dll
├─Qt6Quick.dll
└─some-qt-quick.exe

And when I tried to launch the application, I got an error about missing platform plugin:

The application failed to start because no qt platform plugin could be initialized

Here’s also a screenshot, just in case:

Qt error, missing platform plugin

To resolve that I needed to copy /path/to/qt/plugins/platforms/qwindows.dll to my application installation folder, keeping the folder structure. And then the application launched but with an “empty” application window:

Qt application missing some unknown DLLs

When you see this with a Qt-based application, that’s a symptom of some more DLLs missing, which aren’t required at launch (so you can’t track them with Dependency Walker, DIE or a similar tool?), but apparently are attempted to be loaded a bit later at runtime (and produce no error on failure?). After quite some trial and error I discovered that it’s also Qt6QmlWorkerScript.dll that was missing, which I then deployed too.

But even after that something was still missing, because I was still getting an “empty” application window. When you find yourself in a situation like this, the last resort is to just drop your executable into /path/to/qt/bin/ and launch it from there, and if it launches fine, then you can copy the entiry Qt prefix and start throwing things out of it. That is how I discovered that my application also needs /path/to/qt/qml/QtQml/WorkerScript/{qmldir,workerscriptplugin.dll} files.

So here’s the final deployment folder structure:

├── Qt6Core.dll
├── Qt6Gui.dll
├── Qt6Network.dll
├── Qt6OpenGL.dll
├── Qt6Qml.dll
├── Qt6QmlModels.dll
├── Qt6QmlWorkerScript.dll
├── Qt6Quick.dll
├── some-qt-quick.exe
├── plugins
│   └── platforms
│       └── qwindows.dll
└── qml
    └── QtQml
        └── WorkerScript
            ├── qmldir
            └── workerscriptplugin.dll

Naturally, for your application this set might be different, as your application might be using different parts of Qt functionality and so depending on different Qt modules.

2024-07-09 | Ещё один некоторый итог

Прошло ещё сколько-то времени, я узнал ещё немного нового, а главное сам поучаствовал в сборке нескольких кросс-платформенных проектов. И теперь я могу сказать, что мой предыдущий итог трёхлетней давности конечно смешной, но не очень справедливый.

Глядя на размеры Qt, сколько в него входит компонентов, что он ими умеет делать, а также принимая во внимание количество сторонних зависимостей - это большое чудо и достижение, что он вообще собирается, не говоря уже о том, что делает он это на нескольких платформах. Более того, теперь, когда я такой крутой специалист, я бы даже сказал, что Qt везде собирается почти из коробки - это же вообще умопомрачительно, сколько труда ушло, чтобы такое обеспечить.

Да, безусловно, для рядового пользователя/погроммиста собрать Qt из исходников это (очень) сложно, и действительно, очень много чего нужного не указано в документации. Но как я сейчас вижу, многое из того, что я считал недостатком документации Qt, на самом деле является достаточно общими сведениями, относящимися к теме сборки чего бы то ни было вообще. И как бы ожидается, что ты должен быть в курсе всего этого, раз уж полез сюда, и Qt не обязан водить каждого начинающего инженегра за ручку и вытирать за ним сопли.

Так что да, прежде чем критиковать Qt и его систему сборки, я бы рекомендовал очередному смищному критикану сначала попробовать запилить собственный небольшой проект с парой-тройкой зависимостей и обеспечить его сборку на нескольких платформах (хоть где-то ещё кроме Windows), и чтобы это работало не только на его пекарне (с захардкоженными путями и кучей DLL, сваленных в System32), но и на машинах реальных пользователей (из общения с которыми тоже можно будет узнать что-то новое). После такого опыта какая-то часть претензий должна будет отвалиться сама собой.