|
When using modules that are not installed in the standard directories of Perl, we need to change @INC so perl will be able to find them. There are several ways to do that solving different use cases.
Loading your private Perl moduleYou have a script and have just started to move some parts of it, out to a new module called My::Module. You saved the module to /home/foobar/code/My/Module.pm. Your perl script now starts like this: use strict; use warnings; use My::Module When you run the script you get a friendly error message like this:
Can't locate My/Module.pm in @INC (@INC contains:
/home/foobar/perl5/lib/perl5/x86_64-linux-gnu-thread-multi
/home/foobar/perl5/lib/perl5
/etc/perl
/usr/local/lib/perl/5.12.4
/usr/local/share/perl/5.12.4
/usr/lib/perl5 /usr/share/perl5
/usr/lib/perl/5.12
/usr/share/perl/5.12
/usr/local/lib/site_perl
.).
BEGIN failed--compilation aborted.
Perl cannot find your module.
Upgrading a Perl moduleOn a system you are thinking to upgrade a module that came from CPAN. You don't want to install it in the standard location yet. First you'd like to put it in some private directory, try it, and install to the system only once you are sure it works well. In this case too you "install" the module in a private directory, e.g. in /home/foobar/code and somehow you'd like to convince perl to find that version of the module and not the one that was installed in the system.
The use statementWhen perl encounters use My::Module it goes over the elements of the built-in @INC module that contains directory names. In each directory it check if there is a subdirectory called "My" and if in that subdirectory there is a file called "Module.pm". The first such file it encounters will be loaded into memory. If it does not find the file you get the above error messages. @INC is defined when perl is compiled and it is embedded in the binary code. You cannot change that, unless you recompile perl. Not something we would do every day. Luckily the @INC array can be changed in several ways when we execute a script. We'll see these solutions and discuss when each one of them is appropriate to use.
PERLLIB and PERL5LIBYou can define the PERL5LIB environment variable (though PERLLIB works the same way, I'd recommend using PERL5LIB over PERLLIB as that makes it clear it is related to Perl 5) the same way you can define the PATH environment variable. Every directory listed in this variable will be added to the beginning of @INC. In Bash, in the above case, you would write export PERL5LIB=/home/foobar/code You can add this to the ~/.bashrc to make it always available when you log-in. In Windows you can set the same by going through Right-click My Computer and click Properties. In the System Properties window, click on the Advanced tab. In the Advanced section, click the Environment Variables button. In the Environment Variables window click on New.
This will add the private /home/foobar/code directory to the beginning of @INC for every script that is executed in the same environment. In taint mode, that will be explained in a separate post, the PERLLIB and PERL5LIB environement variables are ignored.
use libAdding a use lib statement to the script will add the directory to @INC for that specific script. Regardless who and in what environment runs it. You just have to make sure have the use lib statement before trying to load the module: use lib '/home/foobar/code'; use My::Module; One note here. I saw several companies where use lib statements were added to the modules so they will be able to load their dependencies. I don't think this is right. I think the right place to change @INC is the main script or even better, outside the script such as in the two other solutions.
-I on the command lineThe last solution is the most temporary solution. Add a -I /home/foobar/code flag to perl when running the script. perl -I /home/foobar/code script.pl This will add /home/foobar/code to the beginning of @INC for this specific execution of the script.
So which way to use?If you would like to just test a newer version of a module, I'd recommend the command line flag: perl -I /path/to/lib. If you are installing lots of modules in a private directory then I'd probably use PERL5LIB though we'll also see local::lib that does this for you. use lib is used in two cases: One: When you have a fixed, but not standard company-wide environment in which you put modules in a common standard location. Two: When you are developing an application and you'd like to make sure the script always picks up the modules relative to their own location. We'll discuss this in another post.
Perl tutorial and video courseFor further articles see the Beginner Perl Maven tutorial book and video course.In the comments, please wrap your code snippets within <pre> </pre> tags and use spaces for indentation. blog comments powered by Disqus |
Follow me: