On Wed, Feb 26, 2003 at 06:11:48PM +0100, Markus Jansen wrote:
> Hi Autrijus,

(Cc'ing the list for more insight.)

Thanks so much on detailed study on this matter.  I see that I'm
really ignorant here, being a Win32 user for far too long. :-)

> packing everything but the kitchen sink (aka libc etc.) is definitely
> not my intention. But I think the $Config{lddlflags} is definitely made
> to cater for shared libraries which are available for more than one module -
> usually that stuff is separately installed before you install any
> depending modules from CPAN.

True.  I must have been confused by the standard ActivePerl/Win32
behaviour, which is to install any shared libraries inside the auto/
path -- so for example, the PPM of DB_File and BerkeleyDB will contain
a libdb40.dll _each_, instead of sharing it somehow.

If I remember correctly, PerlApp's solution is to ask user to explicitly
include any shared libraries outside the auto/ path, and extract those
libraries verbatim to somewhere equivalent of LD_LIBRARY_PATH.  It's
been ages since I last used it though, so I hope somebody more versed
in PerlApp could comment.

> A prominent series of examples is the LibXML:: modules.
> I guess that quite some of of them use the same library (e.g. libxml2.so),
> which are installed only once of course.
> The "native" path to those libraries is then compiled into the libraries -
> the only way to get this information I know is via ldd, but ldd tells
> this only if the path is really found.

Hmm? I thought the libraries only contain the shared object name, not
the "native path" as you call it.  To wit:

    psh$ ldd /usr/local/lib/perl5/5.8.0/i386-freebsd/auto/DB_File/DB_File.so
    /usr/local/lib/perl5/5.8.0/i386-freebsd/auto/DB_File/DB_File.so:
        libdb4.so.0 => /usr/local/lib/libdb4.so.0 (0x28144000)
    psh$ $ENV{LD_LIBRARY_PATH} = "/tmp:/usr/local/lib"
    psh$ cp /usr/local/lib/libdb4.so.0 /tmp/
    psh$ ldd /usr/local/lib/perl5/5.8.0/i386-freebsd/auto/DB_File/DB_File.so
    /usr/local/lib/perl5/5.8.0/i386-freebsd/auto/DB_File/DB_File.so:
             libdb4.so.0 => /tmp/libdb4.so.0 (0x28144000)

So as long as it's somewhere in LD_LIBRARY_PATH, the path does not
matter.

> This is the reason why just copying the file into the PAR archive and even
> some pre-bootstrap unpacking into /tmp will not help at all.
> 
> I. We need to identify the additional libraries we want to pack.
>    I have found 2 alternatives:
>    
> I.1. record the dependencies using e.g. ldd
> 
> I.2. create symbolic links from the auto/... directory to those
>      libraries contained in the $Config{lddlflags} directories,
>      or simply copy them.
>      
>      However, this would introduce a "Perl module post-installation" step
>      for PAR only.

I.1. is clearly the way to go, only that we need to determine it portably.
(and what about second- or third- level of dependency? can we safely
ignore them?)

> II. At present (having thought and read another day on this topic),
>     I see 3 ways of implementing the load part:
> 
> II. 1. store them in the PAR bag with special dependency and order information,
>        and silently load them in the proper order before passing to 
>        DynaLoader::bootstrap

I'm not exactly sure how to load them before DynaLoader::bootstrap in
the Perl land.  Does it needs C-level myldr magic (which will be
incovenient), or is there a simpler way for that?

> II. 2. An alternative to loading the libs before the bootstrap would be to
>        set the LD_LIBRARY_PATH to an unpack directory, where they get their
>        original file name. 

Indeed, that's what I wanted.

>        I have tried hard to do this from inside Perl (set LD_LIBRARY_PATH,
>        pushing the library to @DynaLoader::dl_resolve_using, or pushing
>        the new path to @DynaLoader::dl_library_path) - all of this does not
>        help, but setting LD_LIBRARY_PATH before starting the Perl
>        program of course helps :-(.
>        I guess that augmenting LD_LIBRARY_PATH and calling ourself again
>        is not something we really want ...

It can be less drastic than that. :-)

A quick experiment with myldr/main.c shows that setting it before
creating the perl interpreter does help:

--- myldr/main.c.orig   Thu Feb 27 10:06:01 2003
+++ myldr/main.c        Thu Feb 27 10:06:02 2003
@@ -59,6 +59,8 @@ int main( int argc, char **argv, char **
     GV* tmpgv;
     int options_count;

+    setenv("LD_LIBRARY_PATH", "/tmp", 1);
+
 #if defined(USE_ITHREADS)
     /* XXX Ideally, this should really be happening in perl_alloc() or
      * perl_construct() to keep libperl.a transparently fork()-safe.

So instead of using File::Temp to determine the temporary directory,
we can predetermine it at C-level, augment LD_LIBRARY_PATH to include
it, and have the Perl-level code just look at the new
$ENV{LD_LIBRARY_PATH} as the temporary directory to write shared objects
(and potentially other files?) into.

Does it sound like a clean solution to you?

> II. 3. A third, hypothetical, ugly way would be to change the zero terminated
>        paths in the Module's main shared library to the (necessarily shorter)
>        PAR extraction path.
>        Extraction of the additional libs would also require their original
>        names, unless we change them, too (here we will have a real length
>        problem ...).

Ugh.  Let's not go there.

> For me, I.1. and II.1. still mark the proper ways to go ;-(

I'd welcome II.1 instead of II.2 if the 'silently load' bits is
explained better. :-)

Thanks,
/Autrijus/

Attachment: pgp00000.pgp
Description: PGP signature

Reply via email to