QML Svg in qt 5.15 static build, using CMake - qt

I would like to migrate from 5.9 to 5.15 and I don't get to load svg from QML.
The original version, using qt provided by Ubuntu (5.9) did load svg from QML with
no extra steps. The new build uses a static Qt.
I use:
Ubuntu 18
In the house static build of Qt 5.15
CMake (3.18)
build Qt
./configure \
-confirm-license \
-release \
-static \
-no-pch \
-nomake tests \
-nomake examples \
-nomake tools \
-nomake examples \
-nomake tests \
-skip qtdoc \
-skip wayland \
-skip qtwebengine \
--prefix=/opt/Qt-5.15.0
CMake
cmake_minimum_required(VERSION 3.18)
project(test VERSION 0.0.0 LANGUAGES CXX)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
find_package(Qt5 5.15
PATHS /opt/Qt-5.15.0
COMPONENTS
Core
Widgets
Qml
Svg
Quick
QuickControls2
Charts
Multimedia
LinguistTools
QmlImportScanner
Xml
REQUIRED QUIET
)
add_executable(test_qt
# c++ code files
main.cpp
# qml code files
qml/Main.qml
# resource files
qml/resources.qrc
)
target_include_directories(test_qt PRIVATE ${CMAKE_CURRENT_LIST_DIR})
target_link_libraries(test_qt
PRIVATE
Qt5::Widgets
Qt5::Qml
Qt5::Quick
Qt5::QuickControls2
Qt5::Svg
Qt5::Xml
Qt5::Gui
)
qt_import_qml_plugins(test_qt
INCLUDE
Qt5::QtQuick2Plugin
Qt5::QSvgPlugin
Qt5::QtQuickControls2Plugin
)
main.cpp
#include <QGuiApplication>
#include <QObject>
#include <QQmlApplicationEngine>
#include <QQmlComponent>
#include <QQmlContext>
int main(int argc, char *argv[]) {
int status = 0;
try {
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl("qrc:/Main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::quit, &QGuiApplication::quit);
if (engine.rootObjects().isEmpty())
return -1;
status = app.exec();
} catch (std::exception &) {
return -1;
}
return status;
}
Main.qml
import QtQuick 2.15
import QtQuick.Controls 2.15
ApplicationWindow {
id: window
width: 850
height: 850
visible: true
color: "lightgray"
Image{
source: "image.svg"
}
}
I omit the resource file, but it lists qml, png and svg files.
When using PNG image is loaded successfully, but when using SVG the following error appears:
qrc:/Main.qml:13:5: QML Image: Error decoding: qrc:/image.svg: Unsupported image format
The current Qt build contains the following files related to SVG handling:
./lib/libQt5Svg.a
./lib/libQt5Svg.la
./lib/cmake/Qt5Svg
./lib/cmake/Qt5Svg/Qt5SvgConfigVersion.cmake
./lib/cmake/Qt5Svg/Qt5SvgConfig.cmake
./lib/cmake/Qt5Gui/Qt5Gui_QSvgIconPlugin.cmake
./lib/cmake/Qt5Gui/Qt5Gui_QSvgPlugin_Import.cpp
./lib/cmake/Qt5Gui/Qt5Gui_QSvgIconPlugin_Import.cpp
./lib/cmake/Qt5Gui/Qt5Gui_QSvgPlugin.cmake
./lib/pkgconfig/Qt5Svg.pc
./lib/libQt5Svg.prl
./include/QtSvg
./include/QtSvg/QGraphicsSvgItem
./include/QtSvg/5.15.0/QtSvg
./include/QtSvg/QSvgRenderer
./include/QtSvg/QSvgWidget
./include/QtSvg/QSvgGenerator
./include/QtSvg/QtSvg
./include/QtSvg/QtSvgVersion
./include/QtSvg/QtSvgDepends
EDIT
I added the missing Svg library dependency to the find_package command. The issue remains unsolved.
If I link against a shared build of the Qt libraries, this project works correctly.

The solution for me was in addition to including Qt5::Svg in find_package and target_link_libraries, eg:
find_package(Qt5 REQUIRED COMPONENTS Core Quick Qml Xml Charts Gui Svg QuickControls2)
target_link_libraries(${PROJECT_NAME} PRIVATE Qt5::Core Qt5::Quick Qt5::Qml Qt5::Xml Qt5::Charts Qt5::Gui Qt5::Svg Qt5::QuickControls2)
To also include the following when statically linking Qt 5.15:
qt5_import_plugins(${PROJECT_NAME} INCLUDE Qt5::QSvgPlugin)
That resolved errors such as "QML ButtonIcon: Error decoding: qrc:/resources/images/add-white-36dp.svg: Unsupported image format"

You are using cmake, but in a qmake .pro project,using static linking, you
must add
QT += svg
Note that svg plugin depends of widgets:
"QT += svg" is the same that "QT += svg widgets"
In android/IOS is better skip svg images to reduce app size.
/opt/Qt/5.15.1/gcc_64/lib$ ldd libQt5Svg.so
linux-vdso.so.1 (0x00007fff7bff0000)
libQt5Widgets.so.5 => /opt/Qt/5.15.1/gcc_64/lib/./libQt5Widgets.so.5 (0x00007ff0cbf55000)
libQt5Gui.so.5 => /opt/Qt/5.15.1/gcc_64/lib/./libQt5Gui.so.5 (0x00007ff0cb624000)
You can try to add some C++ QTSVG code in your main.cpp ,to test linking
https://doc.qt.io/qt-5/qsvggenerator.html

Related

Qt and OpenCv CrossCompile for Raspberry Pi Error

I'm trying to use opencv in a QT project for a raspberry pi 4. I'm on a Linux machine
Here is my .pro file and errors I get. And my mainwindow.cpp
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++17
# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp \
mainwindow.cpp
HEADERS += \
mainwindow.h
FORMS += \
mainwindow.ui
TRANSLATIONS += \
SCWWS_fr_FR.ts
CONFIG += lrelease
CONFIG += embed_translations
# Default rules for deployment.
qnx: target.pHere is my mainwindow.cppath = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
RESOURCES += \
resources.qrc
unix:!macx: LIBS += -L$$PWD/../../Documents/Qt-CrossCompile-RaspberryPi/raspberrypi4/sysroot/usr/lib/arm-linux-gnueabihf -lopencv_core -lopencv_highgui -lopencv_imgproc -lopencv_imgcodecs -lopencv_shape -lopencv_videoio
INCLUDEPATH += $$PWD/../../Documents/Qt-CrossCompile-RaspberryPi/raspberrypi4/sysroot/usr/include
DEPENDPATH += $$PWD/../../Documents/Qt-CrossCompile-RaspberryPi/raspberrypi4/sysroot/usr/include
Here is my mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QtCore>
#include <QFontDatabase>
#include <QDebug>
#include <QImage>
//#include "opencv2/core.hpp"
//#include "opencv2/highgui.hpp"
//using namespace cv;
mainwindow::mainwindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::mainwindow)
{
QFontDatabase::addApplicationFont(":/fonts/roboto-light.ttf");
ui->setupUi(this);
qDebug() << "Hello World !";
//cv::VideoCapture camera = VideoCapture(0);
//
//Mat frame;
//camera >> frame;
//QImage img(frame.data, frame.cols, frame.rows, frame.step, QImage::Format_RGB888);
//ui->label->setPixmap(QPixmap::fromImage(img));
}
mainwindow::~mainwindow()
{
delete ui;
}
And here are errors I get
libXinerama.so.1, needed by /home/lolix/Documents/Qt-CrossCompile-RaspberryPi/raspberrypi4/sysroot/usr/lib/arm-linux-gnueabihf/libgdk-3.so.0, not found (try using -rpath or -rpath-link)
libmmal_core.so, needed by /home/lolix/Documents/Qt-CrossCompile-RaspberryPi/raspberrypi4/sysroot/usr/lib/arm-linux-gnueabihf/libavcodec.so.58, not found (try using -rpath or -rpath-link)
libmmal_vc_client.so, needed by /home/lolix/Documents/Qt-CrossCompile-RaspberryPi/raspberrypi4/sysroot/usr/lib/arm-linux-gnueabihf/libavcodec.so.58, not found (try using -rpath or -rpath-link)
.
.
.
liblapack.so.3, needed by /home/lolix/Documents/Qt-CrossCompile-RaspberryPi/raspberrypi4/sysroot/lib/libarmadillo.so.9, not found (try using -rpath or -rpath-link)
/home/lolix/Documents/Qt-CrossCompile-RaspberryPi/raspberrypi4/sysroot/usr/lib/arm-linux-gnueabihf/libopenmpt.so.0:-1: error: undefined reference to `std::random_device::_M_getentropy() const#GLIBCXX_3.4.25'
Errors arrives has soon has I uncomment my code. The version of open cv on the RP4 is 3.2 and when I install it on my machine it's 4.5. Event if I use the same command sudo apt-get install libopencv-dev
Thanks for your help
**EDIT**
I was able to get rid of these errors with this response. But a new one appeared
undefined reference to std::random_device::_M_getentropy() const#GLIBCXX_3.4.25
Regarding OpenCV I suggest to build it from source, for the RPi I always cross-compile using docker, as described here (just remove the references to openvino).
At this point you also need to cross-compile Qt for the RPi, but I guess you already did it.

CMake shows console

I made an app and when I run in QtCreator everything goes well, my question is when I generate the release, a consola is shown along with my app, why does this happen, and how can I avoid it.
Here my code.
#include "mainwindow.h"
#include "./ui_mainwindow.h"
#include <QMessageBox>
#include <QSqlDatabase>
#include <QSqlError>
#include <QSqlTableModel>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent), ui(new Ui::MainWindow)
{
ui->setupUi(this);
QSqlDatabase db=QSqlDatabase::addDatabase("QPSQL");
if(!db.isDriverAvailable("QPSQL")){
QMessageBox::critical(this,qApp->applicationName(),db.lastError().text());
return;
}
db.setDatabaseName("covid");
db.setHostName("localhost");
db.setPassword("2311046");
db.setPort(5432);
db.setUserName("postgres");
if(!db.open()){
QMessageBox::critical(this,qApp->applicationName(),db.lastError().text());
return;
}
QMessageBox::information(this,qApp->applicationName(),"Todo bien");
}
MainWindow::~MainWindow()
{
delete ui;
}
CMakeLists.txt:
cmake_minimum_required(VERSION 3.5)
project(untitled1 LANGUAGES CXX)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# QtCreator supports the following variables for Android, which are identical to qmake Android variables.
# Check http://doc.qt.io/qt-5/deployment-android.html for more information.
# They need to be set before the find_package(Qt5 ...) call.
#if(ANDROID)
# set(ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android")
# if (ANDROID_ABI STREQUAL "armeabi-v7a")
# set(ANDROID_EXTRA_LIBS
# ${CMAKE_CURRENT_SOURCE_DIR}/path/to/libcrypto.so
# ${CMAKE_CURRENT_SOURCE_DIR}/path/to/libssl.so)
# endif()
#endif()
find_package(QT NAMES Qt6 Qt5 COMPONENTS Widgets REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Widgets REQUIRED)
find_package(Qt5 COMPONENTS Sql REQUIRED)
if(ANDROID)
add_library(untitled1 SHARED
main.cpp
mainwindow.cpp
mainwindow.h
mainwindow.ui
)
else()
add_executable(untitled1
main.cpp
mainwindow.cpp
mainwindow.h
mainwindow.ui
)
endif()
target_link_libraries(untitled1 PRIVATE Qt${QT_VERSION_MAJOR}::Widgets)
target_link_libraries(untitled1 PUBLIC Qt${QT_VERSION_MAJOR}::Sql)
Here I show the Windows that are shown every time I run the .exe:
This should be quite simple. Just add:
# ...
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Make sure we build executables as GUI apps, rather than console apps, on Windows
set(CMAKE_WIN32_EXECUTABLE TRUE)
# ...
As the documentation explains:
When [WIN32_EXECUTABLE] is set to true the executable when linked on Windows will be created with a WinMain() entry point instead of just main(). This makes it a GUI executable instead of a console application. [...] This property is initialized by the value of the CMAKE_WIN32_EXECUTABLE variable if it is set when a target is created.

Qt Plugin Loading fails (specified module could not be found)

For some reason I am unable to load my plugins anymore, although it has worked previously. I have a plugin loader code in my MainWindow, which is supposed to load every .dll found in a specific folder. The MainWindow Code contains the following:
Interface
#ifndef PLUGININTERFACE_H
#define PLUGININTERFACE_H
#include <QtPlugin>
// forward declarations
class MainWindow;
struct P3DData;
class PluginInterface
{
public:
virtual bool createPublisher(MainWindow*, P3DData*) = 0;
};
#define PLUGIN_INTERFACE_iid "PluginInterface"
Q_DECLARE_INTERFACE(PluginInterface, PLUGIN_INTERFACE_iid)
#endif // PLUGININTERFACE_H
loadPlugins()
bool MainWindow::loadPlugins()
{
QDir pluginsDir(qApp->applicationDirPath());
pluginsDir.cd("plugins");
const auto entryList = pluginsDir.entryList(QDir::Files);
for(const QString &fileName : entryList)
{
QString dllPath = pluginsDir.absoluteFilePath(fileName);
QPluginLoader* loader = new QPluginLoader(dllPath);
loaderList.push_back(loader);
QObject *plugin = loader->instance();
if (plugin)
{
pluginList.push_back(qobject_cast<PluginInterface *>(plugin));
pluginList.last()->createPublisher(this, simDataPtr);
pluginCount++;
continue;
}
else
{
qDebug() << "[PluginLoader] '" + fileName + "': " + loader->errorString();
delete loaderList.takeLast();
}
}
}
Besides my MainWindow, there is another subdir in my project, which is the plugin "Position". The plugin is deployed into the correct "plugins" folder, which the loadPlugin() method from the MainWindow iterates through. The plugin uses following code to implement the interface:
#include <QObject>
#include "MainWindow.h"
class PositionPublisher : public QObject, PluginInterface
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "PluginInterface")
Q_INTERFACES(PluginInterface)
public:
PositionPublisher();
~PositionPublisher();
bool createPublisher(MainWindow* _window, P3DData* _simDataPtr) override;
//...
};
When trying to run loadPlugins() now, it checks the correct Position.dll file but the "if(plugin)" part returns false and loader->errorString() is executed giving the following error:
[PluginLoader] 'Position.dll': Cannot load library
F:\DEV\build\simNET\bin\plugins\Position.dll: Cannot find the
specified module.
I have already checked and tried the following:
the Plugins folder actually contains the Position.dll file
both projects (MainWindow and Plugin) are built in release mode
the dependencies of the plugin (two libs) exist and the specified path in the pro file is correct
.pro file of plugin:
QT += widgets
TEMPLATE = lib
CONFIG += c++11
CONFIG += plugin
CONFIG += release
SOURCES += \
Position.cpp \
PositionPubSubTypes.cpp \
PositionPublisher.cpp
HEADERS += \
Position.h \
PositionPubSubTypes.h \
PositionPublisher.h
DISTFILES += \
Position.idl
INCLUDEPATH += ../../application
TARGET = $$qtLibraryTarget(Position)
DESTDIR = ../../bin/plugins
INCLUDEPATH += "F:/DEV/prog/FastRTPSv1.5/include"
DEPENDPATH += "F:/DEV/prog/FastRTPSv1.5/include"
LIBS += -L"F:/DEV/prog/FastRTPSv1.5/lib/x64Win64VS2015" -lfastrtps-1.5
PRE_TARGETDEPS += F:/DEV/prog/FastRTPSv1.5/lib/x64Win64VS2015/fastrtps-1.5.lib
INCLUDEPATH += 'F:/Programme/Prepar3D v4/SDK/inc/SimConnect'
DEPENDPATH += 'F:/Programme/Prepar3D v4/SDK/inc/SimConnect'
LIBS += -L'F:/Programme/Prepar3D v4/SDK/lib/SimConnect' -lSimConnect
PRE_TARGETDEPS += 'F:/Programme/Prepar3D v4/SDK/lib/SimConnect/SimConnect.lib'
Does anyone have an idea why it does not load the plugin??
Qt plugin loader is trying to tell you that a Qt module used in your plugin doesn't exist so first you need to check which Qt modules your plugin depends on then,
If you're trying to run the application from Qt Creator itself, and it gives you this error, then maybe the DLL file got deleted for some reason or you're trying to use the plugin with a Qt version that doesn't have its needed modules. (for example, Qt6 doesn't contain the QtSerialPort module but Qt5 did (at the time of writing this)).
If you're trying to run the application directly outside Qt Creator then you need to copy the required module's dll file into your applications root directory.

How to create a project to import a UI qml interface into other applications

I have a project that uses a server/client feature. My project layout is:
Project w/ subprojects
-server
--- some files (not important)
-client display
---Display.qml --> Main view
---ViewerForm.ui.qml --> UI Display to create the view
---Viewer.qml --> To run button clicks and javascript
I am able to run the server and client with no problems. Now, I would like to have the Viewer and ViewerForm to be available for different applications. For example:
Standalone client application (just the client display)
Imported into another application which may have several kinds of UI pages in which one is the client display.
How can I set this up so that I have only 1 Viewer project and it can be imported into different applications. Should this be a Qt Plugin? Module? I looked at the Qt documentation and I created a ViewerPlugin project as it's own project with the ViewerForm.ui.qml, Viewer.qml, several component *.ui.qml and *.qml files, and javascript files as shown below. When I build the ViewerPlugin it creates a Viewer folder with files: ViewerPlugin.dll, ViewerPlugin.exp, ViewerPlugin.lib, and qmldir. Then, I copy this folder into my client application and import the QML plugin in my Display.qml like import Viewer 1.0. But I get build errors that it can't find: CListView.qml and the other qml files.
viewerplugin.pro
TEMPLATE = lib
TARGET = ViewerPlugin
QT += qml quick
CONFIG += qt plugin c++11
DESTDIR = ../../imports/Viewer
TARGET = $$qtLibraryTarget($$TARGET)
uri = Viewer
# Input
SOURCES += \
viewerplugin_plugin.cpp \
viewer.cpp
HEADERS += \
viewerplugin_plugin.h \
viewer.h
DISTFILES += qmldir \
Viewer.qml \
ViewerForm.ui.qml \
components/CListView.qml \
components/CListViewForm.ui.qml \
components/CRangeSliderForm.ui.qml \
components/CSliderForm.ui.qml \
components/IconButtonForm.ui.qml \
components/PressAndHoldButton.qml \
components/TextButton.qml
RESOURCES += qml.qrc
!equals(_PRO_FILE_PWD_, $$OUT_PWD) {
copy_qmldir.target = $$OUT_PWD/qmldir
copy_qmldir.depends = $$_PRO_FILE_PWD_/qmldir
copy_qmldir.commands = $(COPY_FILE) "$$replace(copy_qmldir.depends, /, $$QMAKE_DIR_SEP)" "$$replace(copy_qmldir.target, /, $$QMAKE_DIR_SEP)"
QMAKE_EXTRA_TARGETS += copy_qmldir
PRE_TARGETDEPS += $$copy_qmldir.target
}
qmldir.files = qmldir
# Copy the qmldir file to the same folder as the plugin binary
cpqmldir.files = qmldir
cpqmldir.path = $$DESTDIR
COPIES += cpqmldir
qml.qrc
<RCC>
<qresource prefix="/">
<file alias="ViewerForm.ui.qml">ViewerForm.ui.qml</file>
</qresource>
<qresource prefix="/components">
<file alias="IconButtonForm.ui.qml">components/IconButtonForm.ui.qml</file>
<file alias="CRangeSliderForm.ui.qml">components/CRangeSliderForm.ui.qml</file>
<file alias="CSliderForm.ui.qml">components/CSliderForm.ui.qml</file>
<file alias="CListView.qml">components/CListView.qml</file>
<file alias="TextButton.qml">components/TextButton.qml</file>
</qresource>
<qresource prefix="/HTML5">
<file alias="index.html">HTML5/index.html</file>
<file alias="loader.css">HTML5/loader.css</file>
</qresource>
<qresource prefix="/resources">
<file alias="fontawesome-webfont.ttf">resources/fontawesome-webfont.ttf</file>
</qresource>
</RCC>
qmldir
module Viewer
CListView 1.0 CListView.qml
CListViewForm 1.0 CListViewForm.ui.qml
CRangeSliderForm 1.0 CRangeSliderForm.ui.qml
CSliderForm 1.0 CSliderForm.ui.qml
IconButtonForm 1.0 IconButtonForm.ui.qml
PressAndHoldButton 1.0 PressAndHoldButton.qml
TextButton 1.0 TextButton.qml
plugin ViewerPlugin
The components and HTML5 folders exist as described in the .pro file. The viewerplugin_plugin.h/cpp and viewer.h/cpp are the basic files created from the Qt5 wizard for QT Extensions to extend QQmlExtensionPlugin.
Below are the files that try to import the ViewerPlugin:
Client.pro
QT += quick qml serialport core webengine webchannel
CONFIG += c++11 qt
CONFIG += qtquickcompiler
RESOURCES += qml.qrc
!include($${top_srcdir}/common/common.pri) {
error("Couldn't find common.pri file")
}
!include($${top_srcdir}/qmake-target-platform.pri) {
error("Couldn't find qmake-target-platform.pri file")
}
!include($${top_srcdir}/qmake-destination-path.pri) {
error("Couldn't find qmake-destination-path.pri file")
}
SOURCES += \
main.cpp
DESTDIR = $${top_srcdir}/binaries/$$DESTINATION_PATH
OBJECTS_DIR = $${top_srcdir}/build/$$DESTINATION_PATH/.obj
MOC_DIR = $${top_srcdir}/build/$$DESTINATION_PATH/.moc
RCC_DIR = $${top_srcdir}/build/$$DESTINATION_PATH/.qrc
UI_DIR = $${top_srcdir}/build/$$DESTINATION_PATH/.ui
# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Refer to the documentation for the
# deprecated API to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
DISTFILES += \
Display.qml
# ViewerPlugin needs to be copied to binaries executable directory
CONFIG += file_copies
COPIES += ViewerPlugin
ViewerPlugin.files = $$files($${Viewer}/*)
ViewerPlugin.path = $${DESTDIR}/Viewer
# Additional import path used to resolve QML modules in Qt Creator's code model
QML_IMPORT_PATH = ${top_srcdir}
# Additional import path used to resolve QML modules just for Qt Quick Designer
QML_DESIGNER_IMPORT_PATH =
qml.qrc
<RCC>
<qresource prefix="/">
<file alias="Display.qml">Display.qml</file>
</qresource>
</RCC>
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QtWebEngine>
#include <QObject>
#include <QMetaObject>
int main(int argc, char *argv[])
{
qputenv("QT_IM_MODULE", QByteArray("qtvirtualkeyboard"));
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QtWebEngine::initialize();
QQmlApplicationEngine engine;
const QUrl url(QStringLiteral("qrc:/Display.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(url);
return app.exec();
}
Display.qml
import Viewer 1.0
ApplicationWindow {
id: window
visibility: "Maximized"
visible: true
ViewerForm {
id: viewer
}
Looks like all I needed to do was update the qmldir file to add: Viewer 1.0 qrc:/Viewer.qml and it works.

incompatible qt library between app and plugin compiled same way

After compiling a Qt application and a Qt plugin with the same flags (except -shared added for compiling the .dll) there is an error message at execution:
"The plugin 'Z:/bug_pyqt/plugin.dll' uses incompatible Qt library. Expected build key "Windows mingw release full-config", got "Windows mingw debug full-config""
Why this error message if both the main application and the plugin were compiled with the same flags?
They were compiled with mingw32-g++ on windows XP under cygwin with a hand-made makefile.
Compiling the main application with option "-g" (and plugin still without) makes things "work" and the error message disappear but what is the rationale?
File main.cpp to compile into a.out:
#include <QCoreApplication>
#include <QPluginLoader>
#include <QDebug>
int main(int argc, char **argv)
{
QCoreApplication app(argc, argv);
QPluginLoader loader("plugin.dll");
loader.setLoadHints(QLibrary::ResolveAllSymbolsHint | QLibrary::ExportExternalSymbolsHint);
loader.load();
if(!loader.isLoaded()) {
qDebug() << loader.errorString();
exit(1);
}
(void)loader.instance();
return app.exec();
}
File plugin.h:
#ifndef PLUGIN_H
#define PLUGIN_H
#include <QObject>
class Plugin : public QObject
{
Q_OBJECT
public:
Plugin();
~Plugin();
};
#endif
File plugin.cpp to compile into plugin.dll:
#include "plugin.h"
#include <QtPlugin>
Q_EXPORT_PLUGIN2(Plugin, Plugin)
Plugin::Plugin() { }
Plugin::~Plugin() { }
File Makefile:
MOC=/cygdrive/c/Qt/4.8.4/bin/moc
GCC=/cygdrive/c/MinGW/bin/mingw32-g++.exe
FLAGS=-Ic:/Qt/4.8.4/include -Ic:/Qt/4.8.4/include/QtCore -Lc:/Qt/4.8.4/lib -Lc:/Qt/4.8.4/bin -lQtCore4
LIBFLAGS=-shared
all:
$(MOC) plugin.h > plugin_moc.cpp
$(GCC) -o a.out main.cpp $(FLAGS)
$(GCC) -o plugin.dll $(LIBFLAGS) plugin_moc.cpp plugin.cpp $(FLAGS)
After investigation, here is a half answer
First off, the "build key" that is mentionned in the error message in defined as macro QT_BUILD_KEY in file QtCore/qconfig.h.
Here is a relevant extract of this file:
#if defined(__SYMBIAN32__)
# define QT_BUILD_KEY "Symbian full-config"
#else
# if !defined(QT_NO_DEBUG)
# if (defined(WIN64) || defined(_WIN64) || defined(__WIN64__))
# define QT_BUILD_KEY "Windows x64 mingw debug full-config"
# else
# define QT_BUILD_KEY "Windows mingw debug full-config"
# endif
# else
# if (defined(WIN64) || defined(_WIN64) || defined(__WIN64__))
# define QT_BUILD_KEY "Windows x64 mingw release full-config"
# else
# define QT_BUILD_KEY "Windows mingw release full-config"
# endif
# endif
#endif
From this we understand that we can force the build type of the plugin to be "release" by defining the macro QT_NO_DEBUG.
Adding "-DQT_NO_DEBUG" on the compile command for the plugin solves the issue.
This still does not explain why by default Qt_BUILD_KEY (or QT_NO_DEBUG) is different between the main app and the plugin.

Resources