views:

1320

answers:

4

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.
+2  A: 

Take a look at Par::Packer, it creates an executable with all of the scripts 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.

Chas. Owens
+14  A: 

The simplest approach I found it to use FindBind 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.

depesz
Don't forget that abs_path returns tainted result in taint mode. You must use `use lib (abs_path("$FindBin::Bin/../lib")=~m{^(/.*)})[0];` or just use `use lib "$FindBin::Bin/../lib";` beacuse there is no reason to canonize path.
Hynek -Pichi- Vychodil
+5  A: 

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.

brian d foy
I read perlfaq8 later the same day and found the answer I needed in your contributed article. I wonder why you did include the second method (use Cwd) though since @INC already has an entry for the current directory - '.'
muteW
A: 

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.

Gurunandan