我看到的问题是,在Cygwin上运行的perl
进程中加载了错误的库版本(1.7.15,截至2012年9月的当前版本)。
简单地说,perl
启动,use XML::LibXML
,它是libxml2
的Perl接口,Daniel Veillard的XML库C库,然后Perl / C粘合剂加载C库。现在,安装了两个版本,/usr/lib
中的较旧版本和/usr/local/lib
中的较新版本 - 这是一个典型的场景。 Perl / C胶水库(XML::LibXML
)是根据/usr/local/lib
中较新的版本编译的。然而,负责加载库的Perl或Cygwin组件会选择较旧的组件。这会触发Perl / C粘合代码的警告,该代码正确地期望并要求编译它的版本。 (由于向后兼容性,它仍然主要起作用,但不完全符合预期。)
有一点需要注意,在Cygwin上它不是lib/libxml2.so.2
,而是bin/cygxml2-2.dll
!
这是从屏幕上复制的动作:
MiLu@Dago: /tmp > export LD_LIBRARY_PATH=/usr/local/bin
MiLu@Dago: /tmp > export LD_RUN_PATH=/usr/local/bin
MiLu@Dago: /tmp > ls -l /usr/bin/cygxml2-2.dll
-rwxr-xr-x 1 MiLu root 1096206 1. Mrz 2012 /usr/bin/cygxml2-2.dll
MiLu@Dago: /tmp > ls -l /usr/local/bin/cygxml2-2.dll
-rwxr-xr-x 1 MiLu None 3997813 21. Mai 22:35 /usr/local/bin/cygxml2-2.dll
MiLu@Dago: /tmp > perl -MXML::LibXML -e1
Warning: program compiled against libxml 208 using older 207
Warning: XML::LibXML compiled against libxml2 20800,
but runtime libxml2 is older 20708
我不确定如何加载C库cygxml2-2.dll
(标准名称libxml2
)。
这是Perl / C胶水库的ldd
输出:
$ ldd /usr/lib/perl5/site_perl/5.14/i686-cygwin-threads-64int/auto/XML/LibXML/LibXML.dll
ntdll.dll => /cygdrive/c/Windows/SysWOW64/ntdll.dll (0x774a0000)
kernel32.dll => /cygdrive/c/Windows/syswow64/kernel32.dll (0x756c0000)
KERNELBASE.dll => /cygdrive/c/Windows/syswow64/KERNELBASE.dll (0x76750000)
cygwin1.dll => /usr/bin/cygwin1.dll (0x61000000)
cygssp-0.dll => /usr/bin/cygssp-0.dll (0x6af50000)
>>> cygxml2-2.dll => /usr/local/bin/cygxml2-2.dll (0x63fc0000) <<<
cygz.dll => /usr/bin/cygz.dll (0x6a900000)
cyggcc_s-1.dll => /usr/bin/cyggcc_s-1.dll (0x6ca60000)
cygiconv-2.dll => /usr/bin/cygiconv-2.dll (0x6c390000)
cygperl5_14.dll => /usr/bin/cygperl5_14.dll (0x6b8a0000)
cygcrypt-0.dll => /usr/bin/cygcrypt-0.dll (0x6d3d0000)
??? => ??? (0x520000)
正如您所看到的,正确定位了较新的库,就像在UNIX上发生的那样。但ldd
不是实际的过程,可能使用不同的查找机制。
使用strace perl … | grep -i cygxml
显示无输出。
在我看来,LD_LIBRARY_PATH
和LD_RUN_PATH
被忽略了。因为如果不是为什么我会收到版本不匹配警告?
库加载机制是否特定于perl
或Cygwin?它是如何工作的?如何让perl
或Cygwin加载正确的库?
[我怀疑的是perl
居住在/usr/bin
,它将首先在{binnerie的目录/usr/bin
中查找库,从而遵循Windows约定而不是UNIX约定。]
答案 0 :(得分:1)
在编写Alien :: Base时,我需要使用DynaLoader直接删除特定的库。您可以阅读代码here,但快速和肮脏应该只是
require DynaLoader;
DynaLoader::dl_load_file( $library_path, 0x01 )
答案 1 :(得分:0)
cygwin确实支持LD_LIBRARY_PATH;尝试检查它是否在您的脚本开头按预期设置:
BEGIN { print "LD_LIBRARY_PATH: $ENV{LD_LIBRARY_PATH}.\n" }