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

Qmake rules for C++ plugin extension to QML



  • Hi all,

    I am struggling with the necessary qmake magic to make use of a C++ plugin I built for QML. (On Windows)

    My project is just an at-home learning adventure where I download my Strava cycling activities and try to do some interesting statistical analysis on them. That all works fine.

    The project is laid out as follows:

    0_1472341760487_projectLayout.PNG

    I.e. 3 subdirs... 'cppSrc' is the main plugin, 'main' is my test app, where I want to use the plugin in QML, and 'UnitTests' is obvious.

    The 'DeepStats.pro' file looks like this:
    TEMPLATE = subdirs

    SUBDIRS +=
    main
    UnitTests
    cppSrc

    main.depends = cppSrc
    UnitTests.depends = cppSrc

    The 'cppSrc.pro' file looks like this:
    QT -= gui
    QT += core network qml
    CONFIG += qt shared plugin

    ! include(../common.pri) {
    error("Couldn't find the common.pri file")
    }

    TARGET = deepstats
    TEMPLATE = lib

    DEFINES += DEEPSTATS_LIBRARY

    SOURCES +=
    stravaaccess.cpp
    stravastats.cpp
    stravaactivities.cpp
    stravaactivity.cpp
    stravarangesummary.cpp
    stravaactivitiesmodel.cpp
    stravaportal.cpp

    HEADERS +=
    deepstats_global.h
    stravaaccess.h
    stravastats.h
    stravaactivities.h
    stravaactivity.h
    stravarangesummary.h
    stravaactivitiesmodel.h
    stravaportal.h
    deepstats_plugin.h

    unix {
    target.path = /usr/lib
    INSTALLS += target
    }

    The 'main.pro' file looks like this:
    QT += qml quick

    CONFIG += c++11

    ! include(../common.pri) {
    error("Couldn't find the common.pri file")
    }

    SOURCES += main.cpp

    INCLUDEPATH += ../cppSrc

    RESOURCES += qml.qrc

    QML_IMPORT_PATH = .

    include(deployment.pri)

    QMAKE_RPATHDIR += $$DESTDIR

    LIBS += -L$$DESTDIR -ldeepstats

    My 'deepstats_plugin.h' file looks like this:
    #ifndef DEEPSTATS_PLUGIN_H
    #define DEEPSTATS_PLUGIN_H

    #include <QtQml>
    #include <QQmlExtensionPlugin>
    #include "stravaportal.h"
    #include "stravaactivitiesmodel.h"

    class DeepStats_Plugin : public QQmlExtensionPlugin
    {
    Q_OBJECT
    Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
    public:
    void registerTypes(const char *uri)
    {
    Q_ASSERT(uri == QLatin1String("ca.scumpyware.deepstats"));
    qmlRegisterType<StravaPortal>(uri, 1, 0, "StravaPortal");
    qmlRegisterUncreatableType<StravaActivitiesModel>(uri, 1, 0, "StravaActivitiesModel",
    "StravaActivitiesModel is uncreatable");
    }
    };

    #endif // DEEPSTATS_PLUGIN_H

    my 'qmldir' file (in cppSrc), looks like this:
    module ca.scumpyware.deepstats
    plugin deepstats

    So, if I add 'import ca.scumpyware.deepstats 1.0' to my main.qml file, I get the following error:

    QQmlApplicationEngine failed to load component
    qrc:/main.qml:5 module "ca.scumpyware.deepstats" is not installed

    Can somebody please explain what I need to install, and where, and how to make the qmake/*.pro file changes to accomplish this???

    Thanks in advance...



  • Hi... I got this to work by adding this to my cppSrc.pro file:
    win32 {
    # The dir I want the plugin installed to...
    WAYNES_PLUGIN_DIR = C:\Users\wayne_000\Documents\QtProjects\WaynesPlugins\ca\scumpyware\deepstats
    ##message($$WAYNES_PLUGIN_DIR)

    # If my dir doesn't exist, create it...
    PLUGIN_INSTALL_DIR = $$WAYNES_PLUGIN_DIR
    if (!exists($$PLUGIN_INSTALL_DIR)) {
        message("CREATING DIR")
        createpluginsdir.commands = $(MKDIR) $$PLUGIN_INSTALL_DIR
    
        QMAKE_EXTRA_TARGETS += createpluginsdir
        PRE_TARGETDEPS += createpluginsdir
    }
    else {
        message("NOT CREATING DIR")
    }
    
    
    # Now, copy the lib's & the qmldir file to the plugin install dir...
    EXTRA_BINFILES += \
        $$DESTDIR/*.dll \
        $$DESTDIR/*.lib \
        $$DESTDIR/*.pdb \
        $$PWD/qmldir
    EXTRA_BINFILES_WIN = $${EXTRA_BINFILES}
    EXTRA_BINFILES_WIN ~= s,/,\\,g
        DESTDIR_WIN = $${PLUGIN_INSTALL_DIR}
    DESTDIR_WIN ~= s,/,\\,g
    for(FILE,EXTRA_BINFILES_WIN){
                QMAKE_POST_LINK +=$$quote(cmd /c copy /y $${FILE} $${DESTDIR_WIN}$$escape_expand(\n\t))
    }
    

    }

    Then, I added the following to my main.cpp file:

    // ******************************************************************************
    // Add the import path to my plugins...
    QStringList importPathList = engine.importPathList();
    importPathList.append("C:/Users/wayne_000/Documents/QtProjects/WaynesPlugins");
    engine.setImportPathList(importPathList);
    qDebug() << "Path List: " << engine.importPathList();
    // ******************************************************************************
    

    My logic to only create my output plugin directory if it doesn't already exist doesn't seem to work all the time, but if you delete it manually, it all works. Kludgey, I know, but this has been quite frustrating. Surely there is an easier way!!!!


Log in to reply