skip to Main Content

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


  1. Chosen as BEST ANSWER

    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.

    add_custom_command(TARGET QtGuiTest POST_BUILD 
        COMMAND Qt6::windeployqt
        ARGS $<TARGET_FILE:QtGuiTest>
    )
    

    Which ends up calling the windeployqt application in the simplest manner in a post-build step.


  2. 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.

    Login or Signup to reply.
  3. 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

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search