linuxperl

Making perl modules local, recognizing for some but not others


I have a script that looks at local modules in /home/con/nwchem/ionize/nwchem.info/:

#!/usr/bin/env perl

use FindBin 1.51 qw( $RealBin ); # use local versions so users don't have to install
use lib "$RealBin/lib";
use strict;
use feature 'say';
use warnings FATAL => 'all';
use autodie ':default';
use Devel::Confess 'color';
use JSON 'encode_json';
use DDP {output => 'STDOUT', array_max => 10, show_memsize => 1};
#use re 'debugcolor';
use Module::Path 'module_path';

foreach my $module ('JSON', 'DDP', 'Devel::Confess') {
    my $path = module_path($module);
    if (defined($path)) {
      print "$module\t$path\n";
    } else {
      print "Danger Will Robinson!\n";
    }
}

where 3 files are contained in the same directory: DDP.pm, JSON.pm, and Confess.pm

this outputs:

JSON    /home/con/nwchem/ionize/nwchem.info/JSON.pm
DDP /home/con/nwchem/ionize/nwchem.info/DDP.pm
Devel::Confess  /home/con/perl5/perlbrew/perls/perl-5.40.1/lib/site_perl/5.40.1/Devel/Confess.pm

so JSON and DDP are being loaded locally, but Devel::Confess is not.

I have tried

use lib "$RealBin/lib";

and

use lib $Realbin;

and

use lib "$RealBin/.";

but none point Perl to loading Devel::Confess from the current directory. I'm guessing that it has something to do with the :: in the name.

I've also created a symbolic link in a Devel directory, ln -s Confess.pm Devel/ but that didn't work either.

@INC is

[
    [0] "/home/con/nwchem/ionize/nwchem.info",
    [1] "/home/con/perl5/perlbrew/perls/perl-5.40.1/lib/site_perl/5.40.1/x86_64-linux",
    [2] "/home/con/perl5/perlbrew/perls/perl-5.40.1/lib/site_perl/5.40.1",
    [3] "/home/con/perl5/perlbrew/perls/perl-5.40.1/lib/5.40.1/x86_64-linux",
    [4] "/home/con/perl5/perlbrew/perls/perl-5.40.1/lib/5.40.1"
] (591B)

How can I get Devel::Confess to be loaded from the current directory /home/con/nwchem/ionize/nwchem.info/?


Solution

  • Perl looks for modules in @INC. You can modify this array, for example by specifying the -I (include) flag when calling perl, or with the lib pragma.

    Perl module names can have a structure / hierarchy in their names, where the name components are separated by ::, like in File::Slurper. This makes it easy to find modules. Not all modules under a key are necessarily by the same author, e.g,. you have different modules under Test::. The module hierarchy is reflected in the path where the .pm file of a module lives, for example, a Foo::Bar::Baz module would live in a file called Baz.pm in directory / folder named Bar within a directory named Foo.

    To point Perl to a module path, you need to point it to the root folder where the module lives, if Foo from the above example is in /home/me/perl/modules (for /home/me/perl/modules/Foo/Bar/Baz.pm), you use perl -I/home/me/perl/modules/, and then in your code use Foo::Bar::Baz;.