Linux so library search path

How do you specify the location of libraries to a binary? (linux)

For this question I’ll be using a specific example, but really this generalizes to pretty much any binary on linux that can’t seem to find its’ dependent libraries. So, I have a program that won’t run because of missing libraries:

./cart5: error while loading shared libraries: libcorona-1.0.2.so: cannot open shared object file: No such file or directory 
linux-vdso.so.1 => (0x00007fff18b01000) libcorona-1.0.2.so => not found libstdc++.so.6 => /usr/lib/gcc/x86_64-pc-linux-gnu/4.4.3/libstdc++.so.6 (0x00007f0975830000) libm.so.6 => /lib/libm.so.6 (0x00007f09755af000) libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x00007f0975399000) libc.so.6 => /lib/libc.so.6 (0x00007f0975040000) libz.so.1 => /lib/libz.so.1 (0x00007f0974e2b000) /lib64/ld-linux-x86-64.so.2 (0x00007f0975b36000) 
oliver@human$ find / -name libcorona-1.0.2.so 2> /dev/null /usr/local/lib64/libcorona-1.0.2.so /home/oliver/installed/corona-1.0.2/src/.libs/libcorona-1.0.2.so 

3 Answers 3

For a once-off, set the variable LD_LIBRARY_PATH to a colon-separated list of directories to search. This is analogous to PATH for executables, except that the standard system directories are additionally searched after the ones specified through the environment.

LD_LIBRARY_PATH=/usr/local/lib64 ./cart5 

If you have a program that keeps libraries in a non-standard location and isn’t able to find them on its own, you can write a wrapper script:

#!/bin/sh if [ -n "$LD_LIBRARY_PATH" ]; then LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib64 else LD_LIBRARY_PATH=/usr/local/lib64 fi export LD_LIBRARY_PATH exec /path/to/cart5 "$@" 

