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