Re: Linking against shared objects that reside at different paths on link-time versus runtime?

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



$ 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.


[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux