Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/sql-server-2008/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Gcc 为什么在构建共享库时--rpath会被取代?_Gcc_Ld - Fatal编程技术网

Gcc 为什么在构建共享库时--rpath会被取代?

Gcc 为什么在构建共享库时--rpath会被取代?,gcc,ld,Gcc,Ld,我在CentOS机器上工作。我有一个文件(test.c)正在编译到共享库中 test.c: #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); doub

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

test.c

#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;
}
ld
的详细输出中,似乎找到了
/opt/gcc/5.5.0/lib64/libquadmath.so.0
(这就是我想要的)。即

但是,当我使用ldd poo.so查看时,它没有正确的库。即

$ 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
version5.5.0,希望
poo.so
链接到
/opt/gcc/5.5.0/lib/libquadmath.so.0
,而不是4.7.2版本

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

$ cat /etc/ld.so.conf.d/gcc-4.7.2.conf 
/act/gcc-4.7.2/lib64
/act/gcc-4.7.2/lib
ld
(如我所问)的手册页不太有用


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

要理解解决方案,首先我们必须理解错误的想法

  • 我没有意识到有两个实用程序正在进行链接。有
    ld
    (在编译时使用)和
    ld.so
    (在运行时使用)。
    ld.so的手册页描述了如何在运行时找到库。要总结it搜索,请执行以下操作:

    a)
    DT_RPATH

    b) 在
    LD\u LIBRARY\u路径中指定的目录

    c) 二进制文件的DT_运行路径动态部分中的目录(如果存在)

    d) 缓存文件
    /etc/ld.so.Cache

    e) 默认路径是/lib,然后是/usr/lib

  • ld
    的手册页主要把我弄糊涂了。它在-rpath选项下显示:

    将目录添加到运行库搜索路径。这在将ELF可执行文件与共享对象链接时使用

    我认为在构建共享库时传递
    -rpath
    会 保证它可以在不需要设置的情况下找到库
    LD\u库路径
    错误。此功能似乎只有用 生成可执行文件时,不是共享库。有一个
    -rpath链接
    选项,但我不知道如何使它工作

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

    $ 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]
    
    $cat test2.c
    #包括
    #包括
    #包括
    内部主(空){
    __浮子;
    r=strtoflt128(“1.2345678”,空);
    int*b=malloc(sizeof(int)*5);
    双a=10*M_PI_2q;
    printf(“你好世界%f\n”,a);
    返回0;
    }
    $export LD\u LIBRARY\u路径=
    $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)库RPATH:[/opt/gcc/5.5.0/lib64]
    
  • 链接器找到正确库的方法是利用
    /opt/gcc/5.5.0/bin/gcc
    的路径并查看与之相关的路径。我通过设置
    export LD_LIBRARY\u PATH=
    并排除
    rpath
    参数来检查这一点,即
    gcc-shared-Wl,--verbose-Wl,-soname,poo.so-o poo.so test.o-lquadmath
    。即使在那时,它也能够链接到正确的
    libquadmath.so.0

  • ldpoo.so
    找不到正确的库的原因是它需要
    libquadmath.so.0
    库的
    版本。这是库的32位版本。当您检查库的两个版本并看到它们分别是ELF64和ELF32(例如
    readelf-a/opt/gcc/5.5.0/lib64/libquadmath.so.0 | grep Class
    )时,这一点就很明显了

  • 由于我从未指定要查找的正确库的路径,
    ld.so
    在默认情况下查看
    /etc/ld.conf.cache
    (它建立在“/etc/ld.conf.d/”的基础上)来决定要查找哪些目录。这就是为什么它发现了quadmath的4.7.2版本

  • 要在运行时获得正确的库,我需要设置
    export
    LD_LIBRARY_PATH=/opt/gcc/5.5.0/lib64

  • Summary,它在编译时使用
    ld
    (b/c它查看了gcc的相对路径),但在运行时找不到正确的库(b/c ld\u library\u路径设置不正确)。解决办法是:
    export-LD\u-LIBRARY\u-PATH=/opt/gcc/5.5.0/lib64
    <代码>-rpath
    在构建共享库时不是有效的选项。

    要理解解决方案,首先我们必须理解错误的想法

  • 我没有意识到有两个实用程序正在进行链接。有
    ld
    (在编译时使用)和
    ld.so
    (在运行时使用)。
    ld.so的手册页描述了如何在运行时找到库。要总结it搜索,请执行以下操作:

    a)
    DT_RPATH

    b) 在
    LD\u LIBRARY\u路径中指定的目录

    c) 二进制文件的DT_运行路径动态部分中的目录(如果存在)

    d) 缓存文件
    /etc/ld.so.Cache

    e) 默认路径是/lib,然后是/usr/lib

  • ld
    的手册页主要把我弄糊涂了。它是
    $ cat /etc/ld.so.conf.d/gcc-4.7.2.conf 
    /act/gcc-4.7.2/lib64
    /act/gcc-4.7.2/lib
    
    $ 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]