aks
aks

Reputation: 25347

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

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.

Upvotes: 65

Views: 53955

Answers (10)

armagedescu
armagedescu

Reputation: 2160

The path can be included in perl script in first line, marked with #!

#!/usr/bin/perl -I.
use anymodule;

Upvotes: 3

Robert
Robert

Reputation: 511

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)

Upvotes: 8

Chas. Owens
Chas. Owens

Reputation: 64909

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.

Upvotes: 3

Vikas
Vikas

Reputation: 2028

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.

Upvotes: 4

user80168
user80168

Reputation:

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.

Upvotes: 57

Denis Komnenovic
Denis Komnenovic

Reputation: 11

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.

Upvotes: 0

Juan A. Navarro
Juan A. Navarro

Reputation: 11025

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

Upvotes: 0

Andreas Schuh
Andreas Schuh

Reputation: 1257

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";

Upvotes: 84

Gurunandan Bhat
Gurunandan Bhat

Reputation: 3562

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.

Upvotes: 0

brian d foy
brian d foy

Reputation: 132719

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.

Upvotes: 15

Related Questions