If I want to distribute a Perl script, what is the best way to painlessly install any required modules that are missing on the user's system? Extra credit if there is a way to even install/upgrade Perl itself if it is missing or "too old".
5 Answers
Auto-installing software is the best way to make both end users and sysadmins very angry with you. Forget about this approach.
You can simply ship all your dependencies with your application distro, the inc
directory is customary.

- 39,270
- 4
- 65
- 132
-
While I agree with the sentiment, I think the answer needs more work. Are you advocating the shipping of other perl packages or just shipping a copy of their code? The issue here is very common. It's painful in all languages to keep track of the 3rd party modules one uses. As a professional developer who distributes code, I now judge a language on the quality of it's package management. CPAN was once the greatest repository of software known to developers. But...It has taught lessons to other technologies which have less cryptic ways to create a software module. – Mark O'Connor Nov 19 '11 at 12:33
-
I'm advocating neither. I'm actually fond of the standard toolchain, yko laid out the details. I felt like taking on the question at face value, even if it is misguided. – daxim Nov 20 '11 at 21:04
Usually this ends with CPAN-like package creation.
So, when you need to install all dependencies you type make installdeps
See perldoc perlmodlib
Also Module::Install
may be useful for you and some Makefile.PL example
Makefile.PL
allows you to define deps and required perl version.
Also you may add
use 5.010;
To your script in order to require minimal version of perl to run. See perldoc -f use for details.

- 2,710
- 13
- 15
-
1That is not the "painless" I had in mind! I want to distribute one perl script file, allow the user to just run that script and the script itself installs any missing (but needed) modules without the user having to do any separate action. – JoelFan Nov 18 '11 at 14:02
-
@JoelFan, if you can get it to run on your platform, see Bill Ruppert's answer for *more* "painless". – Axeman Nov 18 '11 at 16:42
-
4Forget painless.... This is the proper answer, distribute the script as a perl module. Users who know how to manage perl distributions can then easily use the standard tooling. For less knowledgeable users provide a script which invokes the installation of your package. In conclusion your issue really is with Perl.... I used it for years and had the same issues. I flirted with using the PAR module but eventually gave up due to the effort involved. Embrace Perl or abandon it. I discovered there is no in-between :-( – Mark O'Connor Nov 19 '11 at 12:21
Why not use pp (PAR Packager) that creates an executable. No need for Perl or anything on the target machine.

- 8,956
- 7
- 27
- 44
-
PAR is very very cool. In my experience it was never as good as TCL's starkits and starpacks, which is massively disappointing. I learned that it was better to spend some time learning how to package perl as a module. Admittedly clunky, but easier to support across multiple platforms. – Mark O'Connor Nov 19 '11 at 12:25
If you look at cpanminus, this you can install by simply executing one file:
curl -L http://cpanmin.us | perl - --self-upgrade
This might be the behaviour you're looking for; it's done with App::Fatpacker. Check it out:

- 4,181
- 1
- 30
- 39
A semi-automated script taken from here , which should work for people with middle level bash skills and almost 0 level perl skills :
#!/usr/bin/env perl
use strict ; use warnings ;
use 5.10.0 ;
use ExtUtils::Installed;
# quick and dirty check for prerequisites perl modules:
# courtesy of:http://stackoverflow.com/a/9340304/65706
# if you have a calling bash script call by :
# perl "/path/to/isg_pub_preq_checker.pl"
# export ret=$?
# test $ret -ne 0 && doExit 1 "[FATAL] perl modules not found!!!"
my $PrintOkCheck = 1 ;
# check that all the required modules are installed
my ( $ret , $msg ) = doCheckRequiredModules();
unless ( $ret == 0 ) {
print "$msg" ;
# give some time for the user to react
print "printing all installed modules :" ;
my $c = 9 ;
for ( my $i=0;$i<=$c;$i++){
print ( ( $c-$i) . '.') ;
sleep 1 ;
}
print "\n" ;
doListAllInstalledModules();
print "\n" ;
}
exit(0);
sub doListAllInstalledModules {
my $instmod = ExtUtils::Installed->new();
foreach my $module ($instmod->modules()) {
my $version = $instmod->version($module) || "???";
print "found module:$module -- v$version\n";
}
}
#eof sub
sub doCheckRequiredModules {
my @modules = qw(
YAML::Any
Test::More
Spreadsheet::XLSX
Test::Deep
File::Copy::Recursive
IO::HTML
Test::More
Filter::Util::Call
Algorithm::Diff
Text::Diff
Test::Base
Test::CPAN::Meta::YAML
Test::YAML::Valid
Test::YAML::Meta
Test::YAML
Data::Printer
ExtUtils::Installed
Sub::StrictDecl
Spreadsheet::WriteExcel
Mojolicious::Plugin::RenderFile
JSON
Carp::Always
Mojolicious::Plugin::PDFRenderer
Redis::Client
);
for(@modules) {
eval "use $_";
if ($@) {
#flush the screen
print "\033[2J";
print "\033[0;0H";
my $msg = "\n\n\n [FATAL] did not found the following prerequisite perl module: $_ \n\n" ;
$msg .= "\n # == START copy paste == " ;
$msg .= "\n#you must install it otherwise the application will not work" ;
$msg .= "\n#the module could be installef by running the following commands:" ;
# if the user knows already the difference between the running the cmd
# with sudo or he / she probably knows already how-to install perl modules
$msg .= "\n# as a start configure the cpan to install dependancies first \n" ;
$msg .= "\n" . 'perl -MCPAN -e \'my $c = "CPAN::HandleConfig"; $c->load(doit => 1, autoconfig => 1); $c->edit(prerequisites_policy => "follow"); $c->edit(build_requires_install_policy => "yes"); $c->commit\'' . "\n" ;
$msg .= "\n#than install the $_ module by running: \n" ;
$msg .= "\nsudo perl -MCPAN -e 'install $_'\n\n\n" ;
$msg .= "\n # == STOP copy paste == \n\n\n" ;
$msg .= "\n # == START copy paste == " ;
$msg .= "\n# if you seem to be stuck in circular reference kind of loop try even :\n" ;
$msg .= "\nsudo perl -MCPAN -e 'CPAN::Shell->force(qw( install $_));'\n" ;
$msg .= "\n # == STOP copy paste == " ;
$msg .= "\n# You may end-up now with Ctrl + C \n\n\n" ;
return ( 1, "$msg") if $@;
} else {
say "[INFO ] == ok == check for prerequisite perl module : $_" if $PrintOkCheck == 1 ;
}
}
#eof foreach module
return ( 0 , "all required modules found" ) ;
}
#eof sub
# ??!!
#perl -MCPAN -e 'install Module::Signature'
# the following modules have been or might be part of the installable modules
#PDF::WebKit
#HTML::TreeBuilder
#HTML::TreeBuilder::XPath
#HTML::TableExtract
#HTML::ElementTable

- 5,114
- 1
- 56
- 53