Можем ли мы опустить -ldependency в приведенной выше команде
Если вы управляете связью самого libutils.so
, да, вы можете. Иллюстрация:
main.c
extern void foo(void);
int main(void)
{
foo();
return 0;
}
foo.c
extern void bar(void);
void foo(void)
{
bar();
}
bar.c
#include <stdio.h>
void bar(void)
{
puts(__func__);
}
Мы создадим программу, которая зависит от libfoo.so
, которая зависит от libbar.so
.
Сделайте объектные файлы:
$ gcc -Wall -c -fPIC foo.c bar.c
gcc -Wall -c main.c
Теперь ссылка libbar.so
Без излишеств:
$ gcc -shared -o libbar.so bar.o
Следующая ссылка libfoo.so
вот так:
$ gcc -shared -o libfoo.so foo.o -L. -lbar -Wl,-rpath=$(pwd)
Эффект -rpath linker option
составляет:
-rpath = каталог
Добавить каталог в путь поиска библиотеки времени выполнения. Это используется при связывании исполняемого файла ELF с общими объектами.
Все аргументы -rpath объединяются и передаются компоновщику среды выполнения, который использует их для поиска общих объектов во время выполнения.
Опция -rpath также используется при поиске общих объектов, которые необходимы для общих объектов, явно включенных в ссылку;
см. описание опции -rpath-link. Если -rpath не используется при связывании исполняемого файла ELF,
содержимое переменной среды LD_RUN_PATH будет использоваться, если оно определено.
Результат таков:
$ objdump -x -j .dynamic libfoo.so | egrep '(RUNPATH|NEEDED)'
NEEDED libbar.so
RUNPATH /home/imk/develop/so/scrap
libfoo.so
имеет запись NEEDED
, вписанную в раздел .dynamic
, в которой говорится, что
библиотека имеет зависимость времени выполнения от libbar.so
. Точно так же имеет
запись RUNPATH
о том, что зависимости во время выполнения можно искать в /home/imk/develop/so/scrap
Это просто pwd
, где я сделал связь: это не должно быть так долго, пока это действительно так
каталог, в котором libbar.so
можно найти, когда его ищет компоновщик или загрузчик.
Эта информация может быть прочитана компоновщиком, когда libbar.so
связан с чем-то другим,
и загрузчиком во время выполнения. Наконец, я могу связать prog
так:
$ gcc -o prog main.o -L. -lfoo -Wl,-rpath=$(pwd)
Мне не нужно упоминать -lbar
, потому что libfoo.so
сам предоставляет компоновщику
информация, от которой libfoo.so
зависит libbar.so
, и где ее искать.
Так как я также передал -rpath=$(pwd)
в связи prog
, мы видим, что прога
предоставит эту информацию
$ objdump -x -j .dynamic prog | egrep '(RUNPATH|NEEDED)'
NEEDED libfoo.so
NEEDED libc.so.6
RUNPATH /home/imk/develop/so/scrap
загрузчику времени выполнения: prog
необходимо libfoo.so
, и его можно искать
в /home/imk/develop/so/scrap
. Когда загрузчик найдет libfoo.so
и загрузит его, он будет
узнайте из этого, что:
NEEDED libbar.so
RUNPATH /home/imk/develop/so/scrap
и в свою очередь найдет и загрузит libbar.so
, что позволит ему разрешить все
символы, упомянутые в процессе строительства. Следовательно, prog
может быть запущено немедленно:
$ ./prog
bar
У меня не было , чтобы передать -rpath=$(pwd)
в связи prog
. Но если бы я не сделал:
$ gcc -o prog main.o -L. -lfoo
$ ./prog
./prog: error while loading shared libraries: libfoo.so: cannot open shared object file: No such file or directory
загрузчик не будет знать, где найти libfoo.so
. См:
$ ldd prog
linux-vdso.so.1 (0x00007ffffcc35000)
libfoo.so => not found
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f4d1aff9000)
/lib64/ld-linux-x86-64.so.2 (0x00007f4d1b5ec000)
И тогда мне придется прибегнуть к:
$ export LD_LIBRARY_PATH=.
$ ldd prog
linux-vdso.so.1 (0x00007fff964dc000)
libfoo.so => ./libfoo.so (0x00007fc2a7f35000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fc2a7b44000)
libbar.so => ./libbar.so (0x00007fc2a7942000)
/lib64/ld-linux-x86-64.so.2 (0x00007fc2a8339000)
$ ./prog
bar
Позже
все еще немного неясно, достаточно ли присутствия libdependency.so в выводе ldd libutils.so, чтобы опустить -ldependencny во время связывания
Вам нужно задать хотя бы один и максимум два вопроса о выводе ldd utils.so
: -
- Вывод
ldd libutils.so
сообщает о так называемом libdependency.so
на всех ?
- Если «Да» для 1 , разрешает ли это так же имя в реальном файле?
Если нет для 1 , то libdutils.so
не содержит информации о зависимости libdependency.so
и вы должны указать -lutils -ldependency
в любой дальнейшей связи.
Если Да для 1 , но Нет для 2 (т.е. ldd libutils.so
сообщает libdependency.so => not found
), тогда libutils.so
имеет
NEEDED
запись для так называемого libdependency.so
, но не a RUNPATH
записи, с помощью которой компоновщик или
Загрузчик может преобразовать это имя в любой фактический файл. В этом случае вы снова должны связать -lutils -ldependency
, если связываете -lutils
, чтобы компоновщик затем искал файл, который разрешает -ldependency
. По крайней мере, вы должны делать это, пока ldd libutils.so
все еще сообщает о libdependency.so => not found
, когда вы делаете связь. Продолжайте читать ...
Если Да - 1 и Да - 2 , тогда вы можете сбросить -ldependency
в дальнейшую связь , если это
работать в той же среде, в которой вы запускали ldd libutils.so
Это предостережение необходимо, потому что, если ldd libutils.so
разрешит libdependency.so
, все, что вы знаете
ldd
удалось разрешить libdependency.so
, используя алгоритм поиска загрузчика: -
- Переменная окружения
LD_LIBRARY_PATH
(в активной оболочке), перечисляет каталог
в котором найдено libdependency.so
или
libutils.so
обеспечивает RUNPATH
, в котором находится libdependency.so
или
libdependency.so
находится в одном из каталогов, перечисленных в /etc/ld.so.conf
(или его рекурсивном include
-расширениях), или
libdependency.so
находится в одном из доверенных поисковых каталогов загрузчика, /lib
и /usr/lib
Если ldd
может разрешить libdependency.so
одним из этих четырех способов, то компоновщик сможет
сделать это так же, , пока этот путь все еще успешен, когда вы делаете связь .
Итак, возвращаясь к моему примеру и моей связи:
$ gcc -shared -o libfoo.so foo.o -L. -lbar -Wl,-rpath=$(pwd)
После этого, спасибо -rpath=$(pwd)
. Я могу связать prog
как:
$ gcc -o prog main.o -L. -lfoo
без упоминания -lbar
, и это удается. Теперь я связываю libfoo.so
вместо без
-rpath
:
$ gcc -shared -o libfoo.so foo.o -L. -lbar
после чего:
$ objdump -x -j .dynamic libfoo.so | egrep '(RUNPATH|NEEDED)'
NEEDED libbar.so
больше нет RUNPATH
, а следовательно:
$ ldd libfoo.so
linux-vdso.so.1 (0x00007ffda05e6000)
libbar.so => not found
потому что загрузчик не может разрешить libbar.so
любым другим способом.
Теперь я больше не могу связать prog
без -lbar
:
$ gcc -o prog main.o -L. -lfoo
/usr/bin/ld: warning: libbar.so, needed by ./libfoo.so, not found (try using -rpath or -rpath-link)
./libfoo.so: undefined reference to `bar'
Но если я сделаю:
$ export LD_LIBRARY_PATH=$(pwd)
, то:
$ ldd libfoo.so
linux-vdso.so.1 (0x00007ffe56d1e000)
libbar.so => /home/imk/develop/so/scrap/libbar.so (0x00007fd2456e8000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fd2452f7000)
/lib64/ld-linux-x86-64.so.2 (0x00007fd245aec000)
libfoo.so
Зависимость libbar.so
разрешается загрузчиком, используя LD_LIBRARY_PATH
, и в
так же по компоновщику:
$ gcc -o prog main.o -L. -lfoo; echo Done
Done
И если я очищу LD_LIBRARY_PATH
снова:
$ unset LD_LIBRARY_PATH
$ gcc -o prog main.o -L. -lfoo; echo Done
/usr/bin/ld: warning: libbar.so, needed by ./libfoo.so, not found (try using -rpath or -rpath-link)
./libfoo.so: undefined reference to `bar'
collect2: error: ld returned 1 exit status
Done
возврат к сбою.