Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Qt 5.13 gives error for plugins with precompiled QML



  • How to create a standalone QML extension plugin that publishes QML components that are precompiled in the plugin DLL without exposing QML files?

    In plugin DLL pro-file:

    • Add qml files in resources
    • use "config += qtquickcompiler"

    Include both plugin DLL and qmldir in plugin import directory so there are files

    $$QML2_IMPORT_PATH/MyPlugin/myplugin.dll
    $$QML2_IMPORT_PATH/MyPlugin/qmldir

    Now to the problem. Let's assume qmldir lists the included QML files normally like:

    module MyPlugin
    plugin myplugin
    MyComponent 1.0 MyComponent.qml

    Then let's try to import the plugin in an application QML

    import MyPlugin 1.0
    
    MyComponent {}
    

    -> This gives error because MyComponent.qml is actually precompiled and located in the resources of myplugin library (qrc:/MyComponent.qml)

    Workaround to this is to change plugin's qmldir like this:

    module MyPlugin
    plugin myplugin
    MyComponent 1.0 qrc:/MyComponent.qml

    -> This works perfectly otherwise, but starting from Qt 5.13, it gives console error for each included QML component:

    "Component "MyComponent" is specified with non-relative URL "qrc:/MyComponent.qml" in a qmldir file. URLs in qmldir files should be relative to the qmldir file's directory."

    Everything seems to work still, but clearly these console errors are suggesting that this is a wrong way to do it.
    So, is there any working solution now without these console errors for precompiled QML plugins?

    (Note, documentation of qtquickcompiler actually advices to put also qmldir of the precompiled component in its resources, but in that case case, system does not find the plugin because to load the plugin library's resources containing "qmldir", it should load the plugin first and that cannot be done if "qmldir" is only in its resources.)



  • Hello -mt-,

    I just had the same issue on Qt 5.12.4 but for me it is not only console errors, files are not loaded at all.

    I don't know if you succeed to resolve your problem, but I post here my solution.

    I have declared by QML files from C++ with the QQmlExtensionPlugin instead of the qmldir file. It can be done with this method: int qmlRegisterType(const QUrl &url, const char *uri, int versionMajor, int versionMinor, const char *qmlName)

    Here an example with the qml file Ostrich.qml

    // animalsplugin.h
    #pragma once
    #include <QQmlExtensionPlugin>
    
    class AnimalsPlugin : public QQmlExtensionPlugin
    {
        Q_OBJECT
        Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
    
    public:
        void registerTypes(const char *uri) override;
    };
    
    // animalsplugin.cpp
    #include "animalsplugin.h"
    #include <qqml.h>
    
    void AnimalsPlugin::registerTypes(const char *uri)
    {
        qmlRegisterType(QUrl("qrc:/Ostrich.qml"), uri, 1, 0, "Ostrich");
    }
    

    I don't know if it is a good way to do it and I would be interested in an official solution to avoid exposing my code with my plugin. But at least it resolves my problem



  • Faced the same issue at my project on Qt 5.13.2.
    Simon's approach works fine until you don't need to use singletons.

    If you register singleton in C++ plugin class:

    void MyPlugin::registerTypes(const char *uri)
    {
        qmlRegisterSingletonType(QUrl("qrc:/Palette.qml"), uri, 1, 0, "Palette");
    }
    

    You will have two copies of singleton object. One for main application and one for plugin.
    But if you define singleton in qmldir, it will be unique as expected.


Log in to reply