The list of standard system directories is kept in /etc/ld.so.conf . Recent systems allow this file to include other files; if yours contains something like include /etc/ld.so.conf.d/*.conf , create a new file called /etc/ld.so.conf.d/mala.conf containing the directories you want to add. After you change /etc/ld.so.conf or an included file, run /sbin/ldconfig for your changes to take effect (this updates a cache).

( LD_LIBRARY_PATH also applies to many other unices, including FreeBSD, NetBSD, OpenBSD, Solaris and Tru64. HP-UX has SHLIB_PATH and Mac OS X has DYLD_LIBRARY_PATH . /etc/ld.so.conf has analogs on most unices but the location and syntax differs more widely.)

Источник

Can’t find .so in the same directory as the executable?

I have an executable which needs to link with libtest.so dynamically,so I put them in the same directory,then :

error while loading shared libraries: libtest.so: cannot open shared object file: No such file or directory 

How can it be unable to find libtest.so which is already in the same directory as the executable itself?

9 Answers 9

The loader never checks the current directory for shared objects unless it is explicitly directed to via $LD_LIBRARY_PATH . See the ld.so(8) man page for more details.

Читайте также:  Be linux my friend

LD_LIBRARY_PATH is generally a poor choice in production. It is good for quick hacks, and things like helping uninstalled binaries find their shared libraries when running unit tests (think ./configure; make; make check). When building your binary, you can either put your library in a standard location (listed at /etc/ld.so.conf) or pass the -R flag to the linker to let the binary know where to look.

While you can set LD_LIBRARY_PATH to let the dynamic linker know where to look, there are better options. You can put your shared library in one of the standard places, see /etc/ld.so.conf (on Linux) and /usr/bin/crle (on Solaris) for the list of these places

You can pass -R to the linker when building your binary, which will add to the list of directories scanned for your shared library. Here’s an example. First, showing the problem:

#include void hello_world(void)
#include "libtest.h" int main(int argc, char **argv)

Makefile (tabs must be used):

all: hello hello: libtest.so.0 %.o: %.c $(CC) $(CFLAGS) -fPIC -c -o $@ $< libtest.so.0.0.1: libtest.o $(CC) -shared -Wl,-soname,libtest.so.0 -o libtest.so.0.0.1 libtest.o libtest.so.0: libtest.so.0.0.1 ln -s $< $@ clean: rm -f hello libtest.o hello.o libtest.so.0.0.1 libtest.so.0 
$ make cc -fPIC -c -o libtest.o libtest.c cc -shared -Wl,-soname,libtest.so.0 -o libtest.so.0.0.1 libtest.o ln -s libtest.so.0.0.1 libtest.so.0 cc hello.c libtest.so.0 -o hello $ ./hello ./hello: error while loading shared libraries: libtest.so.0: cannot open shared object file: No such file or directory 

How to fix it? Add -R to the linker flags (here, by setting LDFLAGS ).

$ make clean (. ) $ make LDFLAGS="-Wl,-R -Wl,/home/maciej/src/tmp" (. ) cc -Wl,-R -Wl,/home/maciej/src/tmp hello.c libtest.so.0 -o hello $ ./hello Hello world, I'm a library! 

Looking at the binary, you can see that it needs libtest.so.0 :

$ objdump -p hello | grep NEEDED NEEDED libtest.so.0 NEEDED libc.so.6 

The binary will look for its libraries, apart from the standard places, in the specified directory:

$ objdump -p hello | grep RPATH RPATH /home/maciej/src/tmp 

If you want the binary to look in the current directory, you can set the RPATH to $ORIGIN . This is a bit tricky, because you need to make sure that the dollar sign is not interpreted by make. Here's one way to do it:

$ make CFLAGS="-fPIC" LDFLAGS="-Wl,-rpath '-Wl,\$\$ORIGIN'" $ objdump -p hello | grep RPATH RPATH $ORIGIN $ ./hello Hello world, I'm a library! 

If not using make , such as when manually calling g++ , try -Wl,-rpath='$ORIGIN' (note the single quotes) to prevent $ORIGIN from expanding to an empty string.

Читайте также:  Linux ldap get user info

This info was very useful, thanks. Without it, I was resorting to launching an executable with a wrapping shell script LD_LIBRARY_PATH=. ./my-executable $@ whereas using the -rpath='.' is (still a workaround in my case, but) much cleaner.

I think I don't get it completly. First you are using -R and later -rpath to pass the additional search path to the linker. What's the difference?

The -R and -rpath options (on the ld command) are interchangeable with some caveats, see man ld for details.

To load the shared objects from the same directory as your executable, simply execute:

Note: It will not modify the LD_LIBRARY_PATH variable of your system. The change only affects to this, and only this, execution of your program.

For anyone using CMake for their build, you can set the CMAKE_EXE_LINKER_FLAGS to the following:

set(CMAKE_EXE_LINKER_FLAGS "$ -Wl,-rpath='$ORIGIN'") 

This will properly propagate the linker flags for all build types (e.g., Debug, Release, etc. ) to look for .so files in the current working directory first.

Hey, this is super useful. I can prepare a derivative library B using library A, redistribute library A with my library B, and be immune to library A variations on the user's system. Are there downsides to this approach?

Oh, and I seem to be able to do this with bazel's cc_library: linkopts = ["-Wl,-rpath '-Wl,$$ORIGIN'"] .

For anyone that still struggles without an answer I found one myself with the following suggestion:

You could try updating the ld.so.cache using: sudo ldconfig -v

It also solved problem for me, but I additionally looked at /etc/ld.so.conf for directories where the library files are searched, and placed my library to the first directory in the list (namely, /usr/local/lib/arm-linux-gnueabihf/). Then I executed this command and boom, the library is now found.

There can be subtle situations showing the same symptoms. I use to build a CMake project, both locally at /path/to/myproj and remotely on a server, at /path/to/myproj-deploy . Project contains an .so build artifact and multiple ELF files depending on that.

When I pulled back binaries from the build server, I found out that (locally) calling ELFs results in the same problems. Thanks to authomatthias, calling

$ objdump -p bin/myelf | grep my bin/myelf: file format elf64-x86-64 NEEDED libmyso.so RUNPATH /path/to/myproj-deploy/bin 

ends up in a non-surprising consequence: CMake system hardcoded remote path into the RUNPATH , demonstrating some non-portability (without proper additional actions, I suppose)

Читайте также:  Examples for linux commands

Источник

.so search paths

I am a Linux novice (coming from a Windows background). I'd like to understand the details of how shared objects (.so files) are loaded at runtime. According to http://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html the file /etc/ld.so.conf configures the directories to search for .so files at runtime. However an experiment shown below seems to indicate that isn't the case. /usr/local/lib is in one of the .conf files in /etc/ld.so.conf.d, but when my .so is in /usr/local/lib it is not found at run-time. Conversely /usr/lib is not configured by /etc/ld.so.conf, but when my .so is in /usr/lib it is found at runtime. What am I missing? Thanks, Dave

davids@ds-ub64-7:/$ # Display the .so search path configured in /etc/ld.so.conf davids@ds-ub64-7:/$ cat /etc/ld.so.conf include /etc/ld.so.conf.d/*.conf davids@ds-ub64-7:/$ cat /etc/ld.so.conf.d/*.conf /usr/lib/mesa /usr/lib32/mesa /usr/lib32/alsa-lib /usr/lib/alsa-lib # libc default configuration /usr/local/lib # Multiarch support /lib/x86_64-linux-gnu /usr/lib/x86_64-linux-gnu davids@ds-ub64-7:/$ # libsotest.so.1 is in /usr/local/lib davids@ds-ub64-7:/$ ls -la /usr/local/lib/libsotest* lrwxrwxrwx 1 root root 14 2012-07-19 08:24 /usr/local/lib/libsotest.so -> libsotest.so.1 lrwxrwxrwx 1 root root 18 2012-07-19 08:24 /usr/local/lib/libsotest.so.1 -> libsotest.so.1.0.1 -rwxr-xr-x 1 davids davids 7952 2012-07-19 08:13 /usr/local/lib/libsotest.so.1.0.1 davids@ds-ub64-7:/$ # But when I run an executable that refrs to libsotest.so.1, the loader doesn't find it. davids@ds-ub64-7:/$ /projects/sotest/exe/sotestexe /projects/sotest/exe/sotestexe: error while loading shared libraries: libsotest.so.1: cannot open shared object file: No such file or directory davids@ds-ub64-7:/$ # Configure loader to display the paths it's searching. it's searching /usr/lib but not /usr/local/lib davids@ds-ub64-7:/$ export LD_DEBUG=lib davids@ds-ub64-7:/$ /projects/sotest/exe/sotestexe warning: debug option `lib' unknown; try LD_DEBUG=help /projects/sotest/exe/sotestexe: error while loading shared libraries: libsotest.so.1: cannot open shared object file: No such file or directory davids@ds-ub64-7:/$ export LD_DEBUG=libs davids@ds-ub64-7:/$ /projects/sotest/exe/sotestexe 6691: find library=libsotest.so.1 [0]; searching 6691: search cache=/etc/ld.so.cache 6691: search path=/lib/tls/x86_64:/lib/tls:/lib/x86_64:/lib:/usr/lib/tls/x86_64:/usr/lib/tls:/usr/lib/x86_64:/usr/ lib:/lib/x86_64-linux-gnu/tls/x86_64:/lib/x86_64-linux-gnu/tls:/lib/x86_64-linux- gnu/x86_64:/lib/x86_64-linux-gnu:/usr/lib/x86_64-linux-gnu/tls/x86_64:/usr/lib/x86_64-linux- gnu/tls:/usr/lib/x86_64-linux-gnu/x86_64:/usr/lib/x86_64-linux-gnu (system search path) 6691: trying file=/lib/tls/x86_64/libsotest.so.1 6691: trying file=/lib/tls/libsotest.so.1 6691: trying file=/lib/x86_64/libsotest.so.1 6691: trying file=/lib/libsotest.so.1 6691: trying file=/usr/lib/tls/x86_64/libsotest.so.1 6691: trying file=/usr/lib/tls/libsotest.so.1 6691: trying file=/usr/lib/x86_64/libsotest.so.1 6691: trying file=/usr/lib/libsotest.so.1 6691: trying file=/lib/x86_64-linux-gnu/tls/x86_64/libsotest.so.1 6691: trying file=/lib/x86_64-linux-gnu/tls/libsotest.so.1 6691: trying file=/lib/x86_64-linux-gnu/x86_64/libsotest.so.1 6691: trying file=/lib/x86_64-linux-gnu/libsotest.so.1 6691: trying file=/usr/lib/x86_64-linux-gnu/tls/x86_64/libsotest.so.1 6691: trying file=/usr/lib/x86_64-linux-gnu/tls/libsotest.so.1 6691: trying file=/usr/lib/x86_64-linux-gnu/x86_64/libsotest.so.1 6691: trying file=/usr/lib/x86_64-linux-gnu/libsotest.so.1 6691: /projects/sotest/exe/sotestexe: error while loading shared libraries: libsotest.so.1: cannot open shared object file: No such file or directory davids@ds-ub64-7:/$ 

Источник

Оцените статью
Adblock
detector