Test for existence of perl mod inside script

Go To StackoverFlow.com

0

Based on the answer provided here, I am attempting to validate whether or not a perl module is installed. For this, I have:

# &getYN and &prompt are only included here for completeness
sub getYN {
    unless ( $autoyes =~ /[Yy]/ ) {
        my ( $prompt, $default ) = @_;
        my $defaultValue = $default ? "[$default]" : "";
        print "$prompt $defaultValue: ";
        chomp( my $input = <STDIN> );
        return $input ? $input : $default;
    } else {
        return "Y";
    }
}

sub prompt {
    my ( $prompt, $default ) = @_;
    my $defaultValue = $default ? "[$default]" : "";
    print "$prompt $defaultValue: ";
    chomp( my $input = <STDIN> );
    return $input ? $input : $default;
}

&chklib("RRDTool::OO");
sub chklib {
    my $lib = shift;
    eval { require $lib; };
    if ($@) {
        print "You are missing a required Perl Module: $lib\n";
        my $ok = &getYN( "Shall I attempt to install it for you?", "y" );
        if ( $ok =~ /[Yy]/ ) {
            require CPAN;
            CPAN::install($lib);
        } else {
            print "Installation requires $lib\n";
            exit;
        }
    }
}

This runs as expected, but for some reason, the eval returns that I don't have RRDTool::OO installed, when, in fact, I do.

If I create an empty file and run:

# File foo.pl
use strict;

$| = 1; 

use RRDTool::OO;

Then I get no errors.

But when I run the first file with print $@;, it returns:

Can't locate RRDTool::OO in ...

What am I doing wrong?

2012-04-04 17:03
by Clayton Dukes


2

You have to check the result of the eval, like

if (eval("require xxx;")) {
     print "you have it\n";
} else {
     print "you don't\n";
}
2012-04-04 17:19
by ShinTakezou
And you can check the docs on "require" to see why the quotes are helpful in this case: http://perldoc.perl.org/functions/require.htm - oalders 2012-04-04 17:22
@oalders yes, I've done it thinking about xxx written as "the right thing" (without even asking myself what it would be): I was just pointing the way I would check if eval is successful or not - ShinTakezou 2012-04-04 17:29
@ShinTakezou Sorry, I meant the comment to be for the OP and not for you. I just wanted to point out that I didn't think his example would work without the quotes, which you correctly supplied in your answer. : - oalders 2012-04-04 18:09
Hmm, now that it is working. If I add a use blah: after the check, the script still fails. How do I test for it, install it and then use it after it is installed - Clayton Dukes 2012-04-04 20:26
@ClaytonDukes At this point your script has compiled, so you'll need a second "require" rather than a "use" - oalders 2012-04-05 03:09
@ClaytonDukes You may also want to have a look at https://metacpan.org/module/Class::Loa - oalders 2012-04-05 11:39


2

What is happening is that

$lib = "RRDTool::OO";
eval { require $lib }

is executed with the stringified expression

require "RRDTool::OO"

not the bareword style

require RRDTool::OO

so it is looking for a file called RRDTool::OO in your @INC path instead of a file called RRDTool/OO.pm.

If you want to use require at run-time with a variable expression, you'll want to either use the stringy form of eval

eval "require $lib"

or process the arg to require yourself

$lib = "RRDTool::OO";
$lib =~ s{::}{/}g;
eval { require "$lib.pm" }
2012-04-04 17:22
by mob
Ads