The man for gold
states:
-L DIR, --library-path DIR
Add directory to search path
--rpath-link DIR
Add DIR to link time shared library search path
The man for bfd ld
makes it sort of sound like -rpath-link
is used for recursively included sos.
ld.lld
doesn't even list it as an argument.
Could somebody clarify this situation for me?
The
--rpath-link
option is used by bfd ld to add to the search path used for finding DT_NEEDED shared libraries when doing link-time symbol resolution. It's basically telling the linker what to use as the runtime search path when attempting to mimic what the dynamic linker would do when resolving symbols (as set by--rpath
options or theLD_LIBRARY_PATH
environment variable).Gold does not follow DT_NEEDED entries when resolving symbols in shared libraries, so the
--rpath-link
option is ignored. This was a deliberate design decision; indirect dependencies do not need to be present or in their runtime locations during the link process.Here is a demo, for GNU
ld
, of the difference between-L
and-rpath-link
- and for good measure, the difference between-rpath-link
and-rpath
.foo.c
bar.c
foobar.c
main.c
Make two shared libraries,
libfoo.so
andlibbar.so
:Make a third shared library,
libfoobar.so
that depends on the first two;Oops. The linker doesn't know where to look to resolve
-lfoo
or-lbar
.The
-L
option fixes that.The
-Ldir
option tells the linker thatdir
is one of the directories to search for libraries that resolve the-lname
options it is given. It searches the-L
directories first, in their commandline order; then it searches its configured default directories, in their configured order.Now make a program that depends on
libfoobar.so
:Oops again. The linker detects the dynamic dependencies requested by
libfoobar.so
but can't satisfy them. Let's resist its advice -try using -rpath or -rpath-link
- for a bit and see what we can do with-L
and-l
:So far so good. But:
at runtime, the loader can't find
libfoobar.so
.What about the linker's advice then? With
-rpath-link
, we can do:and that linkage also succeeds.
The
-rpath-link=dir
option tells the linker that when it encounters an input file that requests dynamic dependencies - likelibfoobar.so
- it should search directorydir
to resolve them. So we don't need to specify those dependencies with-lfoo -lbar
and don't even need to know what they are. What they are is information already written in the dynamic section oflibfoobar.so
:-We just need to know a directory where they can be found, whatever they are.
But does that give us a runnable
prog
?No. Same as story as before. That's because
-rpath-link=dir
gives the linker the information that the loader would need to resolve some of the dynamic dependencies ofprog
at runtime - assuming it remained true at runtime - but it doesn't write that information into the dynamic section ofprog
. It just lets the linkage succeed, without our needing to spell out all the recursive dynamic dependencies of the linkage with-l
options.At runtime,
libfoo.so
,libbar.so
- and indeedlibfoobar.so
- might well not be where they are now -$(pwd)
- but the loader might be able to locate them by other means: through theldconfig
cache or a setting of theLD_LIBRARY_PATH
environment variable, e.g:rpath=dir
provides the linker with the same information asrpath-link=dir
and instructs the linker to bake that information into the dynamic section of the output file. Let's try that:All good. Because now,
prog
contains the information that$(pwd)
is a runtime search path for shared libraries that it depends on, as we can see:That search path will be tried after the directories listed in
LD_LIBRARY_PATH
, if any are set, and before the system defaults - theldconfig
-ed directories, plus/lib
and/usr/lib
.