gcc link 共享库在指定路径但不在标准路径
gcc link the shared library in specified path but not in the standard path
我在使用 gcc link 指定路径但不在标准路径中的共享库时遇到了一个奇怪的问题。
当我下载GNU readline library version 6.3并在路径$HOME/Downloads.
编译成功
GNU readline 库需要 link libtinfo,所以我通过 sudo apt-get install libtinfo
.
安装了它
之后,我创建了一个名为rl.c的小样本测试来检查它。为了构建示例项目,我还创建了两个符号 links,如下所示:
$ 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 linked 库:
$ 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)
我也尝试了另一个命令,但得到了相同的结果:
gcc -o rl rl.c -I$HOME/Downloads -L$HOME/Downloads/readline/shlib -lreadline -ltinfo -Wl,-rpath,$HOME/Downloads/readline/shlib
所以,为什么 rl 被喜欢 /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
您还需要一个名为 libreadline.so.6
的符号 link,而不仅仅是 libreadline.so
。原因是libreadline.so.6.3
的soname
是libreadline.so.6
.
A soname
是嵌入在库本身中的 "generic" 名称。当您 link 针对具有 soname
的共享库时,它是嵌入到您的可执行文件中并随后由动态 linker 查找的名称。 (对于没有 sonames
的共享库,使用文件名代替,尽管这并不常见。)您可以通过 运行 来判断库的 soname
是什么,例如
objdump -p <library> | grep SONAME
soname
s 的目的是使您的可执行文件 link 与应该兼容的最通用的库名称(通常是仅带有 主要版本 -- 在这种情况下为 6 -- 添加),而不仅仅是您碰巧 link 反对的特定(例如,小错误修复版本)版本。
ldd
的输出还告诉您它正在专门寻找 libreadline.so.6
。
解决问题的替代方法有:
Link 反对 .so
的完整路径。例如
$ gcc -o rl rl.c -I$HOME/Downloads $HOME/Downloads/readline/shlib/readline.so.6.3 -ltinfo
正如@Ulfalizer 所建议的,您可能需要另一个仅包含主要编号的符号 link。
如果您正在使用 LD_LIBRARY_PATH
,请不要忘记将其导出。
在使用-L<path>
时也使用-Wl,-rpath,<path>
,这样运行时linker ld.so.2
在与[=相同的路径下找到共享库17=] 确实如此,例如:
$ gcc -o rl rl.c -I$HOME/Downloads -L$HOME/Downloads/readline/shlib -Wl,-rpath,$HOME/Downloads/readline/shlib -lreadline -ltinfo
在调试 linker 问题时,使用 readelf -d <binary>
命令查看共享库 <binary>
需要的确切版本(NEEDED 属性)以及在何处查找它们(RPATH 属性)查看标准 linker 目录(/etc/ld.so.conf/ 中的配置)。
如果您确实希望将库的路径硬编码到可执行文件中,则需要将以下内容传递给 gcc:
-Wl,-rpath=$HOME/Downloads/readline/shlib
不推荐设置自定义LD_LIBRARY_PATH,如果要使用,将其作为参数执行即可。
LD_LIBRARY_PATH=$HOME/Downloads/readline/shlib ./rc
我在使用 gcc link 指定路径但不在标准路径中的共享库时遇到了一个奇怪的问题。
当我下载GNU readline library version 6.3并在路径$HOME/Downloads.
编译成功GNU readline 库需要 link libtinfo,所以我通过 sudo apt-get install libtinfo
.
之后,我创建了一个名为rl.c的小样本测试来检查它。为了构建示例项目,我还创建了两个符号 links,如下所示:
$ 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 linked 库:
$ 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)
我也尝试了另一个命令,但得到了相同的结果:
gcc -o rl rl.c -I$HOME/Downloads -L$HOME/Downloads/readline/shlib -lreadline -ltinfo -Wl,-rpath,$HOME/Downloads/readline/shlib
所以,为什么 rl 被喜欢 /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
您还需要一个名为 libreadline.so.6
的符号 link,而不仅仅是 libreadline.so
。原因是libreadline.so.6.3
的soname
是libreadline.so.6
.
A soname
是嵌入在库本身中的 "generic" 名称。当您 link 针对具有 soname
的共享库时,它是嵌入到您的可执行文件中并随后由动态 linker 查找的名称。 (对于没有 sonames
的共享库,使用文件名代替,尽管这并不常见。)您可以通过 运行 来判断库的 soname
是什么,例如
objdump -p <library> | grep SONAME
soname
s 的目的是使您的可执行文件 link 与应该兼容的最通用的库名称(通常是仅带有 主要版本 -- 在这种情况下为 6 -- 添加),而不仅仅是您碰巧 link 反对的特定(例如,小错误修复版本)版本。
ldd
的输出还告诉您它正在专门寻找 libreadline.so.6
。
解决问题的替代方法有:
Link 反对
.so
的完整路径。例如$ gcc -o rl rl.c -I$HOME/Downloads $HOME/Downloads/readline/shlib/readline.so.6.3 -ltinfo
正如@Ulfalizer 所建议的,您可能需要另一个仅包含主要编号的符号 link。
如果您正在使用
LD_LIBRARY_PATH
,请不要忘记将其导出。在使用
-L<path>
时也使用-Wl,-rpath,<path>
,这样运行时linkerld.so.2
在与[=相同的路径下找到共享库17=] 确实如此,例如:$ gcc -o rl rl.c -I$HOME/Downloads -L$HOME/Downloads/readline/shlib -Wl,-rpath,$HOME/Downloads/readline/shlib -lreadline -ltinfo
在调试 linker 问题时,使用 readelf -d <binary>
命令查看共享库 <binary>
需要的确切版本(NEEDED 属性)以及在何处查找它们(RPATH 属性)查看标准 linker 目录(/etc/ld.so.conf/ 中的配置)。
如果您确实希望将库的路径硬编码到可执行文件中,则需要将以下内容传递给 gcc:
-Wl,-rpath=$HOME/Downloads/readline/shlib
不推荐设置自定义LD_LIBRARY_PATH,如果要使用,将其作为参数执行即可。
LD_LIBRARY_PATH=$HOME/Downloads/readline/shlib ./rc