Deploy Qt dlls on build time
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
- iconengines
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