sfzhang
sfzhang

Reputation: 791

gcc link the shared library in specified path but not in the standard path

I came across a strange issue when using gcc to link the shared library in specified path but not in the standard path.

When I downloaded GNU readline library version 6.3 and compiled it successfully in path $HOME/Downloads.

GNU readline library needs to link libtinfo, so I installed it by sudo apt-get install libtinfo.

After that, I created a small sample test named rl.c to check it. To build my sample project, I also created two symbolic links like follow:

$ ls -lrt ~/Downloads/
drwxr-xr-x 6 sfzhang sfzhang    4096 Mar  2 15:45 readline-6.3
lrwxrwxrwx 1 sfzhang sfzhang      12 Mar  2 16:00 readline -> readline-6.3

$ ls -lrt ~/Downloads/readline-6.3/shlib/
-rwxr-xr-x 1 sfzhang sfzhang 833856 Mar  2 15:36 libreadline.so.6.3
lrwxrwxrwx 1 sfzhang sfzhang     18 Mar  2 16:28 libreadline.so -> libreadline.so.6.3

To use the new built readline library, I export the path to LD_LIBRARY_PATH:

$ echo $LD_LIBRARY_PATH
/home/sfzhang/Downloads/readline/shlib

And, I compiled rl.c using the following command:

$ gcc -o rl rl.c -I$HOME/Downloads -L$HOME/Downloads/readline/shlib -lreadline -ltinfo

Checking the rl linked libraries:

$ ldd rl
linux-vdso.so.1 =>  (0x00007fffe09a3000)
libreadline.so.6 => /lib/x86_64-linux-gnu/libreadline.so.6 (0x00007fe22d243000)
libtinfo.so.5 => /lib/x86_64-linux-gnu/libtinfo.so.5 (0x00007fe22d01a000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fe22cc8d000)
/lib64/ld-linux-x86-64.so.2 (0x00007fe22d492000)

I also tried anther command, but got the same result:

gcc -o rl rl.c -I$HOME/Downloads -L$HOME/Downloads/readline/shlib -lreadline -ltinfo -Wl,-rpath,$HOME/Downloads/readline/shlib

So, why the rl was liked to /lib/x86_64-linux-gnu/libreadline.so.6 but not $HOME/Downloads/readline/shlib/libreadline.so.

OS: Linux debian 3.2.0-4-amd64 #1 SMP Debian 3.2.65-1+deb7u1 x86_64 GNU/Linux

gcc: gcc version 4.7.2 (Debian 4.7.2-5)

ldd: ldd (Debian EGLIBC 2.13-38+deb7u6) 2.13

Upvotes: 2

Views: 5401

Answers (3)

Ulfalizer
Ulfalizer

Reputation: 4762

You need a symbolic link called libreadline.so.6 too, not just libreadline.so. The reason is that the soname of libreadline.so.6.3 is libreadline.so.6.

A soname is a "generic" name embedded in the library itself. When you link against a shared library that has a soname, it is that name that gets embedded in your executable and is later looked up by the dynamic linker. (For shared libraries without sonames the filename is used instead, though this is uncommon.) You can tell what the soname of a library is by running e.g.

objdump -p <library> | grep SONAME

The point of sonames is to make it so that your executable is linked against the most generic library name that should be compatible (usually this is the library name with just the major version -- 6 in this case -- tacked on), rather than just the specific (e.g., minor bug fix release) version that you happened to link against.

The output from ldd also tells you that it's looking specifically for libreadline.so.6.

Upvotes: 4

Maria Samokhina
Maria Samokhina

Reputation: 139

If you really want a path to a library to be hardcoded in the executable, you will need to pass the following to gcc:

-Wl,-rpath=$HOME/Downloads/readline/shlib

setting custom LD_LIBRARY_PATH is not recommended, if you want to use it, use it as a parameter for execution.

LD_LIBRARY_PATH=$HOME/Downloads/readline/shlib ./rc

Upvotes: 2

Maxim Egorushkin
Maxim Egorushkin

Reputation: 136505

The are alternative ways to fix your issue:

  1. Link against full path to the .so. E.g.

    $ gcc -o rl rl.c -I$HOME/Downloads $HOME/Downloads/readline/shlib/readline.so.6.3 -ltinfo
    

    And as @Ulfalizer suggests, you may need another symbolic link with just the major number.

  2. If you are using LD_LIBRARY_PATH do not forget to export it.

  3. When using -L<path> also use -Wl,-rpath,<path>, so that runtime linker ld.so.2 finds the shared library in the same path as ld does, e.g:

    $ gcc -o rl rl.c -I$HOME/Downloads -L$HOME/Downloads/readline/shlib -Wl,-rpath,$HOME/Downloads/readline/shlib -lreadline -ltinfo
    

When debugging linker issues use readelf -d <binary> command to see which exact versions of shared libraries <binary> needs (NEEDED attribute) and where it looks for them (RPATH attribute) prior to looking in the standard linker directories (configuration in /etc/ld.so.conf/).

Upvotes: 0

Related Questions