首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么--在构建共享库时,rpath被取代?

问为什么--在构建共享库时,rpath被取代?
EN

Stack Overflow用户
提问于 2018-05-31 15:35:32
回答 2查看 1.2K关注 0票数 0

我正在CentOS机器上工作。我有一个文件(test.c),正在编译成一个共享库。

test.c

代码语言:javascript
复制
#include <stdio.h>
#include <stdlib.h>
#include <quadmath.h>
int my_func(void){
    __float128 r;
    r = strtoflt128 ("1.2345678", NULL);
    int * b = malloc(sizeof(int) * 5);
    double a = 10*M_PI_2q;
    printf("Hello world  %f\n",a);
    return 0;
}

要编译它:

代码语言:javascript
复制
$ gcc -c -fPIC test.c -o test.o
$ gcc -shared -Wl,--verbose -Wl,-soname,poo.so -Wl,-rpath,/opt/gcc/5.5.0/lib/ -o poo.so test.o -lquadmath
$ echo $LD_LIBRARY_PATH   ### This shouldn't matter?
    /opt/gcc/5.5.0/lib

从ld的详细输出来看,似乎找到了/opt/gcc/5.5.0/lib64/libquadmath.so.0 (这正是我想要的)。也就是说。

代码语言:javascript
复制
.
.
.
attempt to open /opt/gcc/5.5.0/bin/../lib/gcc/x86_64-unknown-linux-gnu/5.5.0/libquadmath.so failed
attempt to open /opt/gcc/5.5.0/bin/../lib/gcc/x86_64-unknown-linux-gnu/5.5.0/libquadmath.a failed
attempt to open /opt/gcc/5.5.0/bin/../lib/gcc/libquadmath.so failed
attempt to open /opt/gcc/5.5.0/bin/../lib/gcc/libquadmath.a failed
attempt to open /opt/gcc/5.5.0/bin/../lib/gcc/x86_64-unknown-linux-gnu/5.5.0/../../../../lib64/libquadmath.so succeeded 
-lquadmath (/opt/gcc/5.5.0/bin/../lib/gcc/x86_64-unknown-linux-gnu/5.5.0/../../../../lib64/libquadmath.so)
 .
 .
 .

但是,当我使用ldd poo.so时,它没有正确的库。也就是说。

代码语言:javascript
复制
$ ldd poo.so 
    linux-vdso.so.1 =>  (0x00007fffc0e8e000)
    libquadmath.so.0 => /act/gcc-4.7.2/lib64/libquadmath.so.0 (0x00002aea8fd39000)
    libc.so.6 => /lib64/libc.so.6 (0x00002aea8ff6f000)
    libm.so.6 => /lib64/libm.so.6 (0x00002aea90303000)
    /lib64/ld-linux-x86-64.so.2 (0x00002aea8f8f2000)

我使用的是gcc版本5.5.0,并且希望poo.so链接到/opt/gcc/5.5.0/lib/libquadmath.so.0,而不是4.7.2版本。

我认为这与/etc/ld.so.conf中指定旧库位置的文件的存在有关。也就是说。

代码语言:javascript
复制
$ cat /etc/ld.so.conf.d/gcc-4.7.2.conf 
/act/gcc-4.7.2/lib64
/act/gcc-4.7.2/lib

ld的手册页(如我所询问的这里)不太有用。

linking :我在链接和构建共享库时指定了-rpath,但我不明白为什么它会找到老版本的gcc-4.7.2版本的四边形库。为什么链接器似乎对/etc/ld.so.conf中的路径进行优先排序而忽略了-rpath选项?如何在编译时指定库位置,以及如何解决这个问题?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-05-31 19:04:54

