2

I'm trying to get a C application to load shared objects from a relative directory regardless of where I call it from. So far it only works if I'm in the same directory as the executable when I call it:

~/prog$ ./my_program
Success
~/prog$ cd ..
~$ ./prog/my_program
./prog/my_program: error while loading shared libraries: libs/libmysharedobject.so: cannot open shared object file: No such file or directory

As you can guess from the output above, the shared object is stored under the ~/prog/libs/ directory. Here's what the relevant gcc calls look like:

gcc -std=c99 -ggdb -Wall -pedantic -Isrc
    -fPIC -shared -Wl,-soname,libs/libmysharedogbject.so
    -o libs/libmysharedobject.so libs/mysharedobject.c
[...]
gcc [CFLAGS omitted] -o my_program main.c
    build/src/my_program.o build/src/common.o
    -lm -Llibs -lmysharedobject

Here's the top of the output from readelf -d my_program:

Dynamic section at offset 0x6660 contains 26 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libm.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [libs/libmysharedobject.so]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]

I have tried adding -Wl,-z,origin,-rpath='$ORIGIN', which causes the following lines to show up in readelf's output:

 0x000000000000000f (RPATH)              Library rpath: [$ORIGIN]
[...]
 0x000000006ffffffb (FLAGS_1)            Flags: ORIGIN

But it doesn't seem to solve my problem. I've also tried setting rpath to $ORIGIN/libs, ., and ./libs, all to no avail. (UPDATE: $(CURDIR) doesn't have any effect either. This surprises me, since it's expanded to an absolute path.)

Is there a way to get my executable to find its shared objects regardless of the directory from which it's invoked, preferably without having the end user set LD_LIBRARY_PATH every time? Or am I trying to do something that Linux doesn't support?

  • You could just export LD_LIBRARY_PATH and then run whatever calls you need. – HalosGhost Jun 16 '14 at 23:32
  • That's precisely what I'm trying to avoid. I'll edit my post to clarify. – Fraxtil Jun 16 '14 at 23:36
  • Then libtool may also be of interest to you. – HalosGhost Jun 16 '14 at 23:38
  • If altering the source is an option, you could use dlopen() and load the libraries at the top of main(). – Patrick Jun 18 '14 at 3:05
3

Set rpath to $ORIGIN/libs and set soname to libsharedobject rather than libs/libsharedobject. My makefile is as follows.

all: my_program

libs/libmysharedobject.so: Makefile success.c
  gcc -fPIC -shared -Wl,-soname,libmysharedobject.so \
    -o libs/libmysharedobject.so success.c

my_program: Makefile libs/libmysharedobject.so
  gcc -o my_program main.c -Llibs -lmysharedobject -Wl,-R,'$$ORIGIN/libs'

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.