The short answer: Don't waste your time on this. Link dynamically, and let an installer distribute your application. This is the only mode that is seriously supported by Qt5 and by CMake. Working without their support and against their advise is close to hopeless. Setting up an installer is far easier (though no fun either - we currenly use black magic from https://hk.saowen.com/a/d1cf90fcfea6d511629fd5a6c8113808721a7f19656677e8a5fab370a8d35cd4).
The long (yet incomplete) answer, in case you want to outsmart me:
The following steps brought me deceptively close to a solution. I succeeded in building static libraries, but I failed to link my application: Upon getting hundreds of LNK2001 and LNK2019 errors caused by cryptic unresolved external symbols, I had to give up.
So here comes a step-by-step description of what worked for me in October 2018 on a Windows10 virtual desktop. For each installation step, a check is indicated. If a check fails then fix the problem before proceeding further.
To start, install some tools that are needed later on:
- Perl, needed for zlib and openssl configuration:
- An editor that can handle Unix end-of-line. Notepad won't do. Install vim, emacs, or whatsoever.
- chocolatey package manager, needed to install flex and bison:
- Run admin shell (Circle Menu > search for "Command" > right-click on "Command Prompt" > run as Admin)
- Copy download command from https://chocolatey.org/install#install-with-cmdexe
- Paste command to admin shell, and watch installation
- Check: in terminal, try command "choco"
- flex and bison, needed by qtbase compilation:
- It's not obvious to get the right version of flex. From gnuwin32.sourceforge.net I got an outdated flex that missed a command-line argument required during Qt compilation. Compiling flex from source introduces a tail of further dependences. The simplest solution I found uses the Chocolatey package manager.
- In admin shell, run: "choco install winflexbison3". This creates a directory X that contains the binaries win_flex.exe and win_bison.exe and a supporting "data" folder. Find out the location of X. In my case, X=C:\ProgramData\chocolatey\lib\winflexbison3\tools
- Check: cd X, and run "win_flex --version", "win_bison --version".
- During Qt compilation, these tools will be needed under their standard names "flex" and "bison". Therefore we need symbolic links flex->win_flex, bison->win_bison.
- mlink X\flex.exe X\win_flex.exe
- mlink X\bison.exe X\win_bison.exe
- note: mklink needs absolute paths to work reliably
- note: the symlink must not go to another directory lest bison won't find the "data" folder
- Add X to the %PATH%
- Check: in any shell, try "flex --version" and "bison --version"
So far for the tools. Now we need two libraries that must be statically linked to Qt (magic learned from https://stackoverflow.com/a/41815812/1017348):
- Build static zlib:
- Download https://zlib.net/zlib1211.zip
- Unpack to C:\Development\zlib-1.2.11
- Edit the file win32\Makefile.msc with an editor that can handle Unix EOLs:
- Find the line starting with CFLAGS
- Replace -MD with -GL -MT -Zc:wchar_t-
- Find the line starting with LDFLAGS
- Replace -debug with -opt:icf -dynamicbase -nxcompat -ltcg /nodefaultlib:msvcrt
- Build zlib using the following command (should take less than a minute):
- nmake -f win32/Makefile.msc AS=ml64 LOC="-DASMV -DASMINF -DNDEBUG -I." OBJA="inffasx64.obj gvmat64.obj inffas8664.obj"
- Check: as a result, the source directory must contain zlib.lib (856kB), inter alia.
- Build static openssl library:
- Download https://www.openssl.org/source/openssl-1.1.1.tar.gz
- Unpack to C:\Development\openssl-1.1.1
- Copy files from zlib: cd zlib-1.2.11; xcopy zconf.h ..\openssl-1.1.1\ ; same for zlib.h zlib.lib zlib.pdb
- cd ..\openssl-1.1.1
- perl Configure VC-WIN64A no-asm no-shared zlib no-zlib-dynamic threads --prefix=C:\opt\local_x64
- note: I added "no-asm" to avoid installation of NASM (Netwide Assembler)
- note: I changed prefix, since only admins can install to C:\Windows
- Edits the file ''makefile'':
- Find the line that starts with: CFLAG
- Append: /Zc:wchar_t- /GL /Zi
- Find the line that starts with: LDFLAGS
- Replace /debug with /incremental:no /opt:icf /dynamicbase /nxcompat /ltcg /nodefaultlib:msvcrt
- Find the line that starts with: CNF_EX_LIBS
- Replace ZLIB1 with zlib.lib
- Build: "nmake"
- Check: directory must contain openssl.lib (size?)
Now we are ready to build qtbase from source, using the command-line version of the Visual Studio C++ compiler:
- Download (update location for latest Qt): https://download.qt.io/archive/qt/5.11/5.11.2/submodules/qtbase-everywhere-src-5.11.2.zip
- Move the source directory to the Local Disk (C:\Development)
- To work with Visual Studio, use a specially configured terminal. Use Taskbar>Circle>Search to launch "x64 Native Tools Command Prompt for VS 2017"
- cd qtbase...
- Check: configure --help
- configure -platform win32-msvc2017 -opensource -confirm-license -release -static -openssl-linked no-dbus -no-libpng -no-libjpeg -nomake examples -nomake tests -prefix C:\opt\local_x64 -I C:\Development\openssl-1.1.1\include -L C:\Development\openssl-1.1.1 -D OPENSSL_LIBS=C:\Development\openssl-1.1.1\libssl.lib
- while debugging "configure", it may be necessary to delete config.cache.
- option -I does not work with relative paths
- the label "win32" may look wrong if we want to use Qt in a 64bit application, but we are advised not to worry: building Qt under Windows: really with "-platform win32-msvc2017"?
- I don't know how to get rid of Sql: https://bugreports.qt.io/browse/QTBUG-71253
- libpng and libjpeg are needed by optional code. They are provided in src/3rdparty, which tends to provoke clashes with system provided library versions. Therefore, we build without PNG and JPG support.
- nmake
- Check: static libraries (big .lib and small .prl) land in directory lib/
- 54.7 MB Qt5Core.lib
- 23.4 MB Qt5Widgets.lib
- 18.2 MB Qt5Gui.lib
- 07.4 MB Qt5Network.lib
- ...
That's it, we have static Qt libraries. Only, as said above, this did not help me when I tried to link my application with these libraries.