Qt5 QML module is not installed

39,483

Solution 1

I'll try to answer your questions:

  • I think installed means they are located in the proper paths, so
    that they can be found at runtime
  • You should not necessarily create/build a QmlExtensionPlugin for that purpose. You can also use as a module plain QML files in one directory with a qmldir describing this module. It is a matter of distributing your code. With QmlExtensionPlugin you provide the module compiled, if you want to hide the code.
  • The modules can be in resources system or as files on disk, it is up to you.
  • The app looks for modules in predefined paths - in your app's directory, in Qt plugins path, in QML2_IMPORT_PATH, in directories that you added using engine->addImportPath()

There are a bunch of things that can lead to a module not being loaded. You can check the following:

  1. Module identifier in qmldir should be the same as the directory name, where the module actually resides. For example if your module has module identifier module Test.Module in qmldir, your module's relative path must be Test/Module.
  2. If it is a QML extension plugin (shared library), make sure that plugin's directory name is the same as plugin's name.
  3. export QML2_IMPORT_PATH (make sure there is 2 in the name) env variable to point to directory containing your module. There is also a QQmlEngine::addImportPath method, which adds the directory to the list to lookup for plugins.
  4. If it is a qml extension plugin (shared library), then there might be missing dependencies for it. You can check it by Dependency Walker on Windows or ldd command on Linux.
  5. Setting QT_PLUGIN_PATH runtime variable may help to load plugins. It should point to a directory containing you plugin's directory, not the plugin's directory itself.
  6. You can also enable traces to see what's going on while plugins are loaded for better understanding of the problem - export QT_DEBUG_PLUGINS=1 and QML_IMPORT_TRACE=1 environment variables

You can also read this link: https://doc.qt.io/qt-5/qtqml-modules-identifiedmodules.html

Solution 2

In my case (I have all QML files in qrc resources) worked to add qmldir to resources also and call method addImportPath("qrc:/") of QQmlApplicationEngine.

My main.cpp looks like:

QQmlApplicationEngine engine;
engine.addImportPath("qrc:/");
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

Important parts of my .pro file looks like:

RESOURCES += qml.qrc \
    MyModule/mymodule.qrc

QML_IMPORT_PATH += $$PWD

My qmldir:

module MyModule

MyItem          2.0 MyItem20.qml
MyItem          2.1 MyItem21.qml

My qrc:

<RCC>
    <qresource prefix="/MyModule">
        <file>MyItem20.qml</file>
        <file>MyItem21.qml</file>
        <file>qmldir</file>
    </qresource>
</RCC>

And finally my main.qml:

import QtQuick 2.5
import QtQuick.Window 2.2

import MyModule 2.0

Window {
    visible: true
    width: 640
    height: 480

    MyItem {
        anchors.fill: parent
    }
}

QtCreator is happy (not underlining components and imports) and module is loaded. Hope this helps.

Solution 3

I want to expand on arxarian's answer - which I think is the best technique for integrating modules - but couldn't fit those thoughts in a comment, so here's a new answer.

It's important to first understand that qml modules and their associated resources are runtime entities and are assumed to separately exist at some location relative to the executable unless they're included in the application resources. By including them in the resources, they are still runtime entities, but they exist under the qrc:/ root path within the application binary. This hiding of the modules is the primary reason why I think this is the best technique, unless you want your modules to be open to revision after deployment, or to be independently deployable as precompiled plugins (i.e., in the resource storage of a dynamically linked library).

So here's my explanation of the important elements of arxarian's answer:

  1. engine.addImportPath("qrc:/"); is needed in the C++ code prior to loading the qml to instruct the engine to look for qml modules in the application resource storage.
  2. RESOURCES += MyModule/mymodule.qrc is needed in the project (.pro) file to add the module's files to the application resource storage.
  3. QML_IMPORT_PATH += $$PWD in the project file tells Qt Creator to look for the module starting from the root of the project source tree. In my case I had to set this to a subdirectory (e.g., "ui/modules") because my module directories started there. The import path should include the root(s) beneath all module directories. As far as I can tell, this instruction is only for the Qt Creator IDE and does not impact the build - that's why #1 is needed.
  4. The contents of the qmldir file is as is standard for all qml modules, but it's inclusion in the module's .qrc resource file is not intuitive until you think about what's happening with runtime storage. It needs to be in the .qrc so that it is included in the application resource storage, so that the engine can find it at runtime to define the module. <qresource prefix="/MyModule"> in the module's .qrc file defines the module subdirectory relative to the qrc:/ root in the application resource storage.
  5. The import MyModule <version> statement in qml is now setup for success. On startup the engine will have located the module in its directory under qrc:/, parsed the qmldir file there to define the module and established the name and version from those entries.

Hopefully this helps others understand what's going on, and please let me know if I've misunderstood anything.

Share:
39,483
jkj yuio
Author by

jkj yuio

Android developer

Updated on November 06, 2020

Comments

  • jkj yuio
    jkj yuio over 3 years

    I'm confused about modules in Qt QML. I've read all the docs, but it doesn't make clear some basic ideas.

    I understand that i can put a bunch of QML files into a directory and add a qmldir file to describe an identified module. When i do this and adjust the QML_IMPORT_PATH, QtCreator is happy and stops underlining the import ModuleName 1.0 line.

    So creator is happy, but it does not work. I get module is not installed. my questions are:

    • what does it mean by "installed". I have directory of files, but i haven't "installed" them anywhere.
    • should i be building/compiling the module to make a DLL/.so ?
    • does the module QML files go into the resources of the main app, otherwise where are they to be found?
    • my main.qml file is part of the app resources, how does the app locate the resources of the module at runtime.

    Sorry, for all these questions, but the basics of these modules is just not clear. I don't understand if a "module" is just the sharing of files or is it a compiled unit.

    thanks for any help.