We will look at how the contents of this array are constructed and can be manipulated to affect where the Perl interpreter will find the module files.
-
Default
@INC
Perl interpreter is compiled with a specific
@INC
default value. To find out this value, runenv -i perl -V
command (env -i
ignores thePERL5LIB
environmental variable – see #2) and in the output you will see something like this:$ env -i perl -V ... @INC: /usr/lib/perl5/site_perl/5.18.0/x86_64-linux-thread-multi-ld /usr/lib/perl5/site_perl/5.18.0 /usr/lib/perl5/5.18.0/x86_64-linux-thread-multi-ld /usr/lib/perl5/5.18.0 .
Note .
at the end; this is the current directory (which is not necessarily the same as the script’s directory). It is missing in Perl 5.26+, and when Perl runs with -T
(taint checks enabled).
To change the default path when configuring Perl binary compilation, set the configuration option otherlibdirs
:
Configure -Dotherlibdirs=/usr/lib/perl5/site_perl/5.16.3
-
Environmental variable
PERL5LIB
(orPERLLIB
)Perl pre-pends
@INC
with a list of directories (colon-separated) contained inPERL5LIB
(if it is not defined,PERLLIB
is used) environment variable of your shell. To see the contents of@INC
afterPERL5LIB
andPERLLIB
environment variables have taken effect, runperl -V
.$ perl -V ... %ENV: PERL5LIB="/home/myuser/test" @INC: /home/myuser/test /usr/lib/perl5/site_perl/5.18.0/x86_64-linux-thread-multi-ld /usr/lib/perl5/site_perl/5.18.0 /usr/lib/perl5/5.18.0/x86_64-linux-thread-multi-ld /usr/lib/perl5/5.18.0 .
-
-I
command-line optionPerl pre-pends
@INC
with a list of directories (colon-separated) passed as value of the-I
command-line option. This can be done in three ways, as usual with Perl options:-
Pass it on command line:
perl -I /my/moduledir your_script.pl
-
Pass it via the first line (shebang) of your Perl script:
#!/usr/local/bin/perl -w -I /my/moduledir
-
Pass it as part of
PERL5OPT
(orPERLOPT
) environment variable (see chapter 19.02 in Programming Perl)
-
-
Pass it via the
lib
pragmaPerl pre-pends
@INC
with a list of directories passed in to it viause lib
.In a program:
use lib ("/dir1", "/dir2");
On the command line:
perl -Mlib=/dir1,/dir2
You can also remove the directories from
@INC
viano lib
. -
You can directly manipulate
@INC
as a regular Perl array.Note: Since
@INC
is used during the compilation phase, this must be done inside of aBEGIN {}
block, which precedes theuse 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:
- perldoc perlmod
- perldoc lib
- Perl Module Mechanics – a great guide containing practical HOW-TOs
- How do I ‘use’ a Perl module in a directory not in
@INC
? - Programming Perl – chapter 31 part 13, ch 7.2.41
- How does a Perl program know where to find the file containing Perl module it uses?
There does not seem to be a comprehensive @INC
FAQ-type post on Stack Overflow, 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 the default
@INC
compiled into the 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 pass the-I
option to perl. -
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 the script’s command line parameters or script’s path (see the 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 ofuse lib
/no lib
pragmas, then use direct@INC
manipulation insideBEGIN {}
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 How do I use beta Perl modules from beta Perl scripts?. -
An additional use case for directly manipulating
@INC
is to be able to add subroutine references or object references (yes, Virginia,@INC
can contain custom Perl code and not just directory names, as explained in When is a subroutine reference in @INC called?).