QuickQanava icon indicating copy to clipboard operation
QuickQanava copied to clipboard

Install step / Build QML plugins with CMake - Discussion

Open machinekoder opened this issue 6 years ago • 10 comments

Currently, there is no install step specified in the CMakeLists.txt. This makes it unclear how to use QuickQanava in an application.

I suggest deploying QuickQanava as QML module, so it can be easily used by other applications, even if they are written in PyQt for example. I have done this in my framework by installing the QML files and libraries to the QT_INSTALL_QML path (see deployment.pri). This also requires adding a plugin.cpp containing the plugin description.

Unfortunately, I haven't worked a lot with the Qt + CMake combination so far, so I can't provide any recipes. However, if QuickQanava turns out to be useful for my application, I'm happy to contribute any changes I make back upstream.

machinekoder avatar Aug 19 '18 13:08 machinekoder

Qt5Qml_INSTALL_QML seems to be the correct path. https://pastebin.ubuntu.com/7004415/

machinekoder avatar Aug 19 '18 13:08 machinekoder

Thanks for your PR(s) Alexander,

You are right, an install step is missing. Until now, the preferred way to use QuickQanava was direct .pri inclusion from an external qmake project. Creating a QML module is a very good idea, I will merge all your PRs in 'develop' branch.

BTW, @kwallner has also done some work on CMake configuration to ease deployment with Conan.io, I will try to integrate his change in develop too.

cneben avatar Aug 21 '18 08:08 cneben

Just tested the develop branch. Looks good.

machinekoder avatar Aug 21 '18 20:08 machinekoder

Hi @machinekoder @cneben ,

To summarize the changes in my fork:

  • Integration/Usage of Conan.io. This is optional as there are not dependencies. So "conanbuildinfo.cmake" does only changes to some CMake-Variables (CMAKE_*_OUTPUT_DIRECTORY etc.) As I have seen you are using a CMake-Variable (CONAN_BUILD). Better just check for the existence of the file: if (EXISTS ${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
  • Use modern CMake Use properties on targets (like generator expressions for include-patshs), ... In the exports-subdirectory contains the generation of a QuickQanavaConfig.cmake. As I'm using conan.io using dependencies is based on cmake's Find/Config-mechanism.

kwallner avatar Aug 22 '18 06:08 kwallner

Thank for your work @machinekoder and @kwallner !

Latest commits on develop probably address this issue: QuickQanava could now be used from cmake using QML module(s). Support for the good old static way of embedding the complete library in a resource file is still working trough direct qmake .pri inclusion.

I have added more documentation for CMake install in README.MD.

Comments, code review and tests on exotic environments are welcome ! (tested on a recent Ubuntu/g++7/Qt 5.11 and CMake 3.10)

Perhaps @ruisebastiao could join the discussion, since many commits in his QuickQanava fork from https://github.com/ruisebastiao/AutomationStudioV2 and https://github.com/ruisebastiao/QuickQanava/tree/plugin are related to QML plugins and CMake configuration ?

(NB: Still untested on Windows...)

cneben avatar Sep 12 '18 13:09 cneben

Thanks for all your great work on this.

I've been trying this out on the develop branch, with MSVC2017 on Windows. I manage to build and load the plugin so that QtQuick starts parsing the QML in the QRC, but then it fails like this:

QQmlImports(qrc:/QuickQanava/LineGrid.qml)::addLibraryImport: "QuickQanava" 2.0 as "Qan"
QQmlImports(qrc:/QuickQanava/LineGrid.qml)::importExtension: loaded "D:/p/projects/foo/build/lib/GUI/QuickQanava/qmldir"
QQmlImports(qrc:/QuickQanava/LineGrid.qml)::resolveType: "Shape" => "QQuickShape" TYPE
QQmlImports(qrc:/QuickQanava/LineGrid.qml)::resolveType: "Qan.AbstractLineGrid" => "qan::LineGrid" TYPE
QQmlImports(qrc:/QuickQanava/LineGrid.qml)::resolveType: "ShapePath" => "QQuickShapePath" TYPE
QQmlImports(qrc:/QuickQanava/LineGrid.qml)::resolveType: "Component" => "QQmlComponent" TYPE
QQmlImports(qrc:/QuickQanava/LineGrid.qml)::resolveType: "PathLine" => "QQuickPathLine" TYPE
QQmlImports(qrc:/QuickQanava/LineGrid.qml)::addImplicitImport
QQmlImports(qrc:/QuickQanava/LineGrid.qml)::importExtension: loaded ":/QuickQanava/qmldir"
QQmlImportDatabase::resolvePlugin: Could not resolve plugin "quickqanavaplugin" in ":/QuickQanava"

The only way I could get it working is by removing the qmldir from QuickQanava_plugin.qrc but I'm not sure if this will bork other types of build.

rokel avatar Sep 27 '18 13:09 rokel

qmldir is only needed as a hint for Qt Creator / QML designer when registering QML types via C++, so I think it's safe to remove it from the qrc file.

machinekoder avatar Sep 28 '18 14:09 machinekoder

Removing the qmldir from main resource file is working because a valid qmldir is still present in your $QTDIR/qml/QuickQanava directory. Without a qmldir, quickqanavaplugin.dll/so is in fact never loaded and an 'import QuickQanava 2.0' declaration would fail (On 'import XXX' declaration, Qt looks in current QQmlEngine::importPaths() qmldir, then resolve the plugin XXX.so/dll in QQmlEngine::pluginPaths()).

I've spent hours debugging the "plugin + resource system" on Windows, and it work well until you have to create custom nodes or graph from c++ (ie from outside the dll).

Since Qanava rely extensively on creating delegates from c++ using QML files in the resource system with QQmlComponent('qrc:/QuickQanava/component.qml'), you have to make two calls to Q_INIT_RESOURCE(), one from the plugin ... and one from the application code (main()). It work perfectly on Linux thanks to the .so dynamic linking model, but with Windows dll you end up with types in the same namespace (QuickQanava 2.0) but qmlRegistered() either from the dll resource or the application resource and it generate strange QML error messages: qrc:/dataflow.qml:48 Cannot assign object to property

For example, you can no longer assign a subclasse of qan::Graph to the qan::Graph graph property of GraphView.

I’ve no idea of how to fix that and I’am a bit annoyed by this dynamic linking nightmare: especially having to configure import/plugin paths at runtime to load dll or writing dll in Qt “system directory” to install things. So I think I will reactivate a full static build with Cmake and add an option for dynamic linking until I find a better solution.

For the moment … use static linking and .pro inclusion, it works perfectly everywhere.

cneben avatar Sep 28 '18 22:09 cneben

Hello @cneben,

sorry for my late response. I'm not an expert with CMAKE, either with the plugin system of Qt most of the code that i have was taken from other projects. But i will try to help in what i can. For now i'm using QuickQanava as a plugin in a embedded application with buildroot targeting the raspberry pi without problems

ruisebastiao avatar Oct 01 '18 15:10 ruisebastiao

It is not appropriate to perform the installation during the build step.

ohmyarch avatar Dec 21 '18 02:12 ohmyarch