要理解解决办法,首先必须了解错误的思想。

  1. 我没有意识到有两个实用程序正在进行链接。有ld (在编译时使用)和ld.so (在运行时使用)。ld.so的手册页描述了如何在运行时找到库。总之,搜索: ( a) DT_RPATH中指定的目录 ( b) LD_LIBRARY_PATH中指定的目录 ( c)二进制的DT_RUNPATH动态部分中的目录(如果存在) ( d)缓存文件/etc/ld.so.cache ( e)默认路径/lib,然后是/usr/lib
  2. ld的手册页主要让我感到困惑。它在-rpath选项下写道: 将目录添加到运行时库搜索路径。这在将ELF可执行文件与共享对象链接时使用。

我认为在构建共享库时传递-rpath可以保证它可以在不需要设置LD_LIBRARY_PATH的情况下找到库。错误的。这个特性只在构建可执行(而不是共享库)时才有用。有一个-rpath-link选项,但我不知道如何使它工作。

您可以通过执行以下操作来看到这一点:

代码语言:javascript
复制
$ cat test2.c
#include <stdio.h>
#include <stdlib.h>
#include <quadmath.h>
int main(void){
    __float128 r;
    r = strtoflt128 ("1.2345678", NULL);
    int * b = malloc(sizeof(int) * 5); 
    double a = 10*M_PI_2q;
    printf("Hello world  %f\n",a);
    return 0;
}
$ export LD_LIBRARY_PATH=
$ which gcc 
/opt/gcc/5.5.0/bin/gcc
$ gcc -Wl,-rpath,/opt/gcc/5.5.0/lib64 test2.c -lquadmath
$ ldd a.out 
linux-vdso.so.1 =>  (0x00007fffff34f000)
libquadmath.so.0 => /opt/gcc/5.5.0/lib64/libquadmath.so.0 (0x00002b9c35e07000)
libc.so.6 => /lib64/libc.so.6 (0x00002b9c36069000)
libm.so.6 => /lib64/libm.so.6 (0x00002b9c363fd000)
/lib64/ld-linux-x86-64.so.2 (0x00002b9c35be5000)
$ readelf -a a.out  | grep -i rpath
0x000000000000000f (RPATH)              Library rpath: [/opt/gcc/5.5.0/lib64]
  1. 链接器找到正确库的方法是利用/opt/gcc/5.5.0/bin/gcc的路径并查看与它相关的相对路径。我通过设置export LD_LIBRARY_PATH=和排除rpath参数(即gcc -shared -Wl,--verbose -Wl,-soname,poo.so -o poo.so test.o -lquadmath )来检查这一点。即使如此,它仍然能够链接到正确的libquadmath.so.0库。
  2. /opt/gcc/5.5.0/lib/libquadmath.so.0.无法找到正确的库是因为它希望libquadmath.so.0库的64位版本不是libquadmath.so.0。这是库的32位版本.当您检查两个版本的库并看到它们分别是ELF64和ELF32 (例如readelf -a /opt/gcc/5.5.0/lib64/libquadmath.so.0 | grep Class)时,这一点就很明显了。
  3. 由于我从未指定它要查找的正确库的路径,因此ld.so默认会查看/etc/ld.conf.cache (它构建在`/etc/ld.conf.d/‘上),以决定要查找哪些目录。这就是为什么它发现了4.7.2版本的四边形。
  4. 要在运行时获得正确的库,我需要设置export LD_LIBRARY_PATH=/opt/gcc/5.5.0/lib64。

汇总,它使用ld (b/c,查看gcc的相对路径)在编译时找到正确的库,但在运行时找不到正确的库(b/c LD_LIBRARY_PATH设置错误)。解决方案是:export LD_LIBRARY_PATH=/opt/gcc/5.5.0/lib64。在构建共享库时,-rpath不是有效的选项。

票数 1
EN

Stack Overflow用户

发布于 2018-06-01 04:51:42

由-rpath选项指定的路径将被硬编码为您创建的二进制文件。在运行时,ld将优先从这些路径搜索依赖库。这是由ld.so决定的。

但是,在编译程序时,链接器将从LD_LIBRARY_PATH和-L选项指定的文件夹中搜索依赖库。编译时,-rpath指定的路径不生效.这是由ld,GNU链接器决定的。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50627986

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档