当使用gcc链接指定路径中的共享库但未在标准路径中链接时,我遇到了一个奇怪的问题。
当我下载GNU readline library version 6.3并在路径 $ HOME / Downloads 中成功编译时。
GNU readline库需要链接 libtinfo ,所以我按sudo apt-get install libtinfo
安装了它。
之后,我创建了一个名为 rl.c 的小样本测试来检查它。为了构建我的示例项目,我还创建了两个符号链接,如:
$ 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
要使用新构建的readline库,我将路径导出到 LD_LIBRARY_PATH :
$ echo $LD_LIBRARY_PATH
/home/sfzhang/Downloads/readline/shlib
然后,我使用以下命令编译 rl.c :
$ gcc -o rl rl.c -I$HOME/Downloads -L$HOME/Downloads/readline/shlib -lreadline -ltinfo
检查 rl 链接库:
$ 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)
我也尝试过anther命令,但结果相同:
gcc -o rl rl.c -I$HOME/Downloads -L$HOME/Downloads/readline/shlib -lreadline -ltinfo -Wl,-rpath,$HOME/Downloads/readline/shlib
那么,为什么 /ll 喜欢 /lib/x86_64-linux-gnu/libreadline.so.6 ,而不是 $ 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 4.7.2版(Debian 4.7.2-5)
ldd:ldd(Debian EGLIBC 2.13-38 + deb7u6)2.13
答案 0 :(得分:3)
您还需要一个名为libreadline.so.6
的符号链接,而不仅仅是libreadline.so
。原因是soname
的{{1}}为libreadline.so.6.3
。
libreadline.so.6
是"泛型"嵌入在库本身中的名称。当您链接到具有soname
的共享库时,该名称将嵌入您的可执行文件中,稍后由动态链接程序查找。 (对于没有soname
的共享库,会使用文件名,但这种情况并不常见。)您可以通过运行来判断库的sonames
是什么。
soname
objdump -p <library> | grep SONAME
s的目的是使您的可执行文件链接到应该兼容的最通用的库名称(通常这是只有主要版本的库名称 - 在这种情况下为6 - 加上),而不仅仅是您碰巧链接的特定(例如,小错误修复版本)版本。
soname
的输出也告诉您它专门针对ldd
。
答案 1 :(得分:1)
如果您真的想要在可执行文件中硬编码库的路径,则需要将以下内容传递给gcc:
-Wl,-rpath=$HOME/Downloads/readline/shlib
不建议设置自定义LD_LIBRARY_PATH,如果要使用它,请将其用作执行参数。
LD_LIBRARY_PATH=$HOME/Downloads/readline/shlib ./rc
答案 2 :(得分:0)
这是解决问题的替代方法:
链接到.so
的完整路径。 E.g。
$ gcc -o rl rl.c -I$HOME/Downloads $HOME/Downloads/readline/shlib/readline.so.6.3 -ltinfo
正如@Ulfalizer建议的那样,您可能需要另一个只包含主要数字的符号链接。
如果您使用的是LD_LIBRARY_PATH
,请不要忘记将其导出。
使用-L<path>
时也使用-Wl,-rpath,<path>
,以便运行时链接程序ld.so.2
在与ld
相同的路径中找到共享库,例如:
$ gcc -o rl rl.c -I$HOME/Downloads -L$HOME/Downloads/readline/shlib -Wl,-rpath,$HOME/Downloads/readline/shlib -lreadline -ltinfo
调试链接器问题时,使用readelf -d <binary>
命令查看共享库<binary>
需要哪些确切版本(NEEDED属性)以及在查找标准链接器目录之前查找它们的位置(RPATH属性) (在/etc/ld.so.conf /)中配置。