I have distilled this very simple CMake project that uses vcpkg and builds a dead simple Qt gui application just showing a main window. I can get it to build successfully in Visual Studio 2022 but I cannot get it to run seamlessly. The problem arises because the Qt platform DLL isn’t copied to the output location with the other DLL dependencies in the post build step.
The qwindows.dll
(or qwindowsd.dll
) file is meant to be copied to the output location with the executable and other DLLs but in a platforms
subdirectory. This does not happen during a build, but if I create the directory and copy it manually then the application works.
To me this is something that should work seamlessly as part of the build process so I’m curious to know if I’m doing something wrong or I’ve set something up incorrectly.
Now I know that the simplest hacky solution would be to manually put a CMake post build step to copy the appropriate DLL from the vcpkg_installed
directory to the output directory. But this seems like a hack as the system should handle this already otherwise many other people would be having this issue as well.
So the questions I’m asking:
- Am I missing something trivial here in the configuration?
- Am I not understanding something with how CMake + Qt work?
- Is this combination of CMake, vcpkg, and Qt a supported configuration that is expected to work?
The CMakeLists.txt
is (and mostly taken from Qt’s own example):
cmake_minimum_required(VERSION 3.22 FATAL_ERROR)
project(QtTest LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets)
qt_standard_project_setup()
add_executable(QtGuiTest
Source/Main.cpp
Source/MainWindow.cpp
Source/MainWindow.hpp
)
target_link_libraries(QtGuiTest PRIVATE Qt6::Core Qt6::Gui Qt6::Widgets)
set_target_properties(QtGuiTest PROPERTIES WIN32_EXECUTABLE ON MACOSX_BUNDLE ON)
The CMakePresets.json
is:
{
"version": 3,
"cmakeMinimumRequired": {
"major": 3,
"minor": 22,
"patch": 0
},
"configurePresets": [
{
"name": "default",
"displayName": "Default",
"generator": "Visual Studio 17 2022",
"architecture": "x64",
"toolchainFile": "$env{VCPKG_ROOT}\scripts\buildsystems\vcpkg.cmake"
}
]
}
The vcpkg.json
is:
{
"$schema": "https://raw.githubusercontent.com/microsoft/vcpkg/master/scripts/vcpkg.schema.json",
"name": "qtguitest",
"version": "0.1",
"dependencies": [
"qtbase"
]
}
Then I execute CMake to build out of the source tree with the default
preset.
The code for the application is literally this:
// MainWindow.hpp
#pragma once
#include <QtGui>
class MainWindow : public QWindow
{
Q_OBJECT
public:
explicit MainWindow(QWindow* parent = nullptr);
};
// MainWindow.cpp
#include "MainWindow.hpp"
MainWindow::MainWindow(QWindow* parent)
: QWindow(parent)
{}
// Main.cpp
#include <QApplication>
#include "MainWindow.hpp"
int main(int argc, char* argv[])
{
QApplication q_application{argc, argv};
MainWindow main_window;
main_window.show();
return q_application.exec();
}
For reference I’m using:
- The latest Visual Studio 2022 Community Edition (as of 1/10/2022)
- CMake 3.22 installed (though vcpkg downloads 3.24 and uses that)
- vcpkg (as of 1/10/2022)
- Qt 6.3.2 is being installed
3
Answers
Thanks to help from the other answers here I was able to figure this snippet out to add to the CMake configuration I had above.
Which ends up calling the
windeployqt
application in the simplest manner in a post-build step.As far as I am aware you have to call a tool called windeployqt to scan your source/binaries and build a list of stuff needed. Than it should automatically deploy that. Be aware that it might be not enough as some libs/plugins might have external dependencies and those might not be taken into consideration. Some dynamic dependencies or plugins might not be recognized as well, but look into windeployqt help to understand what you can achieve.
There is no magic in vcpkg to automatically deploy Qt6 dlls to where they are needed. Readup on https://doc.qt.io/qt-6/windows-deployment.html to learn what is necessary.
Also for Qt 6.3 read up on https://www.qt.io/blog/cmake-deployment-api . Qt has its own cmake API to help in deployment.
If you want to manually call windeployqt from cmake make sure you use the cmake target! In vcpkg the target has been adjusted to take care of release/debug.
An alternative to deploy the dlls is to deploy a qt.conf with the correct paths set. There is a debug/release variant in
<vcpkg_installed>/<triplet>/tools/Qt6
which could be used as a template to correctly set it up