perlparperl-packager

Can PAR Packer generate stand-alone scripts?


I'm currently using the PAR Packer (pp) to package a couple of pl scripts such that they can be copied to a machine and "just work" without my client having to muck with CPAN.

Unfortunately, the PAR Packer doesn't work for deep dependencies. For example, a script imports CHI::Driver::File but does not explicitly import Log::Any::Adapter::Null which CHI::Driver::File requires. PAR does not pick up this dependency and running the generated script will crash with the following error message:

Can't locate Log/Any/Adapter/Null.pm in @INC (@INC contains: CODE(0x874aab8) /tmp/par-apache/cache-7b4508ab92efb43271da1629e8eb654c1572cc55/inc/lib /tmp/par-apache/cache-7b4508ab92efb43271da1629e8eb654c1572cc55/inc CODE(0x87e8f54) CODE(0x87e9194)) at (eval 215) line 3.
Compilation failed in require at CHI/Driver/File.pm line 11.
BEGIN failed--compilation aborted at CHI/Driver/File.pm line 11.

My work-around is to explicitly import "Log::Any::Adapter::Null" but there must be a better way. Perhaps this is a bug with the PAR Packer? I have installed the latest version (0.994).


Solution

  • If you want a stand-alone script as opposed to a stand-alone binary (which is the default mode for pp), then add the -P option. I'd advise against it, though. It's the least-tested mode of operation.

    Note also that PAR::Packer DOES work for deep dependencies. The subject of your question is a bit pretentious. In fact, PAR::Packer doesn't really check any dependencies itself but delegates this to Module::ScanDeps. Now, Module::ScanDeps is a heuristic approach to dependency scanning and it can be broken by ugly fuzzing with dynamic loading of dependencies. (i.e. generating module names at run time and then using them in an eval).

    Indeed, if you look at the sources for Log::Any (which is used by CHI::Driver::File), you'll quickly see that it uses dynamic loading of modules. This is why the ::Adapter::Null module isn't being picked up.

    Generally, we fix these issues by adding a special case to Module::ScanDeps for such modules whose author thought it'd be a good idea to defeat any sort of static analysis. Until you get a fixed version of Module::ScanDeps, you can use the -c or -x options to pp to have the dependency resolution use compilation or execution of the program instead of only relying on static analysis. The augmented Module::ScanDeps has version 0.95 and should be available from CPAN within the day.