I'm trying to experiment, with CMake and Qt 5.15.1, a tiny project including a dummy custom QML plugin loaded at runtime.
Project structure
|-- CMakeLists.txt
|-- main.cpp
|-- main.qml
|-- main.qrc
|-- qmlplugins/
|-- customqml/
|-- CMakeLists.txt
|-- customqml_plugin.cpp
|-- customqml_plugin.h
|-- customqml.cpp
|-- customqml.h
|-- qmldir
./CMakeLists.txt
cmake_minimum_required(VERSION 3.1)
project(test_qml_plugin LANGUAGES C CXX)
set(CMAKE_CXX_STANDARD 11)
set(CXX_STANDARD_REQUIRED ON)
find_package(Qt5 REQUIRED Gui Core Qml Quick)
add_subdirectory(qmlplugins/customqml)
add_executable(${PROJECT_NAME} main.cpp main.qrc)
target_link_libraries(${PROJECT_NAME} PRIVATE Qt5::Quick Qt5::Gui Qt5::Qml Qt5::Core)
add_dependencies(${PROJECT_NAME} customqml)
set_target_properties(${PROJECT_NAME} PROPERTIES AUTORCC ON)
./main.cpp
#include <QCoreApplication>
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QUrl>
#include <QDir>
int main(int argc, char **argv) {
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.addImportPath(QCoreApplication::applicationDirPath() + QDir::separator() + "qmlplugins");
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty()) return -1;
return app.exec();
}
./main.qml
import QtQuick 2.5
import QtQuick.Window 2.2
import QtQuick.Controls 1.5
import customqml 1.0
ApplicationWindow {
id: root
title: qsTr("test_qml_plugin")
width: 640
height: 480
visible: true
CustomQml {}
}
./main.qrc
<RCC>
<qresource prefix="/">
<file>main.qml</file>
</qresource>
</RCC>
./qmlplugins/customqml/CMakeLists.txt
set(QMLDIR_SRC_PATH ${CMAKE_CURRENT_SOURCE_DIR}/qmldir)
set(QMLDIR_BIN_PATH ${CMAKE_CURRENT_BINARY_DIR}/qmldir)
add_custom_target(customqml-qmldir DEPENDS ${QMLDIR_SRC_PATH} ${QMLDIR_BIN_PATH})
add_custom_command(
COMMENT "Moving updated resource-file ${QMLDIR_SRC_PATH}"
OUTPUT ${QMLDIR_BIN_PATH}
DEPENDS ${QMLDIR_SRC_PATH}
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${QMLDIR_SRC_PATH} ${QMLDIR_BIN_PATH}
)
add_library(customqml MODULE customqml_plugin.cpp customqml.cpp)
target_link_libraries(customqml PRIVATE Qt5::Qml Qt5::Core)
add_dependencies(customqml customqml-qmldir)
set_target_properties(customqml PROPERTIES AUTOMOC ON)
./qmlplugins/customqml/customqml_plugin.cpp
#include "customqml_plugin.h"
#include "customqml.h"
#include <qqml.h>
void CustomqmlPlugin::registerTypes(const char *uri) {
qmlRegisterType<FileIO>(uri, 1, 0, "CustomQml");
}
./qmlplugins/customqml/customqml_plugin.h
#pragma once
#include <QQmlExtensionPlugin>
class CustomqmlPlugin: public QQmlExtensionPlugin {
Q_OBJECT
Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
void registerTypes(const char *uri) override;
};
./qmlplugins/customqml/customqml.cpp
#include "customqml.h"
CustomQml::CustomQml(QObject *parent): QObject(parent) {}
CustomQml::~CustomQml() {}
./qmlplugins/customqml/customqml.h
#pragma once
#include <QtCore>
class CustomQml: public QObject {
Q_OBJECT
Q_DISABLE_COPY(CustomQml)
public:
CustomQml(QObject *parent = 0);
~CustomQml();
};
./qmlplugins/customqml/qmldir
module customqml
plugin customqml
I've tested on Windows with Visual Studio 2019 and MinGW 8.0 gcc 10.2.0, and also on Ubuntu with gcc 9.3.0.
It builds without errors with all these configurations.
At runtime:
- With Visual Studio and with gcc on Ubuntu, application runs without any issue and displays an empty window.
- But with MinGW, it fails at runtime,
engine.rootObjects()is empty and I can't understand why. What I'm missing?