views:

3933

answers:

5

I have some code that uses some shared libraries (c code on gcc). When compiling I have to explicitly define the include and library directories using -I and -L, since they aren't in the standard places. When I try to run the code, I get the following error:

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

However, do the following, everything works just fine:

export LD_LIBRARY_PATH="/path/to/library/"
./sync_test

Now, the strange part is, this only works once. If I try and run sync_test again I get the same error unless I run the export command first. I tried adding the following to my .bashrc, but it made no difference:

LD_LIBRARY_PATH="/path/to/library/"
+4  A: 

Did you 'export' in your .bashrc?

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:"/path/to/library"
bedwyr
+7  A: 

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.

doh! I should have known that. Much thanks.
Paul Wicks
Use `-Wl,-rpath` (if passing to `cc`) or `-rpath` (if passing to `ld`) as more portable than `-R`.
ephemient
+3  A: 

You can just put this all on one line:

LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/path/to/library" ./sync_test

Should make things a little easier, even if it doesn't change anything fundamental

This syntax is wonderful... especially if some of your program behavior is based on transient environment variables, such as TMP or TMPDIR
Tom
+4  A: 

You should avoid setting LD_LIBRARY_PATH in your .bashrc. See "Why LD_LIBRARY_PATH is bad" for more information.

Use the linker option -rpath while linking so that the dynamic linker knows where to find libsync.so during runtime.

gcc ... -Wl,-rpath /path/to/library -L/path/to/library -lsync -o sync_test

EDIT:

Another way would be to use a wrapper like this

#!/bin/bash

LD_LIBRARY_PATH=/path/to/library sync_test "$@"

If sync_test starts any other programs, they might end up using the libs in /path/to/library which may or may not be intended.

sigjuice
That really doesn't help if you move the application to someone else's machine and they don't want to put the library in the same /path/to that you expected at link time. While -rpath is certainly useful for sysadmins and distro providers, I believe it's presumptuous for an individual to set this.
Tom
Although, your first statement "avoid setting LD_LIBRARY_PATH in your .bashrc" I agree with 100%. A middle-ground solution that I have used is a bash script $HOME/bin/myprogram that sets the local LD_LIBRARY_PATH and then runs /path/to/real/myprogram.
Tom
You are right. One cannot assume where someone wants their libs. In case there is a fixed relation between bin/ and lib/, something like -rpath $ORIGIN/../lib might be more appropriate. There is a also a program that can change the rpath in ELF executables called chrpath.
sigjuice
I agree with the use of a wrapper shell script. I will update my answer.
sigjuice
Thanks for the tip. None of the things mentioned in the article are really issues in my case (this code is only ever going to be run on one machine by me), but I'll definitely keep them in mind if I ever run into a similar problem.
Paul Wicks
+1  A: 

What you also can do, if it's something you installed on your system, is to add the directory that contains the shared libraries to your /etc/ld.so.conf file, or make a new file in /etc/ld.so.conf.d/

(I've both checked RHEL5 and Ubuntu distribution so I think it's generic for linux)

The ldconfig program will make sure they are system-wide included.

See the following link for more information: www.dwheeler.com/secure-programs/Secure-Programs-HOWTO/dlls.html

Roalt