I have been given a few Perl scripts to deploy.
What is the easiest way to find and install all modules used by these scripts?
EDIT:
From what I can find there are no conditional includes or includes in evals.
I have been given a few Perl scripts to deploy.
What is the easiest way to find and install all modules used by these scripts?
EDIT:
From what I can find there are no conditional includes or includes in evals.
Well this is the very simplistic way I solved this.
In a bash shell:
cat *.pl | grep "^use " | tr ';' ' ' | while read a b c; do echo $b; done | sort -iu > modules.txt
This gave me a file with only the module names, one on each line.
I then used this
cat modules.txt | while read a; do cpan $a; done
to invoke cpan to each module name in the file. And then sat there answering yes to CPAN's questions to install dependencies as appropriate.
Not pretty but this time it got the job done.
I was hoping Module::ScanDeps which provides the command line utility scandeps.pl would be useful here but, to my dismay, Module::ScanDeps
is apparently not intended for this particular purpose as scandeps.pl
either ignores missing modules or (with -c
or -x
) croaks when the script uses a module that is not installed.
Here is a quick'n'dirty Perl script that tries to execute the script using do until it succeeds:
#!/usr/bin/perl
use strict;
use warnings;
use Term::Prompt;
my ($script) = @ARGV;
die "Provide script file name on the command line\n"
unless defined $script;
until ( do $script ) {
my $ex = $@;
if ( my ($file) = $ex =~ /^Can't locate (.+?) in/ ) {
my $module = $file;
$module =~ s/\.(\w+)$//;
$module = join('::', split '/', $module);
print "Attempting to install '$module' via cpan\n";
system(cpan => $module);
last unless prompt(y => 'Try Again?', '', 'n');
}
else {
die $ex;
}
}
If you do not want the script to be run, you can run perl -c $script
, capture stderr
output of that and parse for missing module messages and call cpan
for each such module found until perl -c $script
outputs "Syntax OK". That gives you a cleaner loop too. I'll look at this later.
You might miss dependencies loaded at run time using this technique.
Or let PAR's pp do the work for you in collecting together everything you need in a single executable.
Does my Module::Extract::Use help? It should be able to pull out the modules named in the various import statements and give you a list.
Once you have that list, which is only the first level of dependencies, you can make a script distribution that allows people to use the normal CPAN toolchain to install everything.