Linking against shared objects that reside at different paths on link-time versus runtime?
Jonathan Wakely
jwakely.gcc@gmail.com
Mon Jun 27 22:14:00 GMT 2011
$ cat bar.cc
#include <stdio.h>
void bar()
{
printf("Hello, World!\n");
}
$ g++ -shared -fPIC bar.cc -o lib/libbar.so
$ ls lib/libbar.so
lib/libbar.so
$ readelf -d lib/libbar.so | fgrep SONAME
$
i.e. I've created libbar.so without a soname.
Now...
$ cat foo.cc
void bar();
int main()
{
bar();
}
This will fail to link:
$ g++ foo.cc
/tmp/ccYDIRqA.o: In function `main':
foo.cc:(.text+0x5): undefined reference to `bar()'
collect2: ld returned 1 exit status
linking to libbar.so works:
$ g++ foo.cc lib/libbar.so
But because libbar.so has no soname, the executable's dependency is on
the filename used to link:
$ ldd a.out
lib/libbar.so => not found
...
(It's not found because it's not in the runtime linker's search path,
ignore that for now)
Using -L and -l gets around that:
$ g++ foo.cc -Llib -lbar
$ ldd a.out
libbar.so => not found
...
Now the dependency is just on the filename, not the full path used.
Another way to get the same effect is using a soname in the library:
$ g++ -shared -fPIC bar.cc -o lib/libbar.so -Wl,-soname=libbar.so
$ readelf -d lib/libbar.so | fgrep SONAME
0x000000000000000e (SONAME) Library soname: [libbar.so]
$ g++ foo.cc lib/libbar.so
$ ldd a.out
libbar.so => not found
...
The dependency is on the soname "libbar.so" even though I linked to
"lib/libbar.so"
Just to demonstrate how the soname is used:
$ g++ -shared -fPIC bar.cc -o lib/libxxx.so -Wl,-soname=libyyy.so
$ ls lib
libbar.so libxxx.so
$ readelf -d lib/libxxx.so | fgrep SONAME
0x000000000000000e (SONAME) Library soname: [libyyy.so]
$ g++ foo.cc -Llib -lxxx
$ ldd a.out
libyyy.so => not found
...
Here the soname is completely different to the filename, and even
though the executable is linked to lib/libxxx.so it has a dependency
on libyyy.so
To ensure the library can be found at runtime, use LD_LIBRARY_PATH, or
better use RPATH:
$ g++ foo.cc -Llib -lbar -Wl,-rpath,'$ORIGIN/lib'
$ readelf -d a.out | fgrep RPATH
0x000000000000000f (RPATH) Library rpath: [$ORIGIN/lib]
$
$ ldd ./a.out
libbar.so => /tmp/lib/libbar.so (0x00002aefafb5d000)
...
$ ln -s lib/libxxx.so ./libyyy.so
$
$ g++ foo.cc -Llib -lxxx -Wl,-rpath,'$ORIGIN'
$ ldd ./a.out
libyyy.so => /tmp/libyyy.so (0x00002b7a1e1a0000)
...
You should be able to figure out what you need to know by modifying
these examples.
More information about the Gcc-help
mailing list