Pregunta

The issue I'm seeing is that the wrong version of a library gets loaded in a perl process running on Cygwin (1.7.15, current as of 09/2012).

Briefly, perl starts, does use XML::LibXML, which is the Perl interface to libxml2, Daniel Veillard's C library for XML, and the Perl/C glue then loads the C library. Now, there's two versions installed, an older one in /usr/lib and a more recent one in /usr/local/lib - a typical scenario. The Perl/C glue libary (XML::LibXML) is compiled against the newer version in /usr/local/lib. The Perl or Cygwin component responsable for loading libraries, however, picks up the older one. This triggers a warning by the Perl/C glue code, which rightly expects and demands the version it was compiled against. (It would still mostly work because of backward compatibility, but not quite as intended.)

One thing to note, on Cygwin it's not lib/libxml2.so.2, but rather bin/cygxml2-2.dll!

Here's the action copied from the screen:

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

I'm not sure how the C library cygxml2-2.dll (standard name libxml2) gets loaded.

Here's the ldd output for the Perl/C glue library:

$ 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)

As you can see, the newer library is correctly located, as would happen on UNIX. But ldd is not the actual process, which might use a different lookup mechanism.

Using strace perl … | grep -i cygxml shows no output.

It seems to me that LD_LIBRARY_PATH and LD_RUN_PATH are ignored. Because if not why do I get the version mismatch warning?

Is the library loading mechanism specific to perl or Cygwin? How does it work? How do I make perl or Cygwin load the proper library?

[One suspicion I have is that perl residing in /usr/bin, it will first look for libraries in /usr/bin, its binarie's directory, thus following the Windows convention rather than the UNIX convention.]

¿Fue útil?

Solución

In writing Alien::Base I needed to directly dlopen specific libraries using DynaLoader. You can read the code here but the quick and dirty should be simply

require DynaLoader;
DynaLoader::dl_load_file( $library_path, 0x01 )

Otros consejos

cygwin does support LD_LIBRARY_PATH; try checking that it's set as you expect at the beginning of your script:

BEGIN { print "LD_LIBRARY_PATH: $ENV{LD_LIBRARY_PATH}.\n" }
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top