ТЛ; др
ExtUtils::MakeMaker
пути жестких кодов разделяемых библиотек в двоичных файлах с помощью записи RPATH
в разделе .dynamic
. Но вы можете предварительно загрузить необходимую библиотеку,
$ LD_PRELOAD=path/to/custom/libxml2/.libs/libxml2.so.2 ldd ./blib/arch/auto/XML/LibXML/LibXML.so
или заставить загрузчик игнорировать RPATH
запись,
$ LD_LIBRARY_PATH=path/to/custom/libxml2/.libs /usr/lib/ld-linux-x86-64.so.2 --inhibit-rpath /abs/path/to/LibXML.so /abs/path/to/perl ./1.pl
или преобразовать RPATH
запись в RUNPATH
один,
$ chrpath --convert blib/arch/auto/XML/LibXML/LibXML.so
или удалить RPATH
запись,
$ chrpath --delete blib/arch/auto/XML/LibXML/LibXML.so
или укажите XMLPREFIX
переменную,
$ perl Makefile.PL XMLPREFIX=path/to/custom/libxml2/build
Под капотом
ExtUtils::Liblist::ext()
берет список библиотек, с которыми нужно связать, например, -lxml2 -lz -llzma -licui18n -licuuc -licudata -lm -ldl
, и превращает их в четыре или пять переменных , которые пробраться в сгенерированный Makefile
. Одним из них является LD_RUN_PATH
. Он содержит все пути, где были найдены библиотеки.
$is_dyna
- истина, если библиотека динамическая (не оканчивается на .a
). $is_perl
имеет значение true, если Perl не был встроенным с it , а %ld_run_path_seen
не должен дублировать значения в LD_RUN_PATH
.
Часть, которая вычисляет LD_RUN_PATH
, которая генерирует часть Makefile с переменной и часть, которая передает его компоновщику .
Последствия
LD_RUN_PATH
и, в свою очередь, запись RPATH
в двоичном файле заставляет загрузчик искать библиотеки (во время выполнения) в каталогах, где они были найдены (во время компиляции).
-rpath = каталог
Добавить каталог в путь поиска библиотеки времени выполнения. Используется при связывании исполняемого файла ELF с общими объектами. Все аргументы -rpath объединяются и передаются компоновщику среды выполнения, который использует их для поиска общих объектов во время выполнения. Опция -rpath также используется при поиске общих объектов, которые необходимы для общих объектов, явно включенных в ссылку; см. описание опции -rpath-link. Если -rpath не используется при связывании исполняемого файла ELF, будет использоваться содержимое переменной среды "LD_RUN_PATH", если оно определено.
https://jlk.fjfi.cvut.cz/arch/manpages/man/core/binutils/ld.1.en
Если зависимость общего объекта не содержит косую черту, то она ищется в следующем порядке:
o Использование каталогов, указанных в атрибуте динамического раздела DT_RPATH двоичного файла, если он присутствует, а атрибут DT_RUNPATH не существует. Использование DT_RPATH устарело.
o Использование переменной окружения LD_LIBRARY_PATH , если только исполняемый файл не запущен в режиме безопасного выполнения (см. Ниже), в этом случае эта переменная игнорируется.
https://jlk.fjfi.cvut.cz/arch/manpages/man/core/man-pages/ld.so.8.en
$ perl Makefile.PL
$ make
Результат,
$ readelf --dynamic ./blib/arch/auto/XML/LibXML/LibXML.so | grep RPATH
0x000000000000000f (RPATH) Library rpath: [/usr/lib]
$ objdump -x ./blib/arch/auto/XML/LibXML/LibXML.so | egrep RPATH
RPATH /usr/lib
$ LD_LIBRARY_PATH=path/to/custom/libxml2/.libs ldd ./blib/arch/auto/XML/LibXML/LibXML.so | grep libxml2
libxml2.so.2 => /usr/lib/libxml2.so.2 (0x00007f6cfabb2000)
--dynamic
- отображать содержимое раздела .dynamic
, -x
- отображать все заголовки.
Решение
Один из способов исправить это - предварительно загрузить необходимый экземпляр libxml2
,
$ LD_PRELOAD=path/to/custom/libxml2/.libs/libxml2.so.2 ldd ./blib/arch/auto/XML/LibXML/LibXML.so | grep libxml2
path/to/custom/libxml2/build/lib/libxml2.so.2 (0x00007fe183aeb000)
Другой способ - Makefile.PL
искать libxml2
в нужном месте (во время компиляции).
$ perl Makefile.PL XMLPREFIX=path/to/custom/libxml2/build
$ make
Результат,
$ readelf --dynamic ./blib/arch/auto/XML/LibXML/LibXML.so | grep RPATH
0x000000000000000f (RPATH) Library rpath: [path/to/custom/libxml2/build/lib:/usr/lib]
$ objdump -x ./blib/arch/auto/XML/LibXML/LibXML.so | egrep RPATH
RPATH path/to/custom/libxml2/build/lib:/usr/lib
$ ldd ./blib/arch/auto/XML/LibXML/LibXML.so | grep libxml2
libxml2.so.2 => path/to/custom/libxml2/build/lib/libxml2.so.2 (0x00007fe183aeb000)
На заметке
Если вы хотите отладить XML::LibXML
, вы можете запустить make с переменной OPTIMIZE
(добавьте -B
, чтобы make перестраивал все, если библиотека уже была собрана),
$ make OPTIMIZE='-g3 -O0'
Есть также -O2
, и нет -g
в LDDLFLAGS
, но не уверен, что это имеет большое значение.
В качестве альтернативы, WriteMakeFile
принимает параметр OPTIMIZE
, поэтому вы можете добавить строку здесь ,
'OPTIMIZE' => '-g3 -O0'
Или вы можете добавить переменную здесь и передать ее Makefile.PL
,
$ perl Makefile.PL OPTIMIZE='-g3 -O0'