QPluginLoader: loading plugin library with another shared lib dependency (linux)
Hi All,
hope you can help me with a "convenience" issue. I'm writing an application with plugin-support on Linux. As these plugins shall be updated outside the general "apt-get update & upgrade" mechanism (with user priviliges) there are located in some subdirectory of the home path. The plugins are configured to be used with QPluginLoader. The plugin-libraries depend on other shared libraries themselves, which are also located in some local path or in the same path as the plugin library.
Normally, the locations of the plugins are NOT listed in LD_LIBRARY_PATH (as this is a system-wide variable and should normally not be adjusted when installing/uninstalling plugins).
I have created a minimalistic test setup in https://github.com/ghorwin/CppCodingTutorials, subdirectory Qt/plugins
(clone the repo, load the three projects in the directory, build and test yourself).
This is the setup:
- PluginLoader loads the plugin library “TestPlugin” at runtime
- TestPlugin requires TestLib as shared library dependency
When running the test, the plugin-loader complains with the errorString:
"Cannot load library /home/ghorwin/git/CppCodingTutorials/Qt/plugins/lib/libTestPlugin.so.1.0.0: (libTestLib.so.1: Kann die Shared-Object-Datei nicht öffnen: Datei oder Verzeichnis nicht gefunden)"
However, when I add the local path to the so-files to LD_LIBRARY_PATH, linking works fine (you can try this in QtCreator easily yourself, by adjusting LD_LIBRARY_PATH in the execution environment).
As recommended by the Qt documentation, I added the library search path to QCoreApplication as follows:
Code:
qApp->addLibraryPath(pluginDir.absolutePath()); // BUG: THIS DOES NOT WORK
qDebug() << qApp->libraryPaths(); // Shows our so directory
bool success = pd.m_loader->load(); // load the plugin - failes to load plugin, as dependency libTestLib.so is not found
Adding a library search path via addLibraryPath apparently does not work.
Here are my questions:
- Would you have any idea why addLibraryPath() does not work as expected on Linux?
- Ist there any alternative to adjusting the LD_LIBRARY_PATH environment variable prior to loading the plugins?
Thanks for any ideas!
-Andreas
Re: QPluginLoader: loading plugin library with another shared lib dependency (linux)
Hi, my guess my addLibraryPath() does not work as you expect is that the dependencies of your plugin are not handled by your Qt program (where you called addLibraryPath), but by the "normal" procedure, which relies on LD_LIBRARY_PATH and does not know about the addLibraryPath() call.
One alternative could be that you use static linking to link libTestLib.so.1 (or the corresponding .a file) to your plugin.
Ginsengelf
Re: QPluginLoader: loading plugin library with another shared lib dependency (linux)
Quote:
Originally Posted by
Ginsengelf
Hi, my guess my addLibraryPath() does not work as you expect is that the dependencies of your plugin are not handled by your Qt program (where you called addLibraryPath), but by the "normal" procedure, which relies on LD_LIBRARY_PATH and does not know about the addLibraryPath() call.
One alternative could be that you use static linking to link libTestLib.so.1 (or the corresponding .a file) to your plugin.
As for your "guess", this matches my observation. My expectation was, however, that when loading the shared library the Qt code somehow updates the LD_LIBRARY_PATH variable locally, then loads the library (with the typical linux-style dlopen() call and restores the environment variable afterwards. However, this won't work, as the man page for dlopen() clearly states:
Quote:
• If, at the time that the program was started, the environment
variable LD_LIBRARY_PATH was defined to contain a colon-
separated list of directories, then these are searched. (As a
security measure, this variable is ignored for set-user-ID and
set-group-ID programs.)
So, as there is no other way to tell dlopen() where to search for (indirectly linked) shared libs, my setup won't work on Linux.
As for the suggestion to link all dependent libraries statically, this is - unfortunately- not possible in all cases due to licensing restrictions.
The only remaining option I see here is to somehow edit the DT_RUNPATH ELF variable in my library, as this seems to be the only remaining way to tell ldopen() where to search for libraries.
Anyway, this is not a Qt issue (anylonger), hence I'm closing the topic.