Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct
[SOLVED] Problem with a plugin which depends on another plugin
Hi, I am trying to make my application as modular as possible by having everything as a plugin. Some of my plugins are self-contained (e.g. plugin A) while others are dependent on other plugins (e.g. plugin B depends on plugin A, more precisely B uses resources and classes which are defined in A).
Before building A and B as 'proper' plugins, I thought I would first build them as 'pure' shared libraries (note: in case it matters, I use CMake not QMake), and everything builds as expected and I can load A and B using QLibrary. If I use QPluginLoader, then obviously I get told that A and B are not Qt plugins.
The next step was for me to make A and B 'proper' plugins. I thought I would start with A and disable B, so that I could test the loading of A using QPluginLoader, and indeed everything works as expected and I can load A using QPluginLoader. Next, I made B a 'proper' plugin, but this time round it doesn't build... I get several undefined references to classes that are defined in A and which I need in B.
Now, could it be that I overlooked something? If so, what could it be? As I said, if I remove the plugin-specific side of things (i.e. Q_EXPORT_PLUGIN2) then everything builds and loads fine.
Have you linked plugin A to plugin B? Have you exported the symbols properly?
[quote author="loladiro" date="1308857694"]Have you linked plugin A to plugin B? Have you exported the symbols properly? [/quote]
As I said, if I build A and B as 'pure' shared libraries, then everything is fine so I would expect things to be fine when converting them to 'proper' plugins? Well, maybe not after all!
In that case, can you show us the (relevant) source code?
Ok, first I have my main plugin interface:
Then, I have my Core plugin (equivalent to A which I mentioned earlier):
- https://github.com/opencor/opencor/blob/master/src/plugins/misc/Core/CMakeLists.txt which, to make Core a 'proper' plugin, requires coreplugin.cpp|h:
Then, I have my Viewer plugin which relies on the aforementioned Core plugin (as well as another plugin):
- https://github.com/opencor/opencor/blob/master/src/plugins/edit/Viewer/CMakeLists.txt which, to make Viewer a 'proper' plugin, would normally require viewerplugin.cpp|h, but I haven't yet committed the code to my Git repository. This being said, it's very similar to the above code for the Core plugin.
What is worth pointing out, I guess, is the fact that for the CMakeLists.txt file for my Viewer plugin, I call my BUILD_PLUGIN with the two plugins on which my Viewer plugin depends (the Core and QtMmlWidget plugins). That macro is defined here:
and is the same CMake code that I used to build my plugins as 'pure' shared libraries. The only difference are the reference (in the plugin's CMakeLists.txt file) to the xxxplugin.cpp|h files and, as a result, the reference to Q_EXPORT_PLUGIN2.
For information, if I try to build my project, then I get the following link errors due to my trying to make the Viewer plugin a 'proper' plugin:
bq. Linking CXX shared library ........\Viewer.dll
Creating library file: ........\libViewer.dll.a
CMakeFiles\ViewerPlugin.dir/objects.ammlviewerwidget.cpp.obj):mmlviewerwidget.cpp:(.text+0xd9): undefined reference to
QtMmlWidget::paintEvent(QPaintEvent*)' CMakeFiles\ViewerPlugin.dir/objects.a(mmlviewerwidget.cpp.obj):mmlviewerwidget.cpp:(.text+0x11b): undefined reference toOpenCOR::CommonWidget::drawBorderIfDocked(bool const&, bool const&, bool const&, bool const&, bool const&)'
collect2: ld returned 1 exit status
mingw32-make: *** [Viewer.dll] Error 1
mingw32-make: *** [src/plugins/edit/Viewer/CMakeFiles/ViewerPlugin.dir/all] Error 2
mingw32-make: *** [all] Error 2
May I ask why you want to create plugins if the interface is empty (what's the use)? AS for your problem, I'm pretty sure you missed linking the libraries properly (I don't usually use CMake, so I can't really help with that). The problems would have also shown up if you had instantiated your classes in the depending problem (which is essentially what Q_EXPORT_PLUGIN2) does. If I were you I wouldn't make plugins for everything. At least the QtMmlWidget would be better in a shared Library (just like everything else if you don't put anything in your interface definition, but I suspect you'll change that).
The interface is empty because I am just working my way towards converting my different modules into plugins. Those modules used to be directly embedded in my application, but I have decided to make plugins out of them, and I prefer to go one step at a time. My first task therefore consisted of extracting those modules from my application and having them as shared libraries. This all worked fine and I was able to link to those libraries at compilation time and make use of them as such. Then, I didn't link to them anymore, but was still able to load them (using QLibrary). At that stage, I didn't try to use those libraries since it would have been quite a pain. This is why I then wanted to convert them to a plugin so that I could easily access them via an interface. So, yes, the interface is empty at the moment, but that's because I first want to be able to build those plugins and load them (using QPluginLoader) before implementing the rest.
With regards to QtMmlWidget, it could most certainly be made available through a 'simple' shared library. In fact, this is what I used to have (and the same with all the other 3rd party libraries that I use), but since I am going the plugin way, I thought I might do the same for the 3rd party libraries I use.