LD_LIBRARY_PATH 对 LibXML.so 无效
LD_LIBRARY_PATH doesn't take effect for LibXML.so
XML::LibXML
是一个 Perl 库。 LibXML.so
是图书馆的一部分。我正在尝试让 XML::LibXML
使用自定义 libxml2
。但是提供 LD_LIBRARY_PATH
没有任何区别:
$ ldd ./blib/arch/auto/XML/LibXML/LibXML.so | grep libxml2
libxml2.so.2 => /usr/lib/libxml2.so.2 (0x00007f66af5e9000)
$ LD_LIBRARY_PATH=/home/yuri/_/libxml2/.libs ldd ./blib/arch/auto/XML/LibXML/LibXML.so | grep libxml2
libxml2.so.2 => /usr/lib/libxml2.so.2 (0x00007f2d26ae3000)
$ ldd /usr/lib/python3.7/site-packages/libxml2mod.so | grep libxml2
libxml2.so.2 => /usr/lib/libxml2.so.2 (0x00007f878cbc8000)
$ LD_LIBRARY_PATH=/home/yuri/_/libxml2/.libs ldd /usr/lib/python3.7/site-packages/libxml2mod.so | grep libxml2
libxml2.so.2 => /home/yuri/_/libxml2/.libs/libxml2.so.2 (0x00007f6f8f5d8000)
我做错了什么?有办法处理吗?目标是让 Perl 脚本使用自定义构建 libxml2
(调查一些问题)。
UPD
$ find /usr/lib -name libxml2.so.2
/usr/lib/libxml2.so.2
/usr/lib/vmware-installer/2.1.0/lib/lib/libxml2.so.2
/usr/lib/vmware-installer/2.1.0/lib/lib/libxml2.so.2/libxml2.so.2
/usr/lib/vmware-vmrc/5.5/lib/libxml2.so.2
/usr/lib/vmware-vmrc/5.5/lib/libxml2.so.2/libxml2.so.2
$ find /usr/local/lib -name libxml2.so.2
如果您在 /usr/local/lib
中安装自定义版本的 libxml,我认为 XML::LibXML 模块应该加载自定义版本而不是 /usr/lib
中的版本(假设您有 sudoers或 root 权限来安装它)。
我不确定为什么 Python 似乎使用与 Perl 不同的库查找路径。也许 libxml 库的完整路径被硬编码在 XML::LibXML 的 LibXML.so 中?如果 XML::LibXML 模块与 -l/usr/lib/libxml2.so 而不是 -lxml2 链接,那将是问题所在。
tl;博士
ExtUtils::MakeMaker
通过 .dynamic
部分中的 RPATH
条目硬编码二进制文件中共享库的路径。但是你可以预加载需要的库,
$ 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
,并将它们转换为 four or five variables,从而进入生成的 Makefile
.其中之一是 LD_RUN_PATH
。它包含找到库的所有路径。
$is_dyna
如果库是动态的(不是 ends with .a
). $is_perl
is true if Perl was not built with it,%ld_run_path_seen
是为了不重复 LD_RUN_PATH
中的值。
calculates LD_RUN_PATH
, that generates part of the Makefile with the variable, and the part that passes it to the linker.
的部分
后果
LD_RUN_PATH
和二进制文件中的 RPATH
条目使加载程序在找到它们的目录中(在编译时)搜索库(在 运行 时间) .
-rpath=dir
Add a directory to the runtime library search path. This is used when linking an ELF executable with shared objects. All -rpath arguments are concatenated and passed to the runtime linker, which uses them to locate shared objects at runtime. The -rpath option is also used when locating shared objects which are needed by shared objects explicitly included in the link; see the description of the -rpath-link option. If -rpath is not used when linking an ELF executable, the contents of the environment variable "LD_RUN_PATH" will be used if it is defined.
https://jlk.fjfi.cvut.cz/arch/manpages/man/core/binutils/ld.1.en
If a shared object dependency does not contain a slash, then it is searched for in the following order:
o Using the directories specified in the DT_RPATH dynamic section attribute of the binary if present and DT_RUNPATH attribute does not exist. Use of DT_RPATH is deprecated.
o Using the environment variable LD_LIBRARY_PATH, unless the executable is being run in secure-execution mode (see below), in which case this variable is ignored.
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
- 显示所有 headers.
解决方案
解决此问题的一种方法是预加载 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
,你可以 运行 使用 OPTIMIZE
变量进行构建(添加 -B
以进行重建,以防库已经被建成),
$ make OPTIMIZE='-g3 -O0'
还有 -O2
,LDDLFLAGS
中没有 -g
,但不确定这是否重要。
或者,WriteMakeFile
采用 OPTIMIZE
参数,因此您可以添加一行 here,
'OPTIMIZE' => '-g3 -O0'
或者你可以添加变量here,然后传递给Makefile.PL
,
$ perl Makefile.PL OPTIMIZE='-g3 -O0'
XML::LibXML
是一个 Perl 库。 LibXML.so
是图书馆的一部分。我正在尝试让 XML::LibXML
使用自定义 libxml2
。但是提供 LD_LIBRARY_PATH
没有任何区别:
$ ldd ./blib/arch/auto/XML/LibXML/LibXML.so | grep libxml2
libxml2.so.2 => /usr/lib/libxml2.so.2 (0x00007f66af5e9000)
$ LD_LIBRARY_PATH=/home/yuri/_/libxml2/.libs ldd ./blib/arch/auto/XML/LibXML/LibXML.so | grep libxml2
libxml2.so.2 => /usr/lib/libxml2.so.2 (0x00007f2d26ae3000)
$ ldd /usr/lib/python3.7/site-packages/libxml2mod.so | grep libxml2
libxml2.so.2 => /usr/lib/libxml2.so.2 (0x00007f878cbc8000)
$ LD_LIBRARY_PATH=/home/yuri/_/libxml2/.libs ldd /usr/lib/python3.7/site-packages/libxml2mod.so | grep libxml2
libxml2.so.2 => /home/yuri/_/libxml2/.libs/libxml2.so.2 (0x00007f6f8f5d8000)
我做错了什么?有办法处理吗?目标是让 Perl 脚本使用自定义构建 libxml2
(调查一些问题)。
UPD
$ find /usr/lib -name libxml2.so.2
/usr/lib/libxml2.so.2
/usr/lib/vmware-installer/2.1.0/lib/lib/libxml2.so.2
/usr/lib/vmware-installer/2.1.0/lib/lib/libxml2.so.2/libxml2.so.2
/usr/lib/vmware-vmrc/5.5/lib/libxml2.so.2
/usr/lib/vmware-vmrc/5.5/lib/libxml2.so.2/libxml2.so.2
$ find /usr/local/lib -name libxml2.so.2
如果您在 /usr/local/lib
中安装自定义版本的 libxml,我认为 XML::LibXML 模块应该加载自定义版本而不是 /usr/lib
中的版本(假设您有 sudoers或 root 权限来安装它)。
我不确定为什么 Python 似乎使用与 Perl 不同的库查找路径。也许 libxml 库的完整路径被硬编码在 XML::LibXML 的 LibXML.so 中?如果 XML::LibXML 模块与 -l/usr/lib/libxml2.so 而不是 -lxml2 链接,那将是问题所在。
tl;博士
ExtUtils::MakeMaker
通过 .dynamic
部分中的 RPATH
条目硬编码二进制文件中共享库的路径。但是你可以预加载需要的库,
$ 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
,并将它们转换为 four or five variables,从而进入生成的 Makefile
.其中之一是 LD_RUN_PATH
。它包含找到库的所有路径。
$is_dyna
如果库是动态的(不是 ends with .a
). $is_perl
is true if Perl was not built with it,%ld_run_path_seen
是为了不重复 LD_RUN_PATH
中的值。
calculates LD_RUN_PATH
, that generates part of the Makefile with the variable, and the part that passes it to the linker.
后果
LD_RUN_PATH
和二进制文件中的 RPATH
条目使加载程序在找到它们的目录中(在编译时)搜索库(在 运行 时间) .
-rpath=dir Add a directory to the runtime library search path. This is used when linking an ELF executable with shared objects. All -rpath arguments are concatenated and passed to the runtime linker, which uses them to locate shared objects at runtime. The -rpath option is also used when locating shared objects which are needed by shared objects explicitly included in the link; see the description of the -rpath-link option. If -rpath is not used when linking an ELF executable, the contents of the environment variable "LD_RUN_PATH" will be used if it is defined.
https://jlk.fjfi.cvut.cz/arch/manpages/man/core/binutils/ld.1.en
If a shared object dependency does not contain a slash, then it is searched for in the following order:
o Using the directories specified in the DT_RPATH dynamic section attribute of the binary if present and DT_RUNPATH attribute does not exist. Use of DT_RPATH is deprecated.
o Using the environment variable LD_LIBRARY_PATH, unless the executable is being run in secure-execution mode (see below), in which case this variable is ignored.
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
- 显示所有 headers.
解决方案
解决此问题的一种方法是预加载 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
,你可以 运行 使用 OPTIMIZE
变量进行构建(添加 -B
以进行重建,以防库已经被建成),
$ make OPTIMIZE='-g3 -O0'
还有 -O2
,LDDLFLAGS
中没有 -g
,但不确定这是否重要。
或者,WriteMakeFile
采用 OPTIMIZE
参数,因此您可以添加一行 here,
'OPTIMIZE' => '-g3 -O0'
或者你可以添加变量here,然后传递给Makefile.PL
,
$ perl Makefile.PL OPTIMIZE='-g3 -O0'