Почему --rpath заменяется при создании разделяемой библиотеки? - PullRequest
0 голосов
/ 31 мая 2018

Я работаю на машине 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;
}

Чтобы скомпилировать его:

$ 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 найдено (что я и хочу).Т.е.

.
.
.
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, у него нет правильной библиотеки.Т.е.

$ 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 с указанием расположения старых библиотек.Т.е.

$ 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?Как мне указать местоположение библиотеки во время компиляции и как это исправить?

Ответы [ 2 ]

0 голосов
/ 01 июня 2018

Путь, указанный параметром --rpath, будет жестко запрограммирован в двоичный файл, который вы создали.Во время выполнения ld будет искать зависимые библиотеки по этим путям преимущественно.Это определяется ld.so .

Но когда вы компилируете программу, компоновщик будет искать зависимые библиотеки из LD_LIBRARY_PATH и тех папок, которые вы указали с помощью опции -L.Во время компиляции путь, указанный в --rpath, не вступает в силу.Это определяется ld, компоновщиком GNU .

0 голосов
/ 31 мая 2018

Чтобы понять решение, сначала мы должны понять неправильное мышление.

  1. Я не осознавал, что две утилиты делают связывание.Есть ld (который используется во время компиляции) и ld.so (который используется во время выполнения).Страница man 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, но я не мог понять, как заставить ее работать.

Это можно сделать, выполнив следующие действия:

$ 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]

Способ, которым компоновщик нашел правильную библиотеку, заключался в использовании пути к /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.

Причина, по которой ldd poo.so не удалось найти правильную библиотеку, заключалась в том, что он хотел 64-бит версия библиотеки libquadmath.so.0 НЕ /opt/gcc/5.5.0/lib/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.

Сводка , она находила правильную библиотеку во время компиляции, используя ld (б / с она смотрела на относительные пути gcc), ноне удалось найти правильную библиотеку во время выполнения (b / c LD_LIBRARY_PATH был неправильно установлен).Решение: export LD_LIBRARY_PATH=/opt/gcc/5.5.0/lib64.-rpath недопустим при создании общей библиотеки.

...