Question

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.

Was it helpful?

Solution

Does my Module::Extract::Use help? There's an extract_modules program in the examples directory:

$ examples/extract_modules -l some_program
 File::Spec
 File::Spec::Functions
 strict
 warning

You can pipe that list to cpan.

$ examples/extract_modules -l some_program | xargs cpan

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.

If there's something that doesn't work for you, modify the program to handle that. If you think it would be useful to other people, send a pull request. :)

OTHER TIPS

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.

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.

Or let PAR's pp do the work for you in collecting together everything you need in a single executable.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top