Perl Library Path

perl library path

This answer assumes that the module is in fact installed, but not in a place that perl is looking for.

Generally, the Perl module Statistics::Distributions will be contained in a file called Statistics/Distributions.pm. On Linux and similar systems, one can search for these files quickly with the locate command:

locate Statistics/Distributions.pm

If it is installed, locate will spit out a line similar to

/opt/my_perl/lib/Statistics/Distributions.pm

You can then instruct the perl interpreter to look in this path, too, in various ways. One is to define the environment variable PERL5LIB, i.e. from bash:

prompt> PERL5LIB=/opt/my_perl/lib/ ./myscript.pl

Or you can use the perl -I switch:

prompt> perl -I/opt/my_perl/lib/ ./myscript.pl

Or you can modify the script to use lib; there is more than one way to do it ;-)

How can I find out where a Perl module is installed?

Note: This solution proposes use of a (self-authored) utility that you must download. While it offers what I believe to be helpful features, installing a third-party solution first is not an option for everyone.


I've created whichpm, a cross-platform CLI (Linux, macOS, Window) that locates installed Perl modules by module (package) name, and optionally reports information about them, including detection of accidental duplicates.

Examples

# Locate the Data::Dumper module.
$ whichpm Data::Dumper
/usr/lib/perl/5.18/Data/Dumper.pm

# Locate the Data::Dumper module, and also print
# version information and core-module status.
$ whichpm -v Data::Dumper
Data::Dumper 2.145 core>=5.005 /usr/lib/perl/5.18/Data/Dumper.pm

# Locate the Data::Dumper module and open it in your system's default text
# editor.
$ whichpm -e Data::Dumper

# Look for accidental duplicates of the Foo::Bar module.
# Normally, only 1 path should be returned.
$ whichpm -a Foo::Bar
/usr/lib/perl/5.18/Foo/Bar.pm
./Foo/Bar.pm

# Print the paths of all installed modules.
$ whichpm -a

Installation

Prerequisites: Linux, macOS, or Windows, with Perl v5.4.50 or higher installed.

Installation from the npm registry

With Node.js or io.js installed, install the package as follows:

[sudo] npm install whichpm -g

Manual installation (macOS and Linux)

  • Download the CLI as whichpm.
  • Make it executable with chmod +x whichpm.
  • Move it or symlink it to a folder in your $PATH, such as /usr/local/bin (OSX) or /usr/bin (Linux).

Perl library path/s

print the contents of the @INC variable:

perl -e 'print "@INC\n";'

@INC contains all the paths that Perl will search to find a module.

How do I include a Perl module that's in a different directory?

EDIT: Putting the right solution first, originally from this question. It's the only one that searches relative to the module directory:

use FindBin;                 # locate this script
use lib "$FindBin::Bin/.."; # use the parent directory
use yourlib;

There's many other ways that search for libraries relative to the current directory. You can invoke perl with the -I argument, passing the directory of the other module:

perl -I.. yourscript.pl

You can include a line near the top of your perl script:

use lib '..';

You can modify the environment variable PERL5LIB before you run the script:

export PERL5LIB=$PERL5LIB:..

The push(@INC) strategy can also work, but it has to be wrapped in BEGIN{} to make sure that the push is run before the module search:

BEGIN {push @INC, '..'}
use yourlib;

Calling a Perl Module which is Installed in different path/directory

$RealBin is the directory in which the script is located. ($Bin is a broken version of the same thing.)

If there's no relationship between the directory in which the script is located and the directory in which a module is located, it doesn't make sense to use $RealBin. In fact, it usually makes more sense to use the PERL5LIB env var than use lib in such cases.

On the other hand, if the script was located in /path/to/bin, it might make sense to use a path relative to $RealBin.

use lib                 # In /path/to/bin/script,
"$RealBin/../lib1", # This is /path/to/bin/../lib1, or /path/to/lib1
"$RealBin/../lib2", # This is /path/to/bin/../lib2, or /path/to/lib2
"$RealBin/../lib3"; # This is /path/to/bin/../lib3, or /path/to/lib3

$RealBin is usually used when the script and modules are packaged together (part of the same project). Same for use lib, really.

perl - package name: Can I use path from root?

The module namespace is relative to @INC directories only. These are by default set up according to where Perl was installed, with privlib (core modules installed with Perl), sitelib (modules installed by a CPAN client), and vendorlib (modules installed by a vendor package manager), and architecture-specific versions of each of these. Additional @INC directories may be added by local::lib, and before Perl 5.26 @INC also included . (the current working directory), but this was a bad idea.

When you invoke use or require on a bareword package name, it does the translation you described (convert :: to path separator and append .pm), and then appends it to each directory in @INC until it finds a file. (It also checks for .pmc but this is rarely relevant.) The package statement inside the file is expected to match the module path used to look it up for the import component of use.

You can modify @INC manually, but it is best to do it with one of the following mechanisms, so that architecture-specific and version-specific subdirectories will be respected if present.

  • lib - use lib '/path/to/lib';
  • -I - perl -I/path/to/lib ...
  • PERL5LIB - env PERL5LIB=/path/to/lib perl ...

These options should only be used to insert absolute paths into @INC, since relative paths will have the same vulnerability as . used to, in that they may mean something different when the current directory is changed. To add a path relative to the script wherever it may be, lib::relative can be installed to simplify the process, or its documentation describes equivalent functionality using core modules.

use lib::relative '../lib';

Once you have added your custom location(s) to @INC, that directory will be searched first for any further use calls.

use Foo::Bar; # now checks /path/to/lib/Foo/Bar.pm first
# which should contain package Foo::Bar

Adding a path to @INC but not within the Perl script

From what I can gather of your description, the PERL5LIB seems to be a good solution.

I don't know what you mean by "PERL5LIB checks the modules in the directory but not recursive", but PERL5LIB is a shell variable, normally set in your shell configuration files (while this can also be done dynamically), to a list of directories. From Environment (perlrun), the PERL5LIB is

A list of directories in which to look for Perl library files before looking in the standard library and the current directory. [...]

So you can set it to a suitable list of directories that covers all that is needed.

Make sure that it is an environment variable, by using export in [ba]sh

export PERL5LIB="/path/to/dir1:/other/path/dir2:$HOME/inhome/dir3"

where the quotes are there in case there are spaces in directory names. This line is normally entered in the file ~/.bashrc

Or, use setenv if in [t]csh, with a following line to add to ~/.tcshrc

setenv PERL5LIB "/path/to/dir1:/other/path/dir2:$HOME/inhome/dir3" 


Related Topics



Leave a reply



Submit