mosra / magnum-plugins

Plugins for the Magnum C++11 graphics engine
https://magnum.graphics/
Other
98 stars 59 forks source link

PluginManager::Manager::load(): cannot load plugin AssimpImporter #63

Closed xiconxi closed 5 years ago

xiconxi commented 5 years ago

PluginManager::Manager::load(): cannot load plugin AssimpImporter from "/home/obirt/Code/Render/VIS-magnum/cmake-build-debug/src/magnum-d/importers/AssimpImporter.so": /home/obirt/Code/Render/VIS-magnum/cmake-build-debug/src/magnum-d/importers/AssimpImporter.so: undefined symbol: _ZN6Magnum5Trade16AnyImageImporterC1ERN7Corrade13PluginManager7ManagerINS0_16AbstractImporterEEE

xiconxi commented 5 years ago

I'm very sorry to make a mistake for this. I forgot to compile to metadata and copy the same path as AssimpImporter.so

mosra commented 5 years ago

Hi, sorry -- I had a reply written but forgot to send it :see_no_evil: Usage of plugins in combination with CMake subprojects is currently everything but ideal. Fixing this is on my short-term roadmap, but not quite there yet.

I just updated Corrade to make this error clearer in mosra/corrade@438fd97c1ea03c2030601d5cc5acd186ad749e62 -- now it will warn about the actual error instead of ending up with a cryptic message like this. The ideal fix for this is to not require random conf files and instead have the metadata self-contained in the *.so. Added that to TODOs for the next release.

xiconxi commented 5 years ago

to get the shared object dependencies, here's some code snippet base on ELF:

#include <dlfcn.h>
#include <elfio/elfio.hpp>
#include <iostream>

int main(int argc, char** argv) {
    ELFIO::elfio reader;
    reader.load(argv[1]);
    auto dynamic = ELFIO::dynamic_section_accessor(reader, reader.sections[".dynamic"]);
    std::cout << "enties num: " << dynamic.get_loaded_entries_num() << std::endl;
    ELFIO::Elf_Xword tag, value;
    std::string entity_str;
    for(int i = 0; i < dynamic.get_loaded_entries_num(); i++) {
        dynamic.get_entry(i, tag, value, entity_str);
        if(tag == DT_NEEDED)
            std::cout << "DT_NEEDED: " << entity_str << std::endl;
        else if(tag == DT_RPATH)
            std::cout << "DT_RPATH: " << entity_str << std::endl;
        else if(tag == DT_RUNPATH)
            std::cout << "DT_RUNPATH: " << entity_str << std::endl;
    }
}

ELFIO

mosra commented 5 years ago

Problem is, the plugin is not explicitly linked to any of its plugin dependencies at compile-time, so the ELF file can't know what *.sos it depends on -- that's what the metadata file is there for. Plus there isn't always 1:1 mapping from a plugin to its dependencies, sometimes it can be multiple plugins satisfying the same dependency. And, finally, the metadata contain other important information needed by the plugin, in case of AssimpImporter it's various configuration of the import behavior (which can be either overriden from the code or changed directly in the conf file).

Contrary to plugin dependencies, for library dependencies (e.g. the AssimpImporter depending on libassimp.so), the dependency is resolved at compile-time and this "just works" -- when loading the AssimpImporter plugin, it just loads libassimp.so on its own, no need to do anything explicitly there.

xiconxi commented 5 years ago

What's the meaning of the plugin is not explicitly linked to any of its plugin dependencies at compile-time? plugin is a lib too, I think all the runtime shared object dependencies has been explicitly linked to the plugin. Those default configurations could declare in header, custom configurations using .conf file . Then the .conf files are removed in trival-case. That's what I really recommand for.

williamjcm commented 5 years ago

What mosra said is that plugins aren't linked to other plugins. Only to the libraries they directly depend on.

xiconxi commented 5 years ago

thank you guys. plugins aren't linked to other plugins

mosra commented 5 years ago

Just FYI: since mosra/corrade@73d3f31d3ef949e2ba0da1ac46967175bfb4a377, mosra/magnum@3a243a04b2217147740d01984c7dd796584c7f7d and mosra/magnum-plugins@dff98d86a1853cf67c0651cfe0da1f52df2b6b5f, plugins are put in the build directory into a common location, which makes CMake subprojects with default config (i.e., dynamic plugins) "just work". This change should also improve the experience for Windows users as all DLLs are placed next to the executables.