CMake avoid copying Qt5 Dlls on windows - c++

I'm using Qt and CMake to develop C++ applications.
On linux there my qt application runs fine, however on windows i have to copy the folders
C:\Qt\5.15.8\msvc2019_64\bin
and
C:\Qt\5.15.8\msvc2019_64\plugins
to the binary folder.
If I do not copy these files to the binary folder I'm getting Qt5xxx.dll missing at application startup.
However (especially when using CMake Multi Config generators) this is a pretty waste of HDD space (and time).
Is there any way to avoid this (this issue seams to be windows only)
I'm running the example taken from https://doc.qt.io/archives/qt-5.12/cmake-manual.html
I also did try to set the CMAKE_PREFIX_PATH before find_package()
list(APPEND CMAKE_PREFIX_PATH "C:/Qt/5.15.8/msvc2019_64/bin")
find_package(Qt5 COMPONENTS ${ACTIVE_QT_MODULES} REQUIRED)
but this does not seam to work. Is there any other way to get this to work?
Thx for your help :)
Edit
To clarify: I'm looking for a solution for a developer PC. All developer PCs already have multiple Qt versions installed at C:/Qt. Therefore in my opinion the copying on developer PCs is not necessary. Of course, when deploying the application to a non developer PC we use the deployqt tool to copy all the necessary stuff

Use CMake to find the necessary directories (dynamically), and generate two outputs. The first is, as recommended by #vre, VS_DEBUGGER_ENVIRONMENT for execution from the debugger and via the IDE. The second is a batch file that sets the environment variables, then invokes the process.
# Get location of Qt DLLS from the bin dir
get_filename_component(QT_BIN_DIR ${QT_MOC_EXECUTABLE} DIRECTORY)
# Also find the location of the Qt plugins, using a random plugin
get_target_property(qsqlite_loc Qt5::QSQLiteDriverPlugin LOCATION_Release)
get_filename_component(Qt5SqlDriver_PLUGIN_DIR ${qsqlite_loc} DIRECTORY)
get_filename_component(Qt5_PLUGINS_DIR ${Qt5SqlDriver_PLUGIN_DIR} DIRECTORY)
# Tell VSCode about these paths so the debugger can launch the app
string( CONCAT debugger_environment
"PATH=${QT_BIN_DIR};%PATH%\n"
"QT_QPA_PLATFORM_PLUGIN_PATH=${Qt5_PLUGINS_DIR}/platforms\n"
"QT_PLUGIN_PATH=${Qt5_PLUGINS_DIR}\n"
)
set_property(TARGET mytarget PROPERTY VS_DEBUGGER_ENVIRONMENT ${USERFILE_ENVIRONMENT})
# Also make a batch file
string( CONCAT batch_contents
"set PATH=${QT_BIN_DIR};%PATH%\n"
"set QT_QPA_PLATFORM_PLUGIN_PATH=${Qt5_PLUGINS_DIR}/platforms\n"
"set QT_PLUGIN_PATH=${Qt5_PLUGINS_DIR}\n"
"$<TARGET_FILE_NAME:${mytarget}>"
)
file( GENERATE OUTPUT "$<TARGET_FILE_DIR:mytarget>/$<TARGET_FILE_BASE_NAME:${mytarget}>.bat"
CONTENT "${batch_contents}" )
Variation: Omit the call to the target executable, and instead allow the .bat file to be called from a terminal to set up future runs from that terminal.
Future improvements: handle UNIX shell syntax for non-Windows builds

This post is just for summarising the comments section.
After lots of input from #vre it turns out that there are 2 ways to solve this issue
add C:/Qt/5.15.8/msvc2019_64/bin to your PATH.
=>Problem here: It is not easy to select a specific QT Version across different projects depending on a project configuration
add
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT <executbale_target>)
and
set_property(TARGET <executable_target> PROPERTY VS_DEBUGGER_ENVIRONMENT "PATH=C:/Qt/5.15.8/msvc2019_64/bin")
=>Problem here: You select different Qt Versions for different projects. However the executable only starts when the (generated) solution file is used to run the executable

Related

Using CMake to find dependencies in an application-specific subfolder

In spite of many years of coding large-scale C++ applications, I do not understand how find_package is supposed to work in a medium-size CMake project, ASSUMING that I want to build the source to dependent packages myself and not simply rely on large systems like opencv, pcl or boost being installed somewhere in a system folder. I can't can't believe that I'm the only person in the world who has shipped multiple OpenCV and other open-source apps, has worked with meta-build systems like NAnt and SCons on major game projects, yet can't understand the most basic things about how CMake works or find a tutorial answering these questions.
In the past, I have essentially hacked around not understaning find_package by setting all the foo_DIR values by hand as CMake complains until I get a working folder.
I would like to run through a simple example which I'm working on right now, and dearly hope someone can explain what I'm doing so wrong.
Firstly, some assumptions:
I want to build everything for both MacOS and Windows, ideally via CMakeGUI. MacOS should build XCodeProjects and Windows should build Visual Studio Solutions.
Where there are dependencies, I want to compile them myself, so I have debug symbols and can modify the dependency source (or at least debug into it.)
No installation of pre-built binaries into system folders, i.e. no use of sudo port install opencv/pcl, etc on mac.
I have multiple projects, and prefer to keep a project and its dependencies in a single folder.
For the purposes of a concrete example, suppose I am building this project, although it's an arbitrary choice to illustrate the process and confusion I suffer:
https://github.com/krips89/opendetection
This lists dependencies, which I have intentionally reordered here so that I can take them in order, as follows:
find_package(OpenCV REQUIRED)
find_package(Eigen REQUIRED)
find_package(Boost 1.40 COMPONENTS program_options REQUIRED )
find_package(PCL REQUIRED)
find_package(VTK REQUIRED)
I would like to have all of these dependencies downloaded and configured in a single path (let's say c:\src on Windows, and ~\src on Mac for simplicity), NOT in a system path. Assume that the actual folder is a sub-folder for this project, and no a sub-folder for all projects. This should also allow for side-by-side installation of multiple projects on the same computer.
Taking this one step at a time:
(1) I clone openCV from https://github.com/opencv/opencv, sync to tag 3.1, configure into the folder opencv_build folder, build and install into opencv_install. I've done this so many times it's pretty straightforward.
(2) As above, but for eigen (although building for eigen doesn't actually do anything s it's a template library. I install to a folder eigen_install
Taking directory shows a series of folders for downloaded dependencies. I have assumed a convention where , and are source repos, and their following _build folders are the "WHere to build the binaries" folders in CMakeGui.
$ ls
boost_1_40_0 opencv opendetection_build
eigen opencv-build opendetection_data
eigen_build opencv_contrib pcl
eigen_install opendetection
All good so far, now let's try to configure opendetection and generate a solution into opendetection_build, and find pendetection's dependencies from within the ~/src folder, that is for the first two dependencies, I hope to find opencv and eigen in the opencv-build and eigen-build folders.
OpenCV immediately fails, as expected, saying:
Could not find a package configuration file provided by "OpenCV" with any of the following names:
OpenCVConfig.cmake
opencv-config.cmake
Add the installation prefix of "OpenCV" to CMAKE_PREFIX_PATH or set "OpenCV_DIR" to a directory containing one of the above files. If "OpenCV" provides a separate development package or SDK, be sure it has been installed.
That's good, because I want to explicitly tell CMake to look for dependent packages under my ~/src folder. Question: Is the use of CMAKE_PREFIX_PATH=/users/foo/src the recommended way to accomplish what I want - looking for all sub-packages under a specific path?
Following this, CMake finds OpenCV (good), and sets OpenCV_DIR = /Users/foo/src/opencv-build.
Question: Given that I have made an "install" to opencv-install (using CMAKE_INSTALL_PREFIX and building the Install Target Of OpenCV, shouldn't it find OpenCV in the opencv-install folder not opencv-build?
Moving on to eigen, I have configured and built eigen, and installed it to ~/src/eigen-install, which since it is a subfolder of CMAKE_PREFIX_PATH (~/src) I might expect to be found. But it doesn't seem to be. Can somebody explain to me what I'm not understanding? Particularly given that Eigen in a template library, and that there are at least three folders (eigen, eigen_build and eigen_install) under CMAKE_PREFIX_PATH which I would have thought CMake would find something in, I assume I must be doing something wrong here. I KNOW from past experience, I can set EIGEN_INCLUDE_DIR by hand in CMakeGUI by hand, and continue hacking forth, but that just seems wrong.
I'm more than willing to write up a web page explaining this for future people as dumb as me if one does not already exist, although I can't understand how use of CMake for basic project configuration and generation is apparently so obvious to everyone but so opaque for me. I have actually been using CMake for some years, usually by just manually setting Boost_INCLUDE_Dir, Foo_INCLUDE_PATH etc manually, but clearly this is not the right solution. Generally, after spending a couple of days fighting through the various packages to generate a solution by manually setting INCLUDE PATHS, LIBRARY PATHS and other options, I just deal with the solution and don't touch CMake again. But I would love to understand what I'm missing about find_package for my (surely not uncommon) use case of wanting to control my project dependencies rather than just using sudo port install * and installing random versions of projects to my global system folders.
As error message says, CMAKE_PREFIX_PATH should be set to installation prefix of the package. E.g., if the package has been built using CMake, this is CMAKE_INSTALL_PREFIX variable's value, if the package has been build using Autotools, this is value of --prefix option used for configure it, and so on.
CMake doesn't search every directory under CMAKE_PREFIX_PATH. That is why specifying it as /users/foo/src is useless if you have the package installed at /users/foo/src/eigen-install.
Instead, you may install all 3d-party packages into /users/foo/src/install, and use that path as CMAKE_PREFIX_PATH in your main project.

CMake post build step: copy multiple files dependent on visual studio configuration

I'm trying to write a CMakeLists.txt which copies as a post build event required dlls from external libraries to the folder in which the executable is located after building. The OS I'm working on is Win7 and VS2010.
There a quite a lot of external libraries, so I do not want to list them individually within the CMakeLists.txt. My current solution is to use file globbing and create a post build event for each library:
FILE(GLOB files "${LIBRARY_DIR}/lib/$(ConfigurationName)/*dll")
MESSAGE("FILE LIST IS: ${files}")
FOREACH(file ${files})
ADD_CUSTOM_COMMAND(
TARGET mylib
POST_BUILD
COMMENT "Copying dll ${file}..."
COMMAND ${CMAKE_COMMAND} -E copy ${file} "${CMAKE_BINARY_DIR}/$(ConfigurationName)/"
)
ENDFOREACH()
Basically, the code snipped above works file if I replace $(ConfigurationName) with Release or Debug. However, I'd like to take the libraries from the corresponding directory dependent on Release or Debug build mode. In the code snipped above, $(ConfigurationName) does not get substituted by the visual studio build mode. I guess this is due to that this is a VS2010 variable which isn't known at cmake generation time).
Does somebody have a smart idea how to resolve this issue?
ADD_CUSTOM_COMMAND understands generator expressions, so you would be able to use $<CONFIG> rather than $(Configuration) or $(ConfigurationName) there. For the FILE command, however, this won't work. More importantly though, the file globbing approach isn't going to work for the first time you build your project if those DLL's are built as part of the same project, since none of the DLL's would be there when you first run CMake in such an arrangement.
You may want to look into BundleUtilities as a more robust way to solve your problem. Despite its name, it supports all platforms, not just Mac. You would need to invoke the fixup_bundle command as a post-build or install step to achieve what you describe. There are a few variations of this approach already described online (e.g. here and here).
You can also have a look at the source for the DeployQt4.cmake file which should be included in the Modules subdirectory of your CMake installation for ideas.
Lets suppose you have _TARGET_NAME filled with your your project name, and ADDITIONAL_DLL_PATH with a list of folders containing external dlls, Then the following code will copy any external dependencies found using dumpbin on windows.
foreach(CONF_TYPE ${CMAKE_CONFIGURATION_TYPES})
string(TOUPPER ${CONF_TYPE} CONF_TYPE_U)
get_property(TARGET_LOCATION_${CONF_TYPE_U} TARGET ${_TARGET_NAME} PROPERTY LOCATION_${CONF_TYPE_U})
get_filename_component(TARGE_DIR ${TARGET_LOCATION_${CONF_TYPE_U}} PATH)
install(CODE "
if (\"\${BUILD_TYPE}\" STREQUAL \"${CONF_TYPE}\")
include(BundleUtilities)
fixup_bundle(\"${TARGET_LOCATION_${CONF_TYPE_U}}\" \"\" \"${ADDITIONAL_DLL_PATH}\")
endif()"
COMPONENT Runtime)
endforeach()
There are downsides to this solution though, Like the need to build INSTALL target whenever you need to copy those files (which might not be many times), and not detecting delay loaded dlls.

How to deploy QWindowsIntegrationPlugin with CMake

I'm using CMake to build a Qt application. My project compiles, and thanks to 'fixup_bundle()', make install copies the required libraries next to my executable. Great!
Only problem is, when I execute it, I get the dreaded 'This application failed to start because it could not find or load the Qt platform plugin "windows".' error.
Indeed, manually copying qwindows.dll into a 'platforms' directory next to the executable fixes the issue. Now, how can I tell CMake to do that automatically?
Not much info from Qt :
Plugins are also available as IMPORTED targets in CMake. The Qt Network, Qt SQL, Qt GUI, and Qt Widgets modules have plugins associated. They provide a list of plugins in the Qt5_PLUGINS variable.
All right, I guess I have to play with Qt5::QWindowsIntegrationPlugin, which should be an imported target. That's where I'm lost.
I know (well, I think I know at least) that fixup_bundle() looks into the executable to find its dependencies. But despite the fact that I link my executable against QWindowsIntegrationPlugin, there is no trace of it. Therefore, no qwindows.dll copied into my output path by fixup_bundle().
Except the manual copy of the file, I couldn't find a nice CMake-friendly answer to this issue.
Thanks for your help.
Just ran into the same issue. Here is how I resolved it in my CMake install script:
# QWindowsIntegrationPlugin is part of the Gui component
find_package(Qt5 COMPONENTS Gui REQUIRED)
install(
FILES "$<TARGET_FILE:Qt5::QWindowsIntegrationPlugin>"
DESTINATION bin/platforms
)

How can I use CMake to both build wxwidgets on-demand and link with it

I have the following situation:
I'm working on an application that depends on a number of third party libs, among them wxwidgets
I build the application for multiple target configurations (x86, arm, Linux, Windows) using Linux as my build host system
Due to the above mentioned multiple target configurations, I have chosen to build those third-party libs from source, using CMake's ExternalProject_Add function.
The third-party libs are built 'on-demand' at a location separate from my application's CMAKE_BINARY_DIR so that I can wipe the build tree for my application without having to rebuild the third-party libs (takes a looooong time).
The location of the third-party libs is different depending on what target configuration I build them for (obviously).
I'm quite new to CMake and the problem I currently face is this:
The source files in my application can't find the wx include files and I need to set the correct linker flags to be able to link my application against wxwidgets.
This seems to be handled by a utility 'wx-config' that provides exactly that info as output when run with either the --cppflags or --libs flag. I can not however, figure out how to catch that output and append it to the include dirs and linked libraries I setup from my CMakeLists.txt files.
So basically what I want is.
Build wxwidgets (if it doesn't exist) for the current target configuration
Run wx-config --cppflags and --libs to find out the correct include dirs and linker flags for the current target configuration
Use the info from step 2 when building targets that are my own application
So far I've tried something like this:
# Set a target-configuration-specific location
set(wxwidgetsTop ${MYPROJECT_EXTERNAL_DIR}/wxwidgets/wxwidgets_${MYPROJECT_CURRENT_TARGET_CFG})
# Build the project
ExternalProject_Add( wxWidgetsExternal
PREFIX ${wxwidgetsTop}
URL ${MYPROJECT_EXTERNAL_DIR}/tarballs/wxWidgets-3.0.2.tar.bz2
SOURCE_DIR ${wxwidgetsTop}/src/wxwidgets
CONFIGURE_COMMAND ${configure_cmdline}
BUILD_COMMAND make -j${MYPROJECT_NCPU}
INSTALL_COMMAND make install
)
# Create a wxwidgets target to be used as a dependency from other code
add_library(wxWidgets IMPORTED STATIC GLOBAL)
add_dependencies(wxWidgets wxWidgetsExternal)
# (non-working) attempt to get the correct include dirs and linker
# flags for wxwidgets
add_custom_command(TARGET wxWidgetsExternal
POST_BUILD
COMMAND ${INSTALL_DIR}/bin/wx-config ARGS --cppflags
COMMENT "Running wx-config"
)
but the above does not provide a way to actually use the result from the custom command to append the cppflags and linker options when building the targets that make up my application.
What is a good way to achieve what I want?
I see three different ways of doing this:
Method 1: use find_package
Use wxWidgets as a standalone requirement for your project, and expect the devs to install it before building your project. In your CMakeLists.txt you will need to call find_package(wxWidgets), like this:
find_package(wxWidgets COMPONENTS net gl core base)
if(wxWidgets_FOUND)
include(${wxWidgets_USE_FILE})
# and for each of your dependent executable/library targets:
target_link_libraries(<YourTarget> ${wxWidgets_LIBRARIES})
endif()
This has the advantage of not rebuilding the lib if you rebuild your project, however it requires some work for your user (they need to handle the installation of wxWidgets by hand) and for you (you need to setup include paths / compile definitions / ... by hand).
Method 2: embed wxWidgets
The second option is to bundle wxWidgets in your repo (svn external or git submodule) and usually (re)write the CMakeLists.txt of this lib to be target-oriented. Then, in your top-most CMakeLists.txt, you can do the following:
# for example, if you just need core and net:
target_link_librairies(my_app PUBLIC wxWidgetsCore wxWidgetsNet)
# No need to manually setup include dirs, etc...
To make a CMakeLists.txt target-oriented, you define include directories and other compilation properties for a target, not a directory. Example:
# When defining wxWidgetsCore, for example
add_library(wxWidgetsCore ...)
target_include_directories(wxWidgetsCore PUBLIC someDir)
target_compile_definitions(wxWidgetsCore PUBLIC -pedantic)
target_link_libraries(wxWidgetsCore PUBLIC someLib)
The drawback of this approach is that rebuilding your project will trigger a rebuild of wxWidgets. However, it is possible to trick this by not using "rebuild" but "clean just my app, then build". Here is some insight on how to achieve this.
Method 3: some sort of hybrid
The big drawback of method 2 leads to the third approach: don't put wxWidgets in your project, but create a CMakeLists.txt that will "import" the lib. The idea: you ask your user for the directory where wxWidgets is installed, then this script will setup everything for your project. First, put the CMakeLists.txt here:
/your-project-root
/thirdparty
/wxWidgets
CMakeLists.txt
/dir-where-wxwidgets-is-installed
...
Now, you define an imported target:
# When defining wxWidgetsCore, for example
set(WX_INCLUDE_DIR ${USER_SPECIFIED_WX_ROOT}/include)
add_library(wxWidgetsCore IMPORTED GLOBAL)
set_property(TARGET wxWidgetsCore APPEND PROPERTY
INTERFACE_INCLUDE_DIRECTORIES ${WX_INCLUDE_DIR})
See INTERFACE_INCLUDE_DIRECTORIES and INTERFACE_LINK_LIBRARIES. You need your user to have build wxWidgets somewhere in his system, but from your point of view you just do target_link_libraries(your_app PUBLIC wxWidgets...), as in method 2. The advantage is that this approach is interchangeable with method 2 transparently, and you don't put the whole dependency in your project.
Setting cppflags and linker flags has to be done at CMake time, but you are trying to run wx-config at build time and you are not capturing its output anyway, so your add_custom_command() isn't doing anything useful other than printing things to the build tool's output.
Ideally, you would use the FindwxWidgets module CMake already provides. It requires wxWidgets to already be built (but see further below). Have a look at the CMake documentation for it and see if that at least sounds like what you are trying to achieve manually by using wx-config. If you can get FindwxWidgets to do the job for you, that would be a much cleaner approach.
Getting something to build at configure time so you can use it later on in your CMakeLists.txt file is a bit more tricky. ExternalProject_Add() downloads and builds things at build time, but you need wxWidgets to be built earlier at configure time. I wrote an article recently for how to do at least the downloading part at configure time and you should be able to adapt it to do the whole build at configure time instead. The article uses Google Test as its example and can be found here:
https://crascit.com/2015/07/25/cmake-gtest/
It would be trivial to make it put the wxWidgets build wherever you like, not just in the CMAKE_BINARY_DIR area. That would allow you to have different wxWidgets builds for each build configuration and to be able to wipe out your application's build tree independently of the wxWidgets builds.
Hope that points you in the right direction.
The solution I use checks for wxWidgets installation in the system using find_package, if it's not found, then the script downloads wxWidgets from github and links the program against downloaded library. The lib is installed in the build directory, so only the first build is slow - subsequent builds do not even check wxWidgets sources timestamps, so the process is as fast as building using preinstalled wxWidgets library.
Here's how my script does it:
It quietly checks for wxWidgets installation using find_package(wxWidgets QUIET),
If it's found, the script adds a dummy library wxWidgets_external,
If it's not, then it creates an ExternalProject named wxWidgets_external which downloads, builds and installs the library in the build dir, setting wxWidgets_ROOT_DIR to point to the wxWidgets installation dir,
Then we add another ExternalProject pointing to a folder with the main program's source files and CMakeLists.txt build script. This external projects depends on wxWidgets_external which is either a dummy library in case wxWidgets is preinstalled in the system, or an external project set up to download the library from github,
In the aforementioned CMakeLists.txt we again call find_package, this time with REQUIRED parameter and use the library the standard way (https://docs.wxwidgets.org/trunk/overview_cmake.html). Because we set up the dependencies and variables correctly, this call will use either preinstalled wxWidgets (if it's available) or the one downloaded from github.
There are more quirks to it, but that's the gist of it. The full sample code (tested on Linux, Windows and Mac) is available on github (https://github.com/lszl84/wx_cmake_template).
Also see full blog post which explains this in more detail: https://justdevtutorials.medium.com/wxwidgets-cmake-multiplatform-superbuild-4ea86c4e6eda

SVG icons not showing up in Qt4 release build in windows

I have a Qt4 application with SVG icons, compiled with mingw (in windows), linked to Qt shared libraries.
When application is run, SVG icons show up in debug and release builds in linux, however in windows SVG icons show up only in debug build but not in release build.
All SVG icons are listed in project.qrc, and project.pro has RESOURCES = project.qrc. Application uses QtSvg4.dll (version 4.7.0).
Qt 4.7.0, Qt Creator 2.0.1, mingw/g++ 4.4.0.
Solution update: In application directory, create /imageformats/ directory and put qsvg4.dll there instead of application directory itself, or create a qt.conf file with appropriate path. More information in deploying plugins.
Most likely you will have to include the plugins from your qt dir. This involves making a qt.conf file that is local to your app (see here: http://doc.qt.io/qt-4.8/qt-conf.html , more specifically the [Paths] section), and copy c:\Qt\4.x.x\plugins\imageformats*.dll to your distributable's directory.
for Qt 5.14
add a line to the .pro file
QT += svg
For Qt5
Since Qt5 the framework has been heavily modularized (List of Modules).
Most likely you are missing the svg module. The application will still compile without complaining. Make sure the SVG module is installed on your system and linked (with qmake (Howto), cmake (Howto) or plain make). If it was linked successfully QImageReader::supportedImageFormats() will list SVG.
For my (Qt 4.6.3) application, I solved this by putting the plug-in dll (qsvgicon4.dll) in a directory called iconengines within the application directory.
Tried other solutions - such as deploying plugin to directory (within app directory) named imageformats with and without an appropriate qt.conf, but no joy.
Note: I previously ran the application with Qt 4.7.0 dlls and had no problems on the same Win7 target machine.
You guessed it: here's yet another way to avoid reading the docs, but instead to rely on cheap advice from the internet.
Just add this line to your app.pro!
QTPLUGINS += qsvg
In my case, Qt is static linked from MSYS2, so plugin DLLs don't even exist. But the app still has to link in that imageformats/qsvg plugin code. The qmake line above is about the easiest way to do it; it translates to the g++ link line segment like this:
g++ [...] -LC:/msys64/mingw64/qt5-static/share/qt5/plugins/imageformats \
C:/msys64/mingw64/qt5-static/share/qt5/plugins/imageformats/libqsvg.a [...]
Based on what you've said, you're doing all that's needed for it to work, so a proper answer is likely to require some more information. See if these links are of any use to you:
http://lists.trolltech.com/qt-interest/2008-10/msg00655.html
http://www.qtcentre.org/archive/index.php/t-9036.html
In particular, make sure that the SVG plugin is getting loaded with:
QImageReader::supportedImageFromats()
It still seem to be a problem with Qt5.1 in Windows, here how I solved it for cmake users:
Find_File(qtsvg NAMES "Qt5Svg.dll" PATHS ${QTBinBase}/.. PATH_SUFFIXES "bin" )
Find_File(qtxml NAMES Qt5Xml.dll PATHS ${QTBinBase}/.. PATH_SUFFIXES "bin" )
Find_File(qsvg NAMES "qsvg.dll" PATHS ${QTBinBase}/.. PATH_SUFFIXES "plugins/imageformats" )
Find_File(qsvgicon NAMES "qsvgicon.dll" PATHS ${QTBinBase}/.. PATH_SUFFIXES "plugins/iconengines" )
install(FILES ${qtsvg} ${qtxml} DESTINATION bin)
install(FILES ${qsvg} DESTINATION bin/plugins/imageformats)
install(FILES ${qsvgicon} DESTINATION bin/plugins/iconengines)
Its the manual way, not beautiful but works. QTBinBase I got with another dirty trick:
get_target_property(QtCore_location Qt5::Core LOCATION)
get_filename_component(QtBinBase ${QtCore_location} PATH)
If adding the Qt4Svg.dll and the imageformats/qsvg4.dll doesn't work, make sure the Qt4Xml.dll is also included along the standard core, gui and svg DLLs.
This is how I solved this for me.
Short: to render svg images you need to include the xml DLL aswell