Hi,
Having read through the thread, my somewhat Windows specific view on this is
that there is only one case where the current PAR implementation does not work.
That is where a shared library is loaded in a completely none standard manner
for the operating system concerned.
This is the case with Gtk2, and to a lesser extend with Wx (you can alter Wx
within Perl so that libs are loaded using current PAR implementation).
I don't recall any other genuine cases reported to this list, though there may
be some.
For example, Image::Magick uses standard methods to load its dependencies so it
is just a matter of packing the correct ones to 'shlib'.
In general, the only shared libraries that can have common names within a Perl
process are the XS modules themselves. Dependent shared libraries - i.e. those
linked to XS modules by standard dynamic linking, must have unique file names.
For the example
sys/libfoo.dll, glib/libfoo.dll, and a bork/libfoo.dll
in windows at least, in general, the first libfoo.dll your process attempts to
load is the libfoo.dll you get.
Note that in Windows 'side by side' loading works from the perspective of DLLs
too
e.g. If I have process perl.exe that loads
../auto/My/Module/Module.dll
and Module.dll has a dependency on ModuleExtra.dll, then if
../auto/My/Module/ModuleExtra.dll exists, that will get loaded .
If later in my prog I do "loadlibrary('ModuleExtra.dll') then I will just get
an increase in the ref count to ./auto/My/Module/ModuleExtra.dll.
So, the current implementation of mangling XS module library names and
extracting dependent libs from shlib to the cache root works for everything
except odd cases.
In the odd case of Gtk2, the only way to cope with its behaviour is to extract
to a standard 'tree' (as pointed out earlier in thread).
We could change everything about PAR to cope with Gtk2, but if we do so, it
might be a good idea to take a step back and think about wider alterations to
current PAR.
Why not take recent work on Archive::Unzip::Burst and incorporate that in a
reworked PAR - say PAR::Burst
PAR::Burst would then just extract everything to cache directory with no name
mangling and a simple tree structure like
inc
shlib
script
'inc' gets added to @INC, shlib to library paths, script folder is added to
'PATH' and perms mask is 0755.
End users can add whatever else thy like to zip structure.
Of course, this would mean that foo.par packed under PAR would be different to
foo.par packed under PAR::Burst - so PAR::Burst would need a fallback method
whereby after extraction, if we don't have 'PAR::Burst' structure, start again
with PAR. This would make older .par files take slightly longer to load, but it
would still work until all dependencies were converted to PAR::Burst
For PAR::Burst::Packer, the goal would be to incorporate the unzip code
directly within the compiled executable, removing the need to load Perl at all
until after the extract is complete.
In addition to increased speed, this would give us the huge advantage that when
the initial executable stub has extracted the zip tree, we can then in the
extracted second executable simply mangle the arguments and call
perl_parse on the path to the extracted script - removing any BEGIN, eval, do -e
wrapper. We would have to prepend a BEGIN block to the script to set up necessary PATHS /
@INC but this would still make the script code that followed run exactly as if it have
been called as "perl myscript.pl". A big win I think.
I would quite like to work on this if there is any agreement that any of it
represents a reasonable idea.
Regards
Mark
Steffen Mueller wrote:
Hi Glenn, hi all,
Glenn Linderman schrieb:
Now if a library was not originally part of the <perl-install> tree,
it is an open question where it should be installed... and maybe that
is what you are referring to?
Unless I'm grossly mistaken, that's exactly what Scott is referring to.
So then in the PAR case we have
<par-cache-for-this-app>/(lib|bin|script) and you are suggesting that
anything that is included from other parts of the original file system
should be placed in <par-cache-for-this-app>? I'd have suggested
placing them in <par-cache-for-this-app>/script -- the script and any
non-perl stuff should go there?
I don't see any reason to put non-perl stuff in script, to be honest.
Maybe this is a Windows thing where people generally put dlls next to
the executables in PATH?
My suggestion would be the following:
- For any Perl stuff, use the original paths and names.
- For shared libraries added with -l, use shlib/ORIGINALNAME or whatever
that path's called. Add that to LD_LIBRARY_PATH and -- on Windows -- to
PATH.
- For data files added with -a, use the main cache directory and the
original file name.
Now, what happens if filenames of external shared objects clash? There
might be a sys/libfoo.so, a glib/libfoo.so, and a bork/libfoo.so
required by the same program, as far as I know. (Is that right?)
We can't possibly recover those paths by looking at them unless we test
against something like m|\blib/((?:[^/]+/)*[^/]+.so)$| on Linux and use
$1 for extraction. But that's not going to work. And I digress...
So maybe -l should accept syntax similar to -a, except it places things
under /shlib instead of / (i.e. -l/usr/lib/sys/foo;sys/foo).
Cheers,
Steffen