How to find out and control where the Perl modules stored locally?
Failing that, I at least need to update @INC , so I can refer to the module; so my second question is:
I can’t issue make install after compiling, and moreover, I’ve been asked not to. (I’ve been asked to design the script so that it doesn’t rely on external modules being in the standard system path.)
I hope you don’t mind — I’ve taken the liberty of shortening your question, so that more people will read it, and so you can hopefully get better answers.
@ruakh, No, I don’t mind. I just made it that long so that people stop confusing things, like they did with my other posting about that topic. That’s why it was the «OT» comment in the beginning and the last comment in the end about better explanation «this time». 😉
3 Answers 3
perl modules should either be installed with the distributions’s system, like you did with gentoo or pkg_add on BSD, etc. or by using CPAN. Don’t do what you’re doing, that is going to confuse you & the system.
Wouldn’t it try to install the module in the standard system path? It might very well be OK on Windows, but not on Linux, where you need a root password.
CPAN is the right answer, it can install system-wide or in a private directory of yours. Read its man page for the details.
You can use local::lib to install Perl modules in a custom directory. Modules so installed can be used from Perl scripts:
use local::lib '/path/to/custom/directory'; # Custom modules can be `use`d from hereon
cpanm uses local::lib internally when you use the -l or -L flag. To install a module in the current directory:
«cpanm -1. DBI». This is number 1 or small letter l? Also is «cpanm» part of standard Perl installation on Linux? Finally I want to install them in ~/modules so I do: «cd ~/modules; cpanm -1. DBI», correct? And this way it will update @INC variable, right?
It is the letter l and not the digit 1 . cpanm is not part of standard Perl and you will have to install it manually. To install to ~/modules , you can use: cpanm -l~/modules DBI . In the program: use local::lib ‘~/modules’ will automatically modify @INC for you.
I don’t have ‘cpanm’ program on the remote machine and I can’t control what is going in there. How/where I can get/install this program? Thank you.
The installation directory is set when the makefile for the module is built. Each module comes with a Makefile.PL which must be run to build the makefile, taking into account the current Perl configuration. Makefile.PL has the option PREFIX that says where the build is going to be installed, so after unpacking the module’s distribution and cd ing to the unpacked directory you can say
perl Makefile.PL PREFIX=/module/directory/path make test make install
This process is described in the Perl documentation — read perldoc perlmodinstall . You could go into the CPAN shell and use the ‘o’ (lower-case) oprion that allows you to change the options passed to makefile.PL , but I think the manual build/test/install is more straightforward and gives you more control over the process.
use lib qw(/module/directory/path);
to the start of your program to make sure Perl searches the new directory for modules.
perl library path
We’re here to help. Please give us your username and password and the name or IP address of a machine on your cluster. One of us will be happy to poke around and see where the libraries can be found. [Edit: smiley face]
Your question (as of know) is too vague. I understand it as: a script of yours tries to load some modules, and fails. Please edit the question to add the error line «can’t locate Statistics/Distributions.pm in @INC» (taken from your comment below).
5 Answers 5
This answer assumes that the module is in fact installed, but not in a place that perl is looking for.
Generally, the Perl module Statistics::Distributions will be contained in a file called Statistics/Distributions.pm . On Linux and similar systems, one can search for these files quickly with the locate command:
locate Statistics/Distributions.pm
If it is installed, locate will spit out a line similar to
/opt/my_perl/lib/Statistics/Distributions.pm
You can then instruct the perl interpreter to look in this path, too, in various ways. One is to define the environment variable PERL5LIB , i.e. from bash :
prompt> PERL5LIB=/opt/my_perl/lib/ ./myscript.pl
Or you can use the perl -I switch:
prompt> perl -I/opt/my_perl/lib/ ./myscript.pl
Or you can modify the script to use lib ; there is more than one way to do it 😉
How does a Perl program know where to find the file containing Perl module it uses?
If my Perl program uses Perl modules, how will it determine where to find the file containing the module code? For example, if the program contains:
use MyModule1; # Example 1 use This::Here::MyModule2; # Example 2
I couldn’t find a comprehensive answer to this question on SO that I could link to, so I decided to create one. If the answer provided below is in need of additions/corrections, please have at it 🙂
3 Answers 3
Perl interpreter (which runs your perl program) will use a special array called @INC to search for a file containing the module.
Each value in the @INC array is a directory name (but see note below); Perl will search within those directories in a loop using the rules specified below. (Please refer to this SO post for details of how the contents of @INC are determined).
If the module’s file is not found after exhausting @INC , the program’s compilation will be aborted with an error. If the module’s file is found in one of the directories specified in @INC , the search is finished without looking at the rest of @INC .
The way Perl searches for a module file within each of the directories listed in @INC is as follows:
- First, it will separate the module name’s hierarchical components (words separated by :: ), into the last component — which will be used to form a file name — and a hierarchy path (all the components preceding the last :: ). In case the module name has only one component (no :: , e.g. MyModule1 above), the hierarchy path is empty and the filename is the name of the module. In the second example in this question, the last component is MyModule2 and hierarchy path will be This::Here .
- The expected file name will be determined by appending the last component of the module name with a .pm extension. E.g. MyModule1.pm and MyModule2.pm in our examples. NOTE: Module names are obviously case sensitive on Unix and other operating systems where file/directory naming is case sensitive.
- The module’s directory will be determined by:
- Taking the next directory from @INC — let’s say /usr/lib/perl as an example
- Forming a sub-directory of that directory by taking the hierarchy path of the module name (if any) and replacing «::» with / or whatever character the operating system uses as directory separator. In our two examples, the first module will be searched for in /usr/lib/perl (no sub-directory) and the second in /usr/lib/perl/This/Here .
- NOTE: the above is a slight simplification — @INC may also contain subroutine references and object references, which load the modules as their custom code specifies instead of performing the lookup in the directory as specified in #2 logic above. That functionality appears to be very seldom used and this article assumes that entire @INC only contains directories.
Let’s go over a specific example, assuming that your @INC contains two sub-directories: («/usr/lib/perl», «/opt/custom/lib») .
Then Perl would search as follows:
========================================================================== | Module | Try # | File to try ========================================================================== | MyModule1 | Try 1 | /usr/lib/perl/MyModule1.pm | MyModule1 | Try 2 | /opt/custom/lib/MyModule1.pm ========================================================================== | This::Here::MyModule2 | Try 1 | /usr/lib/perl/This/Here/MyModule2.pm | This::Here::MyModule2 | Try 2 | /opt/custom/lib/This/Here/MyModule2.pm ==========================================================================
Please recall that Perl interpreter will STOP trying to search once it finds the file in one of the locations, without trying to see if the file is in later locations as well. E.g. if /usr/lib/perl/This/Here/MyModule2.pm exists, then Perl will not look for, nor care about the existence, of /opt/custom/lib/This/Here/MyModule2.pm .
NOTE: @INC is used whenever Perl interpreter is using require -like mechanism for importing Perl modules. This includes:
- require directive itself
- use MyModule statement (equivalent to require+import)
- use base (equivalent to require+»push @ISA»)
- -M command line parameter
How do I include a Perl module that’s in a different directory?
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:
You can include a line near the top of your perl script:
You can modify the environment variable PERL5LIB before you run the script:
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:
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!
Came across this after reading 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)
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.
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'
‘use lib’ can also take a single string value.
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:
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:
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
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: