views:

479

answers:

2

Hi,

I have an application that is broken into several libraries for purposes of code reuse. On Windows all I have to do is put the .dll files in the same path as the executable and it automatically finds them. On Linux (since it hardcodes the paths to things) I have to specify the environmental variable LD_LIBRARY_PATH or preload the libraries before the executable.

I've seen some things about embedding the path using the linker option of -Wl,-rpath=<PATH> and I've tried it using . as the path. But that just looks in the current working directory, not the executable's directory.

Is there a way to specify in the linker to look in the directory of the executable for the shared libraries by default (like on Windows)?

Thanks! Matt

+8  A: 

You need $ORIGIN. See this and this.

Remember that the $ has to really end up in the path, so you need to quote or escape it in the link command line.

Update: You can see what the linker actually put into your executable with

readelf -d /path/to/exe | grep RPATH

Here is what the output should look like:

 0x0000000f (RPATH)              Library rpath: [$ORIGIN]
bmargulies
When using $ORIGIN, you need to make sure the $ is properly quoted so that the linker actually sees it. From the command line, you want "-rpath \$ORIGIN" and from a Makefile you want "-rpath \$$ORIGIN"
R Samuel Klatchko
I'm using Eclipse and CDT, and I'm putting the option under the miscellaneous linker flags. I'm putting `-Wl,-rpath=$$ORIGIN` and in the output window it shows it with a single $. But it doesn't seem to work. I've tried several variations, but nothing happens. It's like the linker just ignores the flag. I've tried:-Wl,-rpath=$ORIGIN-Wl,--rpath=$ORIGIN-Wl,-rpath=/$ORIGIN-Wl,-rpath=$ORIGIN/-Wl,-rpath=/$ORIGIN/etc.
CuppM
Use elfdump or the local equivalent to see what's in there? Use ldd and see what it says?
bmargulies
How about `-rpath \$$ORIGIN` as mentioned above?
John Zwinck
That did it, I just wasn't properly escaping the $ characters. Being able to check it with readelf helped to make sure I got parameter string right. The flag string that worked in Eclipse is `-Wl,-rpath=\$$ORIGIN`.
CuppM
+2  A: 

Wrap your program in a shell script:

#!/bin/sh

PROGRAM_DIRECTORY="`dirname "$0"`"
export LD_LIBRARY_PATH="$PROGRAM_DIRECTORY"

"$PROGRAM_DIRECTORY/program_executable" "$@"

If you run this script (instead of your executable) your program will link just fine.

Pavel Shved
Yeah, that's what I've been doing and it works. The application has a parallelized version using OpenMPI, and that has a way of sharing the LD_LIBRARY_PATH. So we're currently using that workaround, but we would like an easier way of doing things because the application (as well as the MPI runner) takes multiple flags for what to process
CuppM
You can pass all arguments from your script onto the program with `"$@"`.
Roger Pate