I have a problem with the seconday dependences of the shared libraries. Suppose we have the following dependency tree:
libA.so
├─libB.so
└─libC.so
└─libD.so
That is, a shared library A depends on shared libraries B and C, and shared library C depends itself on shared library D. A good example for libC
is GSL shared library which depends on CBLAS.
To make a self-sufficient easy-to-use package and to avoid problems with different versions of installed shared libraries, I package the libraries libB
, libC
and libD
with libA
, and as explained, e.g., in Drepper’s article, “How to write shared libraries” (2011), I add the link flag -Wl,-rpath,\$ORIGIN --enable-new-dtags
to set the RUN_PATH
of libA.so
, so that the dynamic loader can find the dependencies of libA
in the corresponding directories, without needing to set LD_LIBRARY_PATH
(which has its downsides).
The problem is that setting the RUN_PATH
in libA
does not help with the secondary dependencies, like libD.so
.
Turning on the dynamic loader debug messages (via setting LD_DEBUG
) reveals that the loader attempts to find libD.so
only in the standard library locations, and not in the location of libA
(contrary to what it does for finding libB
or libC
).
Is there a way to overcome this problem?
Indeed, I can link the libraries C and D statically, if I have the source code or properly compiled static libraries.
But is there a better way?
Solution:
As explained by Employed Russian
the solution is to set RPATH
instead of RUNPATH
.
With recent versions of GCC, one should use the following link flag:
-Wl,--disable-new-dtags,-rpath,\$ORIGIN
RPATH
is searched for transitive dependencies; that is, paths in RPATH
will be considered for everything that is dynamically loaded, even dependencies of dependencies.
In contrast, the ld
dynamic linker does not search RUNPATH
locations for transitive dependencies (unlike RPATH
).
See also:
- Wikipedia: https://en.wikipedia.org/wiki/Rpath#The_role_of_GNU_ld
- SO question: How to set RPATH and RUNPATH with GCC/LD?