52

How do I include a Perl module that's in a different directory? It needs to be a relative path from the module that's including it.

I've tried

push ( @INC,"directory_path/more_path");

also

push ( @INC,"directory_path\\more_path");
serenesat
  • 4,611
  • 10
  • 37
  • 53

6 Answers6

75

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;
Community
  • 1
  • 1
Andomar
  • 232,371
  • 49
  • 380
  • 404
  • After many attempts the code that finally worked was from the question that Andomar linked to: use FindBin; # locate this scriptuse lib "$FindBin::Bin/.."; # use the parent directory use EPMS; Thank you for all of your help everyone! –  May 08 '09 at 22:17
  • Cheers, looks like everyone read "current directory" where you wrote "module's directory". – Andomar May 08 '09 at 22:33
  • Came across this after reading http://stackoverflow.com/a/90721/2668831 which claims the FindBin method isn't robust for some forms of modular Perl organisation (someone else may be able to clarify) – Louis Maddox Nov 15 '15 at 20:15
15

Most likely the reason your push did not work is order of execution.

use is a compile time directive. You push is done at execution time:

push ( @INC,"directory_path/more_path");
use Foo.pm;  # In directory path/more_path

You can use a BEGIN block to get around this problem:

BEGIN {
    push ( @INC,"directory_path/more_path");
}
use Foo.pm;  # In directory path/more_path

IMO, it's clearest, and therefore best to use lib:

use lib "directory_path/more_path";
use Foo.pm;  # In directory path/more_path

See perlmod for information about BEGIN and other special blocks and when they execute.

Edit

For loading code relative to your script/library, I strongly endorse File::FindLib

You can say use File::FindLib 'my/test/libs'; to look for a library directory anywhere above your script in the path.

Say your work is structured like this:

   /home/me/projects/
    |- shared/
    |   |- bin/
    |   `- lib/
    `- ossum-thing/
       `- scripts 
           |- bin/
           `- lib/

Inside a script in ossum-thing/scripts/bin:

use File::FindLib 'lib/';
use File::FindLib 'shared/lib/';

Will find your library directories and add them to your @INC.

It's also useful to create a module that contains all the environment set-up needed to run your suite of tools and just load it in all the executables in your project.

use File::FindLib 'lib/MyEnvironment.pm'
daotoad
  • 26,689
  • 7
  • 59
  • 100
10

'use lib' can also take a single string value...

#!/usr/bin/perl
use lib '<relative-path>';
use <your lib>;
bedwyr
  • 5,774
  • 4
  • 31
  • 49
7

From perlfaq8:


How do I add the directory my program lives in to the module/library search path?

(contributed by brian d foy)

If you know the directory already, you can add it to @INC as you would for any other directory. You might use lib if you know the directory at compile time:

use lib $directory;

The trick in this task is to find the directory. Before your script does anything else (such as a chdir), you can get the current working directory with the Cwd module, which comes with Perl:

BEGIN {
    use Cwd;
    our $directory = cwd;
    }

use lib $directory;

You can do a similar thing with the value of $0, which holds the script name. That might hold a relative path, but rel2abs can turn it into an absolute path. Once you have the

BEGIN {
    use File::Spec::Functions qw(rel2abs);
    use File::Basename qw(dirname);

    my $path   = rel2abs( $0 );
    our $directory = dirname( $path );
    }

use lib $directory;

The FindBin module, which comes with Perl, might work. It finds the directory of the currently running script and puts it in $Bin, which you can then use to construct the right library path:

use FindBin qw($Bin);
brian d foy
  • 129,424
  • 31
  • 207
  • 592
  • Your second suggestion (using `cwd` inside a `BEGIN` block) does not seem to work. All I get is the following error: `Variable "$directory" is not imported at ./thingy line 16. // Global symbol "$directory" requires explicit package name at ./thingy line 16. // BEGIN not safe after errors--compilation aborted at ./thingy line 16.` – zrajm Dec 22 '14 at 16:00
  • You'd have to show me your code. It sounds like you might have quoted $directory in the import list. – brian d foy Jan 02 '15 at 17:16
2

I'm surprised nobody has mentioned it before, but FindBin::libs will always find your libs as it searches in all reasonable places relative to the location of your script.

#!/usr/bin/perl
use FindBin::libs;
use <your lib>;
Juan A. Navarro
  • 10,595
  • 6
  • 48
  • 52
0

I'll tell you how it can be done in eclipse. My dev system - Windows 64bit, Eclipse Luna, Perlipse plugin for eclipse, Strawberry pearl installer. I use perl.exe as my interpreter.

Eclipse > create new perl project > right click project > build path > configure build path > libraries tab > add external source folder > go to the folder where all your perl modules are installed > ok > ok. Done !

big_space
  • 71
  • 2
  • 10