SVG icons not showing up in Qt4 release build in windows - c++

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

Related

CMake avoid copying Qt5 Dlls on windows

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

How to apply the libraries and plugins configuration loaded in QLibraryInfo in a QApplication?

Context: I have built a c++ executable using Qt 5.13.1 on an OpenSUSE platform (some Linux distribution).
I have to install it on a platform that already have an old Qt version installed and I can't get rid of it.
So I have installed the proper version of the needed Qt shared libraries (plus the platforms plugins) at a custom location and set up a qt.conf file that will specify the library path to use (same thing for the plugin path).
My own Qt installation folder contains:
A lib/ directory which contains the libraries to use.
A plugins/ directory which contains the platforms/ plugin folder.
The qt.conf file is installed alongside my executable and is filled as follows:
[Paths]
Prefix = relative_path/from/executable_location/to/install_dir/
I don't need to specify the lib/ and plugins/ directories in the entries Libraries and Plugins because they are defaulted at these values.
But even if I set them explicitly, it changes nothing.
I also tried with absolute paths but it changes nothing too.
Issue: The issue I encounter is that my executable does not load the libraries, neither find the platforms plugins, despite the qt.conf file is successfully loaded.
I have displayed the output of the following instructions:
QLibraryInfo::location(QLibraryInfo::PrefixPath);
QLibraryInfo::location(QLibraryInfo::LibrariesPath);
QLibraryInfo::location(QLibraryInfo::PluginsPath);
And they contains what's I specified in my qt.conf file. So the issue does not come from here.
Question: I have checked that QLibraryInfo field members had been properly initialized but it seems that my QApplication instance just ignore it.
How to make the QLibraryInfo configuration to be applied by the QApplication instance ?
I know that there exist a QCoreApplication::addLibraryPath() member than could be used to load libraries but I can't find anything alike for the Qt plugins as well.
But I'm pretty sure that we don't have to use this function since the information are already loaded by QLibraryInfo.
EDIT:
After some more investigations, I've found that it works fine for loading the plugins.
The problem remains the same for loading the libraries. It seems that I missed something but I cannot figure it out.
For now, I use the LD_PRELOAD environment variable in order to make it work (which is quite ugly).
EDIT 2:
I found two threads on internet about guys having the same issue:
https://forum.qt.io/topic/58499/solved-problems-with-setting-paths-to-libs-and-plugins-in-qt-app-s-executable-file
https://www.qtcentre.org/threads/32236-qt-conf-(again)-on-windows
The second one is explaining why the library load does not work.
Actually, in order to be able to parse the qt.conf file, the application needs to have the Core module loaded (libQt5Core.so.5 in my case) which makes sense (I should have thought of it).
The issue here is that libQt5Core.so.5 is one of the libraries to load (it's a vicious circle), so the executable cannot run at all.
Solution (still not load any library): It seems that I can't avoid to either load libQt5Core.so.5 with LD_PRELOAD or add it alongside the executable location.
Note: We can use LD_LIBRARY_PATH instead of LD_PRELOAD if there is no already existing Qt installation in the system "lib" directories.
I use LD_PRELOAD here because I want my Qt installation to take precedence over the already existing one (and be loaded first/instead of the system installed ones).
The problem with your libraries is that the Linux dynamic linker only searches a few standard locations, and other paths configured in /etc/ld.so.conf. One workaround is the environment variable LD_LIBRARY_PATH with the paths of your libraries. Another is the RPATH/RUNPATH values embedded in your binaries. CMake uses RPATH by default, and you can use QMAKE_RPATH in Qmake projects too. You can assemble by hand a directory with programs and libraries related using RPATH, but my advice is to create AppDir / AppImage packages using linuxdeployqt which is very similar to using the official Qt tools windeployqt and macdeployqt.
I have finally found out what was wrong.
qt.conf is parsed by Qt Core at runtime.
But the executable dependencies are loaded before the QApplication even exists. If they are not found, the program will just crash right at the beginning (dependencies loading step). And so, qt.conf will never be parsed.
In my case, I have an already existing installation of Qt in the system libraries folder. These are the ones that are found by the loader.
In this case, the dependencies are found and the programs runs (assuming there's no incompatibility between the two versions).
But even if the qt.conf is now parsed, the good version of the library will still not be loaded because the loader already has loaded the dependencies from the wrong Qt install (found at loading step).
Therefore the morality is: We cannot load executable dependencies by using qt.conf because they must be known before execution time (when the loader is looking for them).
Possible solutions:
Install the libraries in one of the folder searched by the loader (/usr/lib/ for example). If there is an already installed version of the libraries, remove it if possible, or if not, do ensure/check that you placed the proper version in a folder that will be searched first by the loader.
Use LD_LIBRARY_PATH to tell the loader where to search for libraries (if a wrong version is already installed, use LD_PRELOAD instead because LD_LIBRARY_PATH will not take precedence over what's inside /etc/ld.so.conf).
Set a rpath (which locates the proper installation directory of the libraries) when building the executable.
Add the required shared libraries in the executable directory.
(Not tested) Explicitly call the loader at application startup with the --library-path option (for example: "$ /lib/ld-linux.so.2 --library-path my_lib_path executable").
I may have missed other workarounds, this list is not guaranteed to be exhaustive.

How to build custom widgets for qt designer

I've read through the tutorials of Qt, I've searched the net, but I can't find the exact way on how to build custom witgets with Qt 5.8.x. In example with this tutorial one is able to build widgets for Qt 4.x as I already succeeded. For Qt 5.8.x I'am lacking in such straightforward tutorials.
Even if you use the build in wizard of Qt for setting up such custom widgets projects, one will end up with none recognized widget libraries.
So first of all, there is a confusion with the installing path, that the makefile should mention while installing the plugin.
In the project file one can find the section
target.path = $$[QT_INSTALL_PLUGINS]/designer
INSTALLS += target
After a straightforward installation of the open source mingw version of Qt 5.8.0 on a windows 7 machine in the path C:\Qt\Qt5.8.0, the variable "QT_INSTALL_PLUGINS" will extend to
C:\Qt\Qt5.8.0\5.8\mingw53_32\plugins
thus the "target.path" for the
make install
will be read as
C:\Qt\Qt5.8.0\5.8\mingw53_32\plugins\designer
But on the plain installation of Qt 5.8.0 with mingw the designer searches its plugins in
C:\Qt\Qt5.8.0\Tools\QtCreator\bin\plugins\designer\
As someone already suggested to me, one has to set the environment variable "QT_PLUGIN_PATH", where Qt Creator as well as Qt Designer ( in the subdirector "designer") searches its plugins in. So in order that Qt Creator still works properly one has to set the environment variable "QT_PLUGIN_PATH" to
the original path as well as to
the install path reffered to by $$[QT_INSTALL_PLUGINS]
So on my Windows 7 environment I set the variable "QT_PLUGIN_PATH" to
C:\Qt\Qt5.8.0\Tools\QtCreator\bin\plugins;C:\Qt\Qt5.8.0\5.8\mingw53_32\plugins
Afterwards Qt Designer is able to find the custom build widget library. But Qt Designer it not able to load the library. One interesting thing is that the designer also refuses the libraries provided by the installation of Qt itself.
on loading the custom widget lib it says:
"... .dll can't be loaded: the given procedure was not found"
on loading the libs supplied by the Qt distribution itselfs in the path C:\Qt\Qt5.8.0\5.8\mingw53_32\plugins\designer it says:
"... .dll cant be loaded: the mentioned modul was not found"
What I've done to build the library is, that I just ran through the project wizard to generate a custom widget for Qt Designer. With the so generated project I get the result of a non loadable lib, as mentioned above.
What do I have to change in the source/project files in order that the Qt Designer ist able to load the lib properly?
Thanks for any hints or suggestions!
You seem to use the MinGW compiler.
You cannot make plugins with that compiler with the default supplied Creator as it's compiled with Visual Studio 2013/2015 (depending on the Qt version).
Due to how DLLs works on Windows, you must use the same compiler that Creator is compiled with to build the plugin (otherwise it can't load it).
Go to "About Qt Creator" in the Help menu to check.
Also make sure to build the plugin in Release mode.

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 to create simple Boost.Build make file containing links to libs I use on Windows and Linux?

main.cpp which should be executable C++ app. It shall depend on
Lib1 be a required to be compiled first (before main.cpp) project-lib (with lib1.h and lib1.cpp inside some separate folders)
'Lib2.lib' with its dependency given precompiled libs (like cross-platform OpenCV for example)
I need it to work for Windows and Linux and if possible Mac OS
found for windows: look here - "Common tasks" page 26
exe hello : hello.cpp some_library.lib /some_project//library
: <threading>multi
;
I hoped for better - more readable syntax form Boost creators... And BTW
What the hell on earth does
On Windows, if an application uses
shared libraries, and both the
application and the libraries are
built using Boost.Build, it is not
possible to immediately run the
application, because the PATH
environment variable should include
the path to the libraries. It means
you have to either add the paths
manually, or have the build place the
application and the libraries into the
same directory.
mean? I can not have a project with 2 nested project - one for .lib and one for app using that .lib?
With this I see how to connect 1 .lib but how to connect a folder with them? And how to connect includes? And when I'll go to Linux what shall be changed?
How should my bjam make/config file look like?
It sounds like you want a framework which works on a cross-platform(Multiple operating system) scenario.
Simplest option would be to install cygwin and create a standard makefile for linux. Compile in a cygwin environment to generate the windows equivalent.
You will save substantial time in creating the makefile.
Another option is mksnt.