В чем разница между `-rpath-link` и`-L`?
Человек для gold
состояния:
-L DIR, --library-path DIR
Add directory to search path
--rpath-link DIR
Add DIR to link time shared library search path
Человек для BFD ld
делает это вроде как -rpath-link
используется для рекурсивно включенного SOS.
ld.lld
даже не перечисляет это как аргумент.
Может ли кто-нибудь прояснить эту ситуацию для меня?
2 ответа
Вот демо, для GNU ld
разницы между -L
а также -rpath-link
- и для хорошей меры, разница между -rpath-link
а также -rpath
,
foo.c
#include <stdio.h>
void foo(void)
{
puts(__func__);
}
bar.c
#include <stdio.h>
void bar(void)
{
puts(__func__);
}
foobar.c
extern void foo(void);
extern void bar(void);
void foobar(void)
{
foo();
bar();
}
main.c
extern void foobar(void);
int main(void)
{
foobar();
return 0;
}
Сделайте две общие библиотеки, libfoo.so
а также libbar.so
:
$ gcc -c -Wall -fPIC foo.c bar.c
$ gcc -shared -o libfoo.so foo.o
$ gcc -shared -o libbar.so bar.o
Сделайте третью общую библиотеку, libfoobar.so
это зависит от первых двух;
$ gcc -c -Wall -fPIC foobar.c
$ gcc -shared -o libfoobar.so foobar.o -lfoo -lbar
/usr/bin/ld: cannot find -lfoo
/usr/bin/ld: cannot find -lbar
collect2: error: ld returned 1 exit status
К сожалению. Компоновщик не знает, где искать, чтобы решить -lfoo
или же -lbar
,
-L
опция исправляет это.
$ gcc -shared -o libfoobar.so foobar.o -L. -lfoo -lbar
-Ldir
опция говорит компоновщику, что dir
является одним из каталогов для поиска библиотек, которые разрешают -lname
варианты дано. Он ищет -L
каталоги сначала в порядке их командной строки; затем он ищет свои настроенные каталоги по умолчанию, в их настроенном порядке.
Теперь создайте программу, которая зависит от libfoobar.so
:
$ gcc -c -Wall main.c
$ gcc -o prog main.o -L. -lfoobar
/usr/bin/ld: warning: libfoo.so, needed by ./libfoobar.so, not found (try using -rpath or -rpath-link)
/usr/bin/ld: warning: libbar.so, needed by ./libfoobar.so, not found (try using -rpath or -rpath-link)
./libfoobar.so: undefined reference to `bar'
./libfoobar.so: undefined reference to `foo'
collect2: error: ld returned 1 exit status
Ой снова Компоновщик обнаруживает динамические зависимости, запрошенные libfoobar.so
но не могу их удовлетворить. Давайте сопротивляться его советам - try using -rpath or -rpath-link
- немного и посмотрим, что мы можем сделать с -L
а также -l
:
$ gcc -o prog main.o -L. -lfoobar -lfoo -lbar
Все идет нормально. Но:
$ ./prog
./prog: error while loading shared libraries: libfoobar.so: cannot open shared object file: No such file or directory
во время выполнения загрузчик не может найти libfoobar.so
,
А как насчет совета линкера? С -rpath-link
, мы можем:
$ gcc -o prog main.o -L. -lfoobar -Wl,-rpath-link=$(pwd)
и эта связь также успешно.
-rpath-link=dir
опция сообщает компоновщику, что когда он встречает входной файл, который запрашивает динамические зависимости - например, libfoobar.so
- он должен искать каталог dir
разрешить их. Таким образом, нам не нужно указывать эти зависимости с -lfoo -lbar
и даже не нужно знать, что они есть. То, что они есть, это информация, уже написанная в динамическом разделе libfoobar.so
:-
$ readelf -d libfoobar.so
Dynamic section at offset 0xdf8 contains 26 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libfoo.so]
0x0000000000000001 (NEEDED) Shared library: [libbar.so]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
...
...
Нам просто нужно знать каталог, где их можно найти, кем бы они ни были.
Но дает ли это нам работоспособный prog
?
$ ./prog
./prog: error while loading shared libraries: libfoobar.so: cannot open shared object file: No such file or directory
Так же, как история, как и раньше. Это потому что -rpath-link=dir
дает компоновщику информацию, которая понадобится загрузчику для разрешения некоторых динамических зависимостей prog
во время выполнения - при условии, что он остался верным во время выполнения - но он не записывает эту информацию в динамический раздел prog
, Это просто позволяет связать успешно, без нашей необходимости прописывать все рекурсивные динамические зависимости связи с -l
опции.
Во время выполнения, libfoo.so
, libbar.so
- и действительно libfoobar.so
- вполне может быть не там, где они сейчас - $(pwd)
- но загрузчик мог бы найти их другими способами: через ldconfig
кеш или настройка LD_LIBRARY_PATH
переменная окружения, например:
$ export LD_LIBRARY_PATH=.; ./prog
foo
bar
rpath=dir
предоставляет компоновщику ту же информацию, что и rpath-link=dir
и инструктирует компоновщику запекать эту информацию в динамический раздел выходного файла. Давайте попробуем это:
$ export LD_LIBRARY_PATH=
$ gcc -o prog main.o -L. -lfoobar -Wl,-rpath=$(pwd)
$ ./prog
foo
bar
Все хорошо. Потому что сейчас prog
содержит информацию, которая $(pwd)
это путь поиска во время выполнения для разделяемых библиотек, от которого он зависит, как мы можем видеть:
$ readelf -d prog
Dynamic section at offset 0xe08 contains 26 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libfoobar.so]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
0x000000000000000f (RPATH) Library rpath: [/home/imk/develop/so/scrap]
... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...
Этот путь поиска будет пробоваться после каталогов, перечисленных в LD_LIBRARY_PATH
, если таковые установлены, и перед настройками системы по умолчанию - ldconfig
каталоги, плюс /lib
а также /usr/lib
,
--rpath-link
опция используется bfd ld для добавления к пути поиска, используемому для поиска разделяемых библиотек DT_NEEDED при выполнении разрешения символов во время соединения. Это в основном говорит компоновщику, что использовать в качестве пути поиска во время выполнения при попытке имитировать то, что динамический компоновщик будет делать при разрешении символов (как установлено --rpath
варианты или LD_LIBRARY_PATH
переменная окружения).
Gold не следует за записями DT_NEEDED при разрешении символов в общих библиотеках, поэтому --rpath-link
опция игнорируется Это было обдуманное дизайнерское решение; косвенные зависимости не обязательно должны присутствовать или находиться в местах их выполнения во время процесса соединения.