The
@INC
array contains a list of directories that are consulted every time a
do
,
require
, or
use
compiles code from another file, library, or module. You can print these out easily from the command line:
% perl -e 'for (@INC) { printf "%d %s\n", $i++, $_ }'
0 /usr/local/perl/lib/i686-linux/5.004
1 /usr/local/perl/lib
2 /usr/local/perl/lib/site_perl/i686-linux
3 /usr/local/perl/lib/site_perl
4 .
The first two directories, elements 0 and 1 of
@INC
, are the standard architecture-dependent and architecture-independent directories, which all standard libraries, modules, and pragmas will go into. You have two of them because some modules contain information or formatting that makes sense only on that particular architecture. For example, the Config module contains information that cannot be shared across several architectures, so it goes in the 0th array element. Modules that include compiled C components, such as
Socket.so
, are also placed there. Most modules, however, go in the platform-independent directory in the 1st element.
The next pair, elements 2 and 3 above, fulfills roles analogous to elements 0 and 1, but on a site-specific basis. Suppose you have a module that didn't come with Perl, like a module from CPAN or one you wrote yourself. When you or (more likely) your system administrator installs this module, its components go into one of the site-specific directories. You are encouraged to use these for any modules that your entire site should be able to access conveniently.
The last standard component,
"."
(your current working directory), is useful only when developing and testing your software, not when deploying it. If your modules are in the same directory that you last
chdir
ed to, you're fine. If you're anywhere else, it doesn't work.
So sometimes none of the
@INC
directories work out. Maybe you have your own personal modules. Perhaps your project group has particular modules that are relevant only to that project. In these cases, you need to augment the standard
@INC
search.
The first approach involves using a command-line flag,
-I
dirlist
. The
dirlist
is a colon-separated[
] list of one or more directories, which will be prepended to the front of the
@INC
array. This works well for simple command lines, and thus can be used on a per-command basis, such as when you call a quick one-liner from a shell script.
This technique should not be included in the
#!
(pound-bang) line. First, it's not much fun to modify each program. More importantly, some older operating systems have bugs related to how long that line can be, typically 32 characters, including the
#!
part. That means if you have a very long path, such as
#!/opt/languages/free/extrabits/perl
, you may get the mysterious
"Command
not
found"
error. Perl does its best to rescan the line manually, but it's still too dicey to rely on.
Often, a better solution is to set the
PERL5LIB
environment variable. This can be done in your shell start-up file. Or, your system administrator may want to do so in a systemwide start-up file so all users can benefit. For example, suppose you have all your own modules in a directory called
~/perllib
. You would place one of the following lines in your shell start-up file, depending on which shell you use:
# syntax for sh, bash, ksh, or zsh
$ export PERL5LIB=$HOME/perllib
# syntax for csh or tcsh
% setenv PERL5LIB ~/perllib
Probably the most convenient solution from your users' perspective is for you to add a
use
lib
pragma near the top of your script. That way the users of the program don't need to take any special action to run your program. Imagine a hypothetical project called Spectre whose programs rely on its own set of libraries. Those programs could have a statement like this at their start:
use lib "/projects/spectre/lib";
What happens when you don't know the exact path to the library? Perhaps you've allowed the whole project to be installed in an arbitrary path. You could create an elaborate installation procedure to dynamically update the script, but even if you did, paths would still be frozen at installation time. If someone moved the files later, the libraries wouldn't be found.
The
FindBin module conveniently solves this problem. This module tries to compute the full path to the executing script's enclosing directory, setting an importable package variable called
$Bin
to that directory. Typical usage is either to look for modules in the same directory as the program or in a
lib
directory at the same level.
To demonstrate the first case, suppose you have a program called
/wherever/spectre/myprog
that needs to look in
/wherever/spectre
for its modules, but you don't want to hardcode that path.
use FindBin;
use lib $FindBin::Bin;
The second case would be used if your program lives in
/wherever/spectre/bin/myprog
but needs to look at
/wherever/spectre/lib
for its modules.
use FindBin qw($Bin);
use lib "$Bin/../lib";