Deploy Qt dlls on build time

Categories: Tool chain

Problem

You have multiple Qt installation on your system and <qt>/bin is not in your PATH variable. But you would like to debug your qt executable.

The problem now is that the build tool cannot find the qt dll’s on your system.

Solution

Let CMake and Qt do all this for you. Use windeployqt.exe to deploy all necessary dlls to your build dir.

Qt offers since Version 6 the windeployqt.exe to collect all necessities which belong to your app.

Example code:

For our example, we have this code.

#include <QtCore/QObject>
#include <QtWidgets/QWidget>

int main(int argc, char* argv[])
{
    const auto* obj = new QObject();
    const auto* wdg = new QWidget();

    return 0;
}

We build it, enter the output directory and run windeploy with

>> cd <path/to/YourApp.exe>
>> windeployqt YourApp.exe --dir .

Now windeployqt scans YourApp.exe for symbols from qt and copies all dll’s, which are necessary to run YourApp, to the given folder (–dir . ).

Output of windeployqt

Adding Qt6Svg for qsvgicond.dll
Direct dependencies: Qt6Core Qt6Widgets
All dependencies   : Qt6Core Qt6Gui Qt6Widgets
To be deployed     : Qt6Core Qt6Gui Qt6Svg Qt6Widgets
Updating Qt6Cored.dll.
Updating Qt6Guid.dll.
Updating Qt6Svgd.dll.
Updating Qt6Widgetsd.dll.
Updating opengl32sw.dll.
Updating D3Dcompiler_47.dll.
Creating directory Z:/Development/YourApp/bin/Debug/plugins/iconengines.
Updating qsvgicond.dll.
Creating directory Z:/Development/YourApp/bin/Debug/plugins/imageformats.
Updating qgifd.dll.
Updating qicod.dll.
Updating qjpegd.dll.
Updating qsvgd.dll.
Creating directory Z:/Development/YourApp/bin/Debug/plugins/platforms.
Updating qwindowsd.dll.
Creating directory Z:/Development/YourApp/bin/Debug/plugins/styles.
Updating qwindowsvistastyled.dll.

Directory view

We have the structure qt needs to find all dll’s.

  • bin
    • YourApp.exe
    • Qt6Cored.dll
    • Qt6Guid.dll
    • Qt6Svgd.dll
    • Qt6Widgetsd.dll
    • opengl32sw.dll
    • D3Dcompiler_47.dll
    • plugins
      • iconengines
        • qsvgicond.dll
      • imageformats
        • qgifd.dll
        • qicod.dll
        • qjpegd.dll
        • qsvgd.dll
      • platforms
        • qwindowsd.dll
      • styles
        • qwindowsvistastyled.dll

Can we do this automatically in our build tool?

Yes, with CMake we can.

CMAKE_MINIMUM_REQUIRED(VERSION 3.20)

SET(PROJECT_BIN_PATH ${CMAKE_CURRENT_SOURCE_DIR}/bin)

PROJECT(YourApp)

FIND_PACKAGE(Qt6 REQUIRED COMPONENTS Core Widgets)

QT_STANDARD_PROJECT_SETUP()
QT_ADD_EXECUTABLE(
    YourApp
    source/main.cpp
)

TARGET_LINK_LIBRARIES(YourApp PRIVATE Qt6::Core)
TARGET_LINK_LIBRARIES(YourApp PRIVATE Qt6::Widgets)

IF(MSVC)
    SET_TARGET_PROPERTIES(YourApp PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BIN_PATH})
ENDIF(MSVC)

ADD_CUSTOM_COMMAND(
  TARGET YourApp
  POST_BUILD
  COMMAND
    CD ${PROJECT_BIN_PATH} &&
    ${WINDEPLOYQT_EXECUTABLE} ${PROJECT_BIN_PATH}/Debug>/YourApp.exe
      --verbose 1 --dir .
    )

What does CMake do here?

We focus on the custom command on the bottom.

ADD_CUSTOM_COMMAND(
  TARGET YourApp
  POST_BUILD
  COMMAND
    CD ${PROJECT_BIN_PATH} &&
    ${WINDEPLOYQT_EXECUTABLE} YourApp.exe
      --verbose 1 --dir .
    )

This is a POST_BUILD script, that executes after the build of YourApp (TARGET).

  • First we enter the build directory with CD ${PROJECT_BIN_PATH}.
  • Then we execute windeploy on our app (YourApp.exe) with ${WINDEPLOYQT_EXECUTABLE} YourApp.exe --verbose 1 --dir .
  • WINDEPLOYQT_EXECUTABLE is generated by qt and stores the absolute path to windeployqt

Done 🙂

Now we have YourApp.exe and all dll’s in the build directory.

Wait, i use a debug and a release build in my project!

Okay, here we must tell CMake in which configurations we want execute which script. Fortunately, CMake can offer here something for us. Generator Expressions which are available in since 3.20.

With these we can run different commands for different build configurations.

SET(BIN_DBG ${PROJECT_BIN_PATH}/Debug)
SET(BIN_REL ${PROJECT_BIN_PATH}/Release)

ADD_CUSTOM_COMMAND(
  TARGET YourApp
  POST_BUILD
  COMMAND
    CD $<$<CONFIG:Debug>:${BIN_DBG}>$<$<CONFIG:Release>:${BIN_REL}> &&
    ${WINDEPLOYQT_EXECUTABLE} YourApp.exe
       --verbose 1 --dir . --plugindir plugins --no-translations --compiler-runtime
    )

The Line CD $<$:${BIN_DBG}>$<$:${BIN_REL}> simply enters the directory according to your current build. bin/Debug for the debug build or bin/Release for the release build.

The rest work automatically, since windeployqt tests if the build needs debug or release dll’s.

And, if you are using other types of builds (RelWithDebInfo, MinSizeRel), feel free to add them.

The sources can be found here: Deploy Qt6 Dlls on Windows

Have fun with it. 🙂


    Leave a Reply

    Your email address will not be published.

    Hi Human, please solve this: + 70 = 74