26

I've got a binary "CeeloPartyServer" that needs to find libFoundation.so at runtime, on a FreeBSD machine. They're both in the same directory. I compile (on another platform, using a cross compiler) CeeloPartyServer using linker flag -rpath=$ORIGIN.

> readelf -d CeeloPartyServer |grep -i rpath
 0x0000000f (RPATH)                      Library rpath: [$ORIGIN]
> ls
CeeloPartyServer    Contents        Foundation.framework    libFoundation.so
> ./CeeloPartyServer 
/libexec/ld-elf.so.1: Shared object "libFoundation.so" not found, required by "CeeloPartyServer"

Why isn't it finding the library when I try to run it?

My exact linker line is: -lm -lmysql -rpath=$ORIGIN.

I am pretty sure I don't have to escape $ or anything like that since my readelf analysis does in fact show that library rpath is set to $ORIGIN. What am I missing?

umläute
  • 28,885
  • 9
  • 68
  • 122
Nektarios
  • 10,173
  • 8
  • 63
  • 93
  • Also see [A description of RPATH $ORIGIN LD_LIBRARY_PATH and portable linux binaries](https://enchildfone.wordpress.com/2010/03/23/a-description-of-rpath-origin-ld_library_path-and-portable-linux-binaries/). The article uses `XORIGIN/../lib` to reserve space in the header, and then uses `chrpath` to change to `$ORIGIN/../lib` to avoid quoting problems. You may also want `-Wl,--enable-new-dtags`. – jww Oct 19 '18 at 02:42

4 Answers4

44

I'm assuming you are using gcc and binutils.

If you do

readelf -d CeeloPartyServer | grep ORIGIN

You should get back the RPATH line you found above, but you should also see some entries about flags. The following is from a library that I built.

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

If you aren't seeing some sort of FLAGS entries, you probably haven't told the linker to mark the object as requiring origin processing. With binutils ld, you do this by passing the -z origin flag.

I'm guessing you are using gcc to drive the link though, so in that case you will need to pass flag through the compiler by adding -Wl,-z,origin to your gcc link line.

acm
  • 12,183
  • 5
  • 39
  • 68
  • 1
    All your assumptions are correct. I'm not using the -z origin flag, never saw that documented anywhere. Will let you know if that resolves it. – Nektarios Jun 13 '11 at 15:53
  • 1
    From some brief experiments, that flag seems unnecessary: I have a binary here that definitely needs an rpath to work, the rpath starts with `$ORIGIN`, the flag is not set, and yet it works. – Ralf Jung Feb 12 '19 at 14:01
  • How will I do this using cmake in install step? Setting INSTALL_RPATH property to $ORIGIN does only a half of the job. – Mariusz Jaskółka Jan 10 '20 at 16:21
  • [Apparently ld ignores the origin flag when reading/processing your library](https://stackoverflow.com/questions/33853344/what-are-the-recommended-gnu-linker-options-to-specify-origin-in-rpath), though some BSD flavours apparently require it – rcoup May 25 '20 at 11:25
17

Depending on how many layers this flag passes through before the linker sees it, you may need to use $$ORIGIN or even \$$ORIGIN. You will know that you have it right when readelf shows an RPATH header that looks like $ORIGIN/../lib or similar. The extra $ and the backslash are just to prevent the $ from being processed by other tools in the chain.

Michael Dillon
  • 31,973
  • 6
  • 70
  • 106
  • 5
    Just to clarify for others (such as myself) who are less familiar with RPATH: When setting RPATH during compilation, try `LDFLAGS="-Wl,-rpath,'\$\$ORIGIN' -Wl,-z,origin"`; where `echo $LDFLAGS` will give: `-Wl,-rpath,'$$ORIGIN' -Wl,-z,origin`. (There is some Makefile magic with `$$`.) – kevinarpe Jun 12 '15 at 09:56
  • \$$ORIGIN worked for me when compiling Python 3. \$\$ORIGIN did not work and resulted in "RIGIN/../lib" as the RPATH. – nicktalbot Apr 06 '20 at 13:07
3

\$\ORIGIN if you are using chrpath and \$\$ORIGIN if you are providing directly in LDFLAGS

0
  1. using ldd CeeloPartyServer to check the dependency .so is starting with ./ or not. (e.g. libFoundation.so and ./libFoundation.so)
    For common situation it should be libFoundation.so and without the prefix ./

  2. if ./ prefix is necessary for some uncommon case, make sure the CWD is the same folder with libFoundation.so, and the $ORIGIN would be invalid.

=======
For example:
g++ --shared -Wl,--rpath="\$ORIGIN" ./libFoundation.so -o lib2.so would got a library lib2.so with ./libFoundation.so
g++ --shared -Wl,--rpath="\$ORIGIN" libFoundation.so -o lib2.so would got libFoundation.so instead.

vrqq
  • 448
  • 3
  • 8