Plugins depending on other plugins problem

This is a problem that I currently did not expect - because so far it worked for me! But I did some renaming, and that might have caused the issue to appear now.

Some of my plugins are derived from some others from my own project. Meaning that their “modules” (which is the actual C++ source code) depends on the “modules” of their “parents” - in order to #include the header and derive the class. As a consequence I put the parent modules into the DEPENDS section of the vtk.module file of the child plugin modules, because only with that I can do the proper #include in the C++ headers.

But now I am getting complaints from ParaViewPlugin.cmake:581: “Failed to find the required module …” - meaning: the module from the parent plugin. This is from the paraview_add_plugin function that wants to build it’s modules and make sure that modules on which it depends do exist. Well - they come later in the list, so they are not built at that moment yet…

So I went for another solution: from the call to paraview_plugin_scan I am getting the names of the modules that are required by the plugins, so I can simply filter out those that are from my own project and build them explicitly before I do the paraview_add_plugin call. With that they should exist when they are required!

But now I am getting another error message from vtkModule.cmake(2079): “The … module has been requested to be built, but it is already built by this project”. This is from the vtk_module_build function which in turn is automatically called by paraview_add_plugin, trying to build the plugin module. But yes - it was already built in order to satisfy some other plugin!

Ok - this is a bit circular in my eyes…

I think I will do now the following - as kind of a workaround: after having the list of plugins from the paraview_plugin_scan function, I will analyze that list and sort it somehow in a way that plugins that are needed by others are first and the others later. A little bit “hackish” in my eyes, but I guess that in my case I will manage like that: it is basically four plugins that have to be ensured that they come in front of all others.

However, a more thorough solution should in my eyes avoid the above circle, by either allowing plugins to depend on modules that are not built yet. Ok, this can generate a problem later on. Or simply not building plugin modules that are already built - instead of complaining: the modules are there - what else do we want?

If a module is to be used by more than one plugin, I highly suggest moving it out of the scope of plugins and into the main build. It is obviously more general than code for a specific plugin at that point.

That makes sense - and I would also like the idea to “loosen” the 1:1 relationship between plugins and modules in my project! However, there were so many things where I struggled in the beginning because I did not understand them yet that finally this 1:1 relation was the only thing that I finally got working.

One very basic thing was the fact that I have somehow two types of VTK modules in a PV project: 1) those that I call “standalone modules” and 2) those that I call “plugin modules” because they are directly related to a plugin. Which basically only makes the following CMakeLists.txt setup logical:

  1. paraview_plugin_find_plugins and paraview_plugin_scan - finding modules that are required by plugins, but EXCLUDING the plugin modules

  2. vtk_module_find_modules and vtk_module_scan - more or less just check if required standalone modules can be built

  3. vtk_module_build - but ONLY for the standalone modules

  4. paraview_plugin_build - for building the plugins, but ALSO automatically the plugin modules

Also now I added another step between 3 and 4, checking the “plugin required modules” if there names actually match with plugins, and simply put these plugins first in the plugin list for step 4. Of course this would not work any more with more complex interrelationships, but at the moment it is ok

I think if I had understood this from the beginning, I would have separeted plugins and modules much more - putting a lot of code into modules and realize many plugins only with an XML file, referring to classes that are inside some standalone modules. But basically I did not understand the difference between these two types of modules, so when I e.g. tried to refer in the paraview_add_plugin call (which is indirectly called through the paraview_build_plugin) to a module that was also already used by another plugin - I got these error messages about “module already built” that I had also yesterday.

With the huge difference that now I understood the logic of the two module types, while in the beginning of my project this was the reason that triggered me to entirely restructure my project again - avoiding any common use of modules between plugins.

You could also say that I did not understand the “hidden vtk_module_build” inside the plugin building logic.

But still today I do not understand why this hidden call should generate an error if somebody tries to refer to a module from several plugins: In my eyes should the fact that a module already exists not trigger an error message, but simply not build it once more, so using the existing module once more.

This way leads to duplicate symbols and spooky runtime linker errors. You don’t want to go there :slight_smile: . The thing is that two plugins both “claiming” a module causes two client server wrapping setups to run. That also ends up with duplicate symbols and CS binding registration. If you have CS wrappings that need to be leveraged by multiple plugins, I suggest doing something like pvPluginInitializer here.

Basically, manually wrap your modules using vtk_module_wrap_client_server and paraview_server_manager_process and link to them in your new “plugin module”. Exclude the module from CS wrapping by using vtk_module_client_server_exclude() (it’d be recursive otherwise). Then make a static plugin like this behind a Schwarz counter to prevent duplicate registration. Your plugins can then trigger this plugin load in an auto_start interface of their own.