ethrbunny has asked for the wisdom of the Perl Monks concerning the following question:

I have a .pl file that Im attempting to convert into a stand-alone executable using PAR::Packer. The process seems to run ok (creates a 2.7Mb file!) but when I copy it to a 'clean' machine I get an error message about missing files.
Can't load 'C:\WINDOWS\TEMP\par-pocl\cache-19dae601c13110aee2ff7f3fd53 +76357129ab7bd\3ae6449b.dll' for module Net::SSLeay: load_file:The spe +cified module could not be found at c:/Perl/lib/DynaLoader.pm line 23 +0. at c:/Perl/site/lib/PAR/Heavy.pm line 82 Compilation failed in require at script/soap3.pl line 6. BEGIN failed--compilation aborted at script/soap3.pl line 6.

I tried to force the packing to include 'Net::SSLeay' but it didn't change anything. Im assuming its the 'auto/net/SSLeay/SSLeay.dll' thats missing. Is there some way to make sure this file is included?

Replies are listed 'Best First'.
Re: PAR::Packer - 'dll not found' error on run
by almut (Canon) on Aug 17, 2007 at 19:47 UTC

    This specific DynaLoader error message is often somewhat misleading. I suspect that it's not SSLeay.dll but rather the DLL(s) that SSLeay.dll itself is depending on, which PAR isn't including... (PAR isn't very good at detecting secondary dependencies).

    You'll probably have to explicitly tell PAR to include those libs (using the --link option, if you're using pp). IIRC, the libs in question are libeay32.dll and/or ssleay32.dll (or some such), but better check yourself using Dependency Walker (in case you have Visual Studio, you probably already have the tool — look for depends.exe). Good luck.

      Gah - alrighty then. Dependancy checker it is.

      Does this error mean anything to you (or anyone)?
      Your vendor has not defined SSLeay macro randomize at IO/Socket/SSL.pm + line 55 BEGIN failed--compilation aborted at IO/Socket/SSL.pm line 57. Compilation failed in require at HTTP/Daemon/SSL.pm line 71. BEGIN failed--compilation aborted at HTTP/Daemon/SSL.pm line 71. Compilation failed in require at SOAP/Transport/HTTP.pm line 360.
      Its from the same packaged code. I added '-link ssleay32.dll -l libeay32.dll' to the original call.

        Just in case the link posted by the AnonyMonk doesn't suffice to solve the issue, I'll elaborate a bit:  Net::SSLeay makes use of AutoSplit and AutoLoader, i.e. most subroutines of the module are kept in separate .al files, which are then loaded on demand. In other words, when IO::Socket::SSL is calling Net::SSLeay::randomize(), the randomize.al file is being loaded. This is done via the AutoLoader::AUTOLOAD routine. OTOH, many XS modules provide a facility to load C constants defined in the related header files. As this is also done using AUTOLOAD, both mechanisms need to peacefully cooperate. This is usually achieved by first trying to load a constant of the requested name, and in case that fails (as is the case with "randomize" here), pass the autoload request on to AutoLoader::AUTOLOAD. To indicate to the caller that the loading of a constant failed, the constant() routine in the XS code sets errno = EINVAL (which, in stringified form, typically is "Invalid argument").

        Apparently, the target system where you're trying to deploy your PAR package is showing some weird behaviour with respect to EINVAL, so the autoload request isn't being passed through to the AutoLoader... (btw, even if the test for "Invalid" etc. fails, the || $!{EINVAL} should still normally be true — %! is a tied hash from Errno).

        The code below is the related AUTOLOAD routine from Net/SSLeay.pm. To figure out what's happening, insert the lines between the "###" (of course, make that modification before creating the PAR package). Then, once you know what EINVAL actually is on the target system, modify the next line (the one with $!{EINVAL}) to match whatever you're getting... (or post here what you're getting).

        # package Net::SSLeay; # ... sub AUTOLOAD { # This AUTOLOAD is used to 'autoload' constants from the constant( +) # XS function. If a constant is not found then control is passed # to the AUTOLOAD in AutoLoader. my $constname; ($constname = $AUTOLOAD) =~ s/.*:://; my $val = constant($constname); if ($! != 0) { ### debug if ($constname =~ /randomize/) { printf "errno: #%d ('%s') %s expected value (#%d)\n", $!, $!, $!{EINVAL} ? "matches":"doesn't match", Err +no::EINVAL; } ### if ($! =~ /((Invalid)|(not valid))/i || $!{EINVAL}) { $AutoLoader::AUTOLOAD = $AUTOLOAD; goto &AutoLoader::AUTOLOAD; } else { croak "Your vendor has not defined SSLeay macro $constname +"; } } eval "sub $AUTOLOAD { $val }"; goto &$AUTOLOAD; }