What is the difference between LD_LIBRARY_PATH and -L at link time?
The settings of LD_LIBRARY_PATH
has the highest precedence, so when it is set, the set of directories mentioned by LD_LIBRARY_PATH
are searched first even before the standard set
of directories. So in your case setting of LD_LIBRARY_PATH
is influencing the lookup of
the libraries mentioned with -l
option. Without LD_LIBRARY_PATH
some of the dependencies
might have been resolved from the standard set of directories.
Though setting of LD_LIBRARY_PATH
help with debugging and to try out a newer version of
a library its usage in the general development environment setup and deployment is considered bad.
Also refer this HOWTO from Linux Documentation for more details on Shared Libraries
What is the difference between LD_PRELOAD_PATH and LD_LIBRARY_PATH?
LD_PRELOAD
(not LD_PRELOAD_PATH
) is a list of specific libraries (files) to be loaded before any other libraries, whether the program wants it or not. LD_LIBRARY_PATH
is a list of directories to search when loading libraries that would have been loaded anyway. On linux you can read man ld.so
for more information about these and other environment variables that affect the dynamic linker.
LD_LIBRARY_PATH vs LIBRARY_PATH
LIBRARY_PATH
is used by gcc before compilation to search directories containing static and shared libraries that need to be linked to your program.
LD_LIBRARY_PATH
is used by your program to search directories containing shared libraries after it has been successfully compiled and linked.
EDIT:
As pointed below, your libraries can be static or shared. If it is static then the code is copied over into your program and you don't need to search for the library after your program is compiled and linked. If your library is shared then it needs to be dynamically linked to your program and that's when LD_LIBRARY_PATH
comes into play.
What's the difference between `-rpath-link` and `-L`?
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
#include <stdio.h>
void foo(void)
{
puts(__func__);
}
bar.c
#include <stdio.h>
void bar(void)
{
puts(__func__);
}
foobar.c
extern void foo(void);
extern void bar(void);
void foobar(void)
{
foo();
bar();
}
main.c
extern void foobar(void);
int main(void)
{
foobar();
return 0;
}
Make two shared libraries, libfoo.so
and libbar.so
:
$ gcc -c -Wall -fPIC foo.c bar.c
$ gcc -shared -o libfoo.so foo.o
$ gcc -shared -o libbar.so bar.o
Make a third shared library, libfoobar.so
that depends on the first two;
$ gcc -c -Wall -fPIC foobar.c
$ gcc -shared -o libfoobar.so foobar.o -lfoo -lbar
/usr/bin/ld: cannot find -lfoo
/usr/bin/ld: cannot find -lbar
collect2: error: ld returned 1 exit status
Oops. The linker doesn't know where to look to resolve -lfoo
or -lbar
.
The -L
option fixes that.
$ gcc -shared -o libfoobar.so foobar.o -L. -lfoo -lbar
The -Ldir
option tells the linker that dir
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
:
$ gcc -c -Wall main.c
$ gcc -o prog main.o -L. -lfoobar
/usr/bin/ld: warning: libfoo.so, needed by ./libfoobar.so, not found (try using -rpath or -rpath-link)
/usr/bin/ld: warning: libbar.so, needed by ./libfoobar.so, not found (try using -rpath or -rpath-link)
./libfoobar.so: undefined reference to `bar'
./libfoobar.so: undefined reference to `foo'
collect2: error: ld returned 1 exit status
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
:
$ gcc -o prog main.o -L. -lfoobar -lfoo -lbar
So far so good. But:
$ ./prog
./prog: error while loading shared libraries: libfoobar.so: cannot open shared object file: No such file or directory
at runtime, the loader can't find libfoobar.so
.
What about the linker's advice then? With -rpath-link
, we can do:
$ gcc -o prog main.o -L. -lfoobar -Wl,-rpath-link=$(pwd)
and that linkage also succeeds. ($(pwd)
means "Print Working Directory" and just "copies" the current path.)
The -rpath-link=dir
option tells the linker that when it encounters an input file that
requests dynamic dependencies - like libfoobar.so
- it should search directory dir
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 of libfoobar.so
:-
$ readelf -d libfoobar.so
Dynamic section at offset 0xdf8 contains 26 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libfoo.so]
0x0000000000000001 (NEEDED) Shared library: [libbar.so]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
...
...
We just need to know a directory where they can be found, whatever they are.
But does that give us a runnable prog
?
$ ./prog
./prog: error while loading shared libraries: libfoobar.so: cannot open shared object file: No such file or directory
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 of prog
at runtime - assuming it remained true at runtime - but it doesn't write that information into the dynamic section of prog
.
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 indeed libfoobar.so
-
might well not be where they are now - $(pwd)
- but the loader might be able to locate them
by other means: through the ldconfig
cache or a setting
of the LD_LIBRARY_PATH
environment variable, e.g:
$ export LD_LIBRARY_PATH=.; ./prog
foo
bar
rpath=dir
provides the linker with the same information as rpath-link=dir
and instructs the linker to bake that information into the dynamic section of
the output file. Let's try that:
$ export LD_LIBRARY_PATH=
$ gcc -o prog main.o -L. -lfoobar -Wl,-rpath=$(pwd)
$ ./prog
foo
bar
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:
$ readelf -d prog
Dynamic section at offset 0xe08 contains 26 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libfoobar.so]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
0x000000000000000f (RPATH) Library rpath: [/home/imk/develop/so/scrap]
... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...
That search path will be tried after the directories listed in LD_LIBRARY_PATH
, if any are set, and before the system defaults - the ldconfig
-ed directories, plus /lib
and /usr/lib
.
What's the difference between -rpath and -L?
You must be reading some outdated copies of the manpages (emphasis added):
-rpath=dir
Add a directory to the runtime library search path. This is used
when linking an ELF executable with shared objects. All -rpath
arguments are concatenated and passed to the runtime linker, which
uses them to locate shared objects at runtime.
vs.
-L searchdir
--library-path=searchdir
Add path searchdir to the list of paths that ld will search for
archive libraries and ld control scripts.
So, -L
tells ld
where to look for libraries to link against when linking. You use this (for example) when you're building against libraries in your build tree, which will be put in the normal system library paths by make install
. --rpath
, on the other hand, stores that path inside the executable, so that the runtime dynamic linker can find the libraries. You use this when your libraries are outside the system library search path.
Difference about pkg-config and LD_LIBRARY_PATH
LD_LIBRARY_PATH
and ld.so.conf
are used to locate shared libraries at run time, when program is started by the loader (ld.so
). pkg-config
files instead contain compiler/linker flags (-I
, -L
, -l
, etc.) needed to build program that uses particular library (e.g. locate linked shlibs via -Lpath
).
Also note that many libraries lack .pc
configs.
Why do I have to define LD_LIBRARY_PATH with an export every time I run my application?
Use
export LD_LIBRARY_PATH="/path/to/library/"
in your .bashrc otherwise, it'll only be available to bash and not any programs you start.
Try -R/path/to/library/
flag when you're linking, it'll make the program look in that directory and you won't need to set any environment variables.
EDIT: Looks like -R
is Solaris only, and you're on Linux.
An alternate way would be to add the path to /etc/ld.so.conf
and run ldconfig
. Note that this is a global change that will apply to all dynamically linked binaries.
Why LD_LIBRARY_PATH is BAD and the correct way to load dynamic libraries
Add the path to the runtime library search path.
gcc -Wl,-rpath=/opt/OpenBlas/lib ...
What the -L
option does at link time, the -rpath
option does at run time.
Related Topics
How to Free Up Space on Docker Devmapper and Centos7
How to Check for Opencv on Ubuntu 9.10
Docker Bash Prompt Does Not Display Color Output
Bluez: Advertise Service/Gatt Server Example
Using Jq to Fetch Key Value from JSON Output
Finding Dlls Required of a Win Exe on Linux (Cross-Compiled with Mingw)
How to Find The Processor Queue Length in Linux
All Newlines Are Removed When Saving Cat Output into a Variable
Linux - Bash - Get $Releasever and $Basearch Values
Understanding Tcpdump Filter & Bit-Masking
Linux Find File Names with Given String Recursively
When Setting Ifs to Split on Newlines, Why Is It Necessary to Include a Backspace
How to Set Limit on Directory Size in Linux
How to Execute Script in The Current Shell on Linux
Why Is "Echo Foo | Read a ; Echo $A" Not Working as Expected