Building Qt for static linking

2015-03-31

One of the drawbacks of using such a comprehensive framework as Qt is the massively increased size of you program. When my pet project RandFill was only using the plain Win32-API, it was a single executable file of a couple of hundred kilobytes.

Now, using dynamically linked Qt, the whole package (with DLLs, MSVC redistributables, etc.) is bigger than 20 megabytes as a 64-bit build!

So I thought about switching to statically linking (I am not a lawyer, but I’m pretty sure that since my program is published under the MIT license, it’s alright to link statically with the open-source edition of Qt…).

As always, the road to this wasn’t quite as easy as I hoped for. Thus I’ll write it down for future reference.

Requirements

The premise is basically the same as previously described: Microsoft Visual Studio 2010, Qt 5.2.1, etc. — read the linked blog post for details on how to set-up the environment.

The next steps are meant for 64-bit builds; for 32-bit builds, act accordingly (tools, paths, values).

Preparation

Edit the file {QT_DIR}\qtbase\mkspecs\win32-msvc2010\qmake.conf

In my case, the define for WIN64 wasn’t set (and therefore the build was always 32-bit), so I forced it by commenting out the condition:

DEFINES                += UNICODE WIN32
QMAKE_COMPILER_DEFINES += _MSC_VER=1600 _WIN32
# contains(QMAKE_TARGET.arch, x86_64) {
    DEFINES += WIN64
    QMAKE_COMPILER_DEFINES += _WIN64
# }

Also, further below in that file, the flags for the linkage model had to be changed from MD to MT:

QMAKE_CFLAGS_RELEASE    = -O2 -MT
QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO += -O2 -MT -Zi
QMAKE_CFLAGS_DEBUG      = -Zi -MTd

Configure and build Qt

Open the “Visual Studio x64 Win64 Command Prompt (2010)” from the start menu and navigate to the folder where you expanded the Qt source.

Configure Qt, for example like this:

configure.bat -confirm-license -prefix C:\devel\ext\Qt\5.2.1\_64LIB
-release -opensource -static -platform win32-msvc2010 -mp
-nomake examples -nomake tests -no-icu -no-opengl -no-angle
-no-openssl -skip qtwebkit -skip qtwebkit-examples

Then run nmake.

After that is done, call nmake install.

Build system/project files and source code

Everything else depends on your project settings. For RandFill, I added several conditional statements in my CMakeLists.txt for switching between a static and a shared build.

I also had to add {QT_DIR}\plugins\platforms to the library directories and link with additional libraries:

  • imm32.lib
  • winmm.lib
  • Ws2_32.lib
  • Qt5PlatformSupport.lib
  • qwindows.lib

In addition, the actual source code needs to be modified. I defined a new preprocessor directive called “QT_STATIC” for static builds and included the necessary code:

#ifdef QT_STATIC
    #include <QtCore/QtPlugin>
    Q_IMPORT_PLUGIN (QWindowsIntegrationPlugin)
#endif 

Conclusion

The result is worth the effort: The application is now again a single file (instead of multiple DLLs, spread over several subfolders) and at approximately 10 megabytes — still no lightweight, but a 50% decrease shouldn’t be scoffed at.

Bonus tip:
When in doubt (or rather, if you get unexplainable errors): Just delete the Qt source folder and start anew. I had cases, while approaching the above solution, where deleting the CMake cache or running nmake confclean alone wasn’t enough.

One comment on “Building Qt for static linking

  1. Grateful

    Got errors for several days and all I was missing was the line:

    Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin)

    Thank you very much! Your post really saved me!

Leave a comment

Your email address will not be published.