Reputation: 791
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
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 soname
s 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
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
Reputation: 136505
The are alternative ways to fix your issue:
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.
If you are using LD_LIBRARY_PATH
do not forget to export it.
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