views:

293

answers:

3

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

where will it look?

+2  A: 

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:

    1. Taking the next directory from @INC - let's say /usr/lib/perl as an example

    2. 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.

    3. 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][3] (equivalent to require+"push @ISA")
DVK
It's probably worth noting where the contents of @INC come from. This may even be the answer the OP was looking for. The brief summary: The main default contents are built-in (exact details of the paths depend on your installation, obviously). The primary ways to modify it outside of your script are to set the environment variable PERL5LIB (a colon-delimited list of paths) or supply `-I/path/to/dir` options to the executable at runtime. (These prepend to the array)
Jefromi
Anyone have a nice authoritative list of precisely how @INC is constructed? The one in perldoc perlvar appears to be missing any mention of PERL5LIB, as well as the `$Config{sitelib}/sitecustomize.pl` mechanism (which has to be built in at compile time).
Jefromi
@DVK: Excellent! Mistakenly assumed you were done because of the comment to the question and the fact that this is already awesomely thorough.
Jefromi
could you mark this CW so low-rep users can also edit in their answers?
Ether
@Ether - Done. There goes my avalanche of rep :( ;)
DVK
@Jefromi - added the link to that new FAQ
DVK
I also added a reference to the ability to have subroutine references and objects in @INC
DVK
A: 

According to the perlfunc documentation on use:

use Module LIST

Imports some semantics into the current package from the named module, generally by aliasing certain subroutine or variable names into your package. It is exactly equivalent to

BEGIN { require Module; Module->import( LIST ); }

except that Module must be a bareword.

So require does the heavy lifting, and the require documentation provides

If EXPR is a bareword, the require assumes a ".pm" extension and replaces "::" with "/" in the filename for you, to make it easy to load standard modules. This form of loading of modules does not risk altering your namespace.

In other words, if you try this:

   require Foo::Bar;    # a splendid bareword

The require function will actually look for the "Foo/Bar.pm" file in the directories specified in the @INC array.

Greg Bacon
+1  A: 

While this does not directly answer the question, here are some simple techniques to determine the full path to the module file you want to use.

To view the default contents of the @INC array from the command line:

perldoc -V

If you want to know the location of the Carp module:

perldoc -l Carp

Inside a script, printing the contents of the %INC hash is useful to determine the actual module you are using, especially if you have modified @INC from its default:

use Carp;
print $INC{'Carp.pm'};

This simple script can also be used to Find installed Perl modules matching a regular expression and to identify any duplicate modules in different directories.

toolic
@toolic - this answer is closely related to the OP question, but I feel it is somewhat separate from it (e.g. "where did the module I imported come from"). Would you mind either posting it as a separate Q+A on SO (I'll link to it), or giving me your consent to ask it as a separate Q and posting your answer (or letting me repost yours)?
DVK
toolic
@toolic - done! http://stackoverflow.com/questions/2527990/how-do-i-find-which-file-contains-perl-module-my-script-uses
DVK