Replicating qmake project that uses MinGW and static Qt build

I am building a Qt application on Windows using static Qt build made with MinGW and using MinGW to compile the application itself too (MinGW wasn’t my choice, unfortunately I have to use it for this project).

The application builds fine with both qmake and CMake, but the resulting executable is different when it is built using qmake and when it is built using CMake. In particular, the imports are different:

As you can see, the executable built with CMake requires some more DLLs for runtime, while executable built with qmake does not require those. In practice this means that I can run the qmake-produced executable and it will launch fine without complaining about missing DLLs, but CMake-produced executable will complain about missing MinGW runtime DLLs, zstd DLL (and likely zlib DLL too).

The Qt is built with -static-runtime option, so the application shouldn’t require MinGW runtime DLLs (and it doesn’t require those with qmake, as expected), but okay, that could probably be “fixed” for CMake like this:

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

Most probably similar “workarounds” would apply to zstd and zlib, although I don’t get how all of a sudden these are shared libraries, because qmake should’ve encountered the same problem, but it hasn’t, so it used static variants somehow.

And so the point/question is, what does qmake do behind the scenes for MinGW builds, so developer doesn’t need to care about such things? Is there some “magic” property for Qt projects in CMake which would do the same?

For the reference, here are my project files:

…oh well, I realized that I can just take a look at qmake output, and there I saw that it links to a lot of things, out of which the following seemed the most relevant: e:/path/to/my/static/Qt/lib/libQt5Core.a, -lz and -lzstd.

And so that is what my CMake project was missing:

#get_target_property(QT_TARGET_TYPE Qt${QT_VERSION_MAJOR}::Core TYPE)
#if(${QT_TARGET_TYPE} STREQUAL "STATIC_LIBRARY")
    if(MINGW)
        set(CMAKE_EXE_LINKER_FLAGS "-static-libgcc -static-libstdc++ -static")
        target_link_libraries(${CMAKE_PROJECT_NAME}
            PRIVATE
                # QtCore is also required, because without it there will still be error
                # about missing zstd DLL (yes, despite -lzstd being present)
                Qt${QT_VERSION_MAJOR}::Core -lz -lzstd
            )
    endif()
#endif()

Now the CMake-built executable also launches fine without complaining about missing DLLs.

If you have libraries in your project, they’ll also need these flags. It is probably best to do this via:

LDFLAGS="-static-libgcc -static-libstdc++ -static" cmake …

to make sure they get everywhere that is important consistently.

1 Like

Right, I haven’t thought about that. That is a good point, thank you!