How can my Perl script find its module in the same directory?

PerlModuleDirectory

Perl Problem Overview


I recently wrote a new Perl script to kill processes based on either process name / user name and extended it using Classes so that I could reuse the process code in other programs. My current layout is -

/home/mutew/src/prod/pskill       <-- Perl script
/home/mutew/src/prod/Process.pm   <-- Package to handle process descriptions

I added ~/src/prod in my $PATH variable to access the script from anywhere. On running the script from any directory other than its resident directory leads to a "Can't locate Process.pm in @INC" (which is understandable given that other than the shared directories in /usr, @INC includes only the current directory - '.'). One workaround that I have been using is the use lib directive as so -

use lib '/home/mutew/src/prod';

but this is a major portability issue. Any solutions which will also allow me to export the script to other systems without and changes?


EDIT

  1. I chose 'depesz' answer as the correct one because of its simplicity and core module usage.
  2. brian d foy's answer though suggests other methods to accomplish the same (TMTOWTDI), his contribution in perlfaq8 renders this question absolutely redundant.

Perl Solutions


Solution 1 - Perl

I am curious why the simplistic solution

use File::Basename;
use lib dirname (__FILE__);
use SomeModuleLocatedInTheSameDirectoryAsThisPerlScriptOrModule;

did not come up. The FindBin module seems to have some issues if the file is not the main executable perl script, but simply a non-executable Perl module. At least that's how I interpret the comment in the documentation. Did not really test it.

To have any other path relative to the location of this Perl file, do something like

use File::Basename;
use lib dirname (__FILE__) . "/MyModules";

Solution 2 - Perl

The simplest approach I found it to use FindBin module. Like this:

use FindBin;
use lib $FindBin::Bin;

Generally I prefer to have my scripts provided in such a way that programs are in whatever/bin, and libraries are in whatever/lib

In these situations I use a slightly more complicated approach:

use Cwd qw(abs_path);
use FindBin;
use lib abs_path("$FindBin::Bin/../lib");

The abs_path call is to make the @INC contain whatever/lib, and not whatever/bin/../lib - it's just a slight change, but makes reading error messages easier.

Solution 3 - Perl

From perlfaq8, which answers "How do I add a directory to my include path (@INC) at runtime?". There are several other answers for questions around this issue too.


How do I add a directory to my include path (@INC) at runtime?

Here are the suggested ways of modifying your include path, including environment variables, run-time switches, and in-code statements:

the PERLLIB environment variable

$ export PERLLIB=/path/to/my/dir
$ perl program.pl

the PERL5LIB environment variable

$ export PERL5LIB=/path/to/my/dir
$ perl program.pl

the perl -Idir command line flag

$ perl -I/path/to/my/dir program.pl

the use lib pragma:

use lib "$ENV{HOME}/myown_perllib";

The last is particularly useful because it knows about machine dependent architectures. The lib.pm pragmatic module was first included with the 5.002 release of Perl.

Solution 4 - Perl

Besides the already stated solutions:

  1. use FindBin / lib
  2. Perl Faq 8 How do I add a directory to my include path (@INC) at runtime?

'The simplest approach' (™) that I use while dev/testing a module prior to deploying it (in /usr/local/lib/site_perl/ or elsewhere in @INC) is to modify @INC before loading the module as follows:

#!/usr/bin/perl
use strict;
use warnings;
# Modify @INC prior to module loading.
BEGIN { unshift @INC, '.'; }
use YourModuleInCWD;

(Add current working directory to @INC? - PerlMonks)

Solution 5 - Perl

Take a look at Par::Packer. It creates an executable with all of the script's dependencies included. It makes distribution easy. You also could also provide your users a version of your module that can be installed on their systems. See Module::Starter for an easy way to build all of the files required to make a standard CPAN-style distribution.

Solution 6 - Perl

You can make perl look in any directory by using the -I flag. Here, -I stands for @INC which is the array of paths in which perl looks for modules. Using -I adds the given path to the @INC array for this execution.

eg:

perl -I lib bin/script.pl

where lib contains the modules I want to use.

I know that this works for perl 5. I am not at sure about other versions.

Solution 7 - Perl

To convert relative links to absolute and add to @INC, I normally use ex::lib. Of course, this is useful only if you plan to keep the relative locations of the script and the module identical on all machines where you plan to run your script.

Solution 8 - Perl

Just keep it simple. There is no need to import any libraries; just find out your current working directory:

use lib "$ENV{PWD}/relativ_path_own_perllib";

For similar problems, you can read out the environment variable which gives your information about where you are, your home directory, operating system stuff, and so on, with just one row of programming code in the shell-terminal, like:

perl -e 'map { print; print " : ". $ENV{$_}." \n\r"; } sort keys %ENV '

There is no need to bind some libraries; just use the %ENV-Hash.

Solution 9 - Perl

FindBin::libs will find all your libs placed at reasonable places relative to the path from where your script is running.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionaksView Question on Stackoverflow
Solution 1 - PerlAndreas SchuhView Answer on Stackoverflow
Solution 2 - Perluser80168View Answer on Stackoverflow
Solution 3 - Perlbrian d foyView Answer on Stackoverflow
Solution 4 - PerlRobertView Answer on Stackoverflow
Solution 5 - PerlChas. OwensView Answer on Stackoverflow
Solution 6 - PerlVikasView Answer on Stackoverflow
Solution 7 - PerlYa. PerelmanView Answer on Stackoverflow
Solution 8 - PerlDenis KomnenovicView Answer on Stackoverflow
Solution 9 - PerlJuan A. NavarroView Answer on Stackoverflow