We will look at how the contents of this array are constructed and can be manipulated to affect where Perl interpreter will find the module files.
Default @INC
Perl interpreter is compiled with a specific default value of @INC
that it was compiled with. To find out this value, run perl -V
command and in the out you will see something like this:
$ perl -V
...
@INC:
/usr/local/lib/perl5/5.8.6/i686-linux
/usr/local/lib/perl5/5.8.6
/usr/local/lib/perl5/site_perl/5.8.6/i686-linux
/usr/local/lib/perl5/site_perl/5.8.6
/usr/local/lib/perl5/site_perl/5.8.5/i686-linux
/usr/local/lib/perl5/site_perl/5.8.5
/usr/local/lib/perl5/site_perl
To change the default path when configuring Perl binary compilation, use otherlibdirs
variable:
Configure -Dotherlibdirs=/usr/lib/perl5/site_perl/5.8.1
Environmental variable PERL5LIB
(or PERLLIB
)
Perl pre-pends @INC
with a list of directories (colon-separated) contained in PERL5LIB
(if it is not defined, PERLLIB
is used) environmental variable of your shell.
-I
command line parameter
Perl pre-pends @INC
with a list of directories (colon-separated) passed in to it as a value of -I
command line parameter. This can be done in one of two ways, as usual with Perl parameters:
#!/usr/local/bin/perl -w -I /my/moduledir
- Pass it as part of
PERL5OPT
(or PERLOPT
) environmantal variable (see chapter 19.02 in Programming Perl)
Pass it via the use lib
pragma
Perl pre-pends @INC
with a list of directories passed in to it via use lib
pragma.
In a program:
use lib ("/dir1", "/dir2")
On the command line:
perl -Mlib=/dir1,/dir2
You can also remove the directories from @INC
via no lib
You can directly manipulate @INC
as a regular Perl array.
NOTE: Since @INC
us used during compilation phase, this must be done inside of a BEGIN {}
block, which precedes the use MyModule
statement;
Add directories to the beginning via unshift @INC, $dir
Add directories to the end via push @INC, $dir
Do anything else you can do with a Perl array.
NOTE The directories are unshifted onto @INC in the order listed in this answer, e.g. default @INC is last in the list, preceded by PERL5LIB, preceded by -I, preceded by "use lib" and direct @INC manipulation, the latter two mixed in whichever order they are in Perl code.
References:
There does not seem to be a comprehensive "@INC" FAQ-type post on StackOverflow, so this question is intended as one.
When to use each approach?
If the modules in a directory need to be used by many/all scripts on your site, especially run by multiple users, that directory should be included in default @INC compiled into Perl binary
If the modules in the directory will be used exclusively by a specific user for all the scripts that user runs (or if recompiling Perl is not an option to change default @INC in previous use case), set the users' PERL5LIB
, usually during user login.
NOTE: Please be aware of the usual Unix environment variable pitfalls - e.g. in certain cases running the scripts as a particular user does not guarantee running them with that user's environment set up, e.g. via su
.
If the modules in the directory need to be used only in specific circumstances (e.g. when the script(s) is executed in development/debug mode, you can either set PERL5LIB manually, or use "-I" perl parameter.
If the modules need to be used only for specific scripts, by ALL users using them, use use lib/no lib
pragmas in the program itself. It also should be used when the directory to be searched needs to be dynamically determined during runtime - e.g. from script's command line parameters or script's path (see FindBin module for very nice use case)
If the directories in @INC need to be manipulated according to some complicated logic, either impossible to too unwieldy to implement by combination of "use lib/no lib" pragmas, then use direct @INC
manipulation inside BEGIN {}
block or inside a special purpose library designated for @INC manipulation, which must be used by your script(s) before any other modules are used.
An example of this is automatically switching between libraries in prod/uat/dev directories, with waterfall library pickup in prod if it's missing from dev and/or UAT (the last condition makes the standard "use lib + FindBin" solution fairly complicated.
A detailed illustration of this scenario is in this SO post.
An additional use case for directly manipulating @INC
is to be able to add subroutine references or object references (yes, Virgina, @INC
can contain custom Perl code and not just directory names, as explained here)