Документация
HTML CSS PHP PERL другое

Section 10.5.  require and @INC

 
Previous
Table of Contents
Next

10.5. require and @INC

So far, the examples have glossed over how we've set up the directory structure of where the main code and the included files are located. That's because it "just works" for the simplest case where we have a program and its libraries in the same directory and we run the program from that directory.

Things get a bit more complicated when the libraries aren't in the current directory. In fact, Perl searches for libraries along a library search path, similar to what the shell does with the PATH environment variable. The current directory (represented in Unix by a single dot) is an element of the search path. So, as long as our libraries are in our current working directory, everything is fine.

The search path is a list of elements in the special @INC array, as we briefly discussed in Chapter 3. By default, the array contains the current directory and a half-dozen or so directories specified by the person who compiled Perl. Typing perl -V on the command line shows what these directories are, in the last dozen lines of the output. Also, the following command displays just the @INC directories:[*]

[*] On a Windows machine, use double quotes instead of single quotes on the command line.

perl -le 'print for @INC'

Except for . in that list, we probably won't be able to write to any of the other directories unless we're the person responsible for maintaining Perl on our machine, in which case, we should be able to write to all of them. The remaining directories are where Perl searches for system-wide libraries and modules, as we'll see later.

10.5.1. Extending @INC

We may run into some cases where we can't install modules in the pre-configured directories in @INC. We can change @INC itself before the require, so Perl searches our directories too. The @INC array is an ordinary array, so have the Skipper add a directory below his home directory to the mix:

unshift @INC, '/home/skipper/perl-lib';

Now, in addition to searching the standard directories and the current directory, Perl searches the Skipper's personal Perl library. In fact, Perl searches in that directory first, since it is the first one in @INC. By using unshift rather than push, Perl resolves any conflict in names between the Skipper's private files and the system-installed files, with the Skipper's file-taking precedence.

Normally we want to ensure that this happens before anything else, so we can wrap it in a BEGIN block. Perl executes the code in the BEGIN block during the compile phase before the require executes at runtime. Otherwise, Perl executes statements in the order that it finds them, and we have to ensure that our unshift shows up before our require.

BEGIN {
  unshift @INC, '/home/skipper/perl-lib';
};

This is such a common operation, though, that Perl has a pragma for it. The pragma makes everything happen before runtime, so we'll get what we expect. It puts the directories we specify at the beginning of @INC, just like we did before.

use lib qw(/home/skipper/perl-lib);

We don't always have to know the path ahead of time, either. In the previous examples, we've hardcoded the paths. If we don't know what those will be because we're passing code around to several machines, the FindBin module, which comes with Perl, can help. It finds the full path to the script directory so we can use it to build paths.

use FindBin qw($Bin);

Now, in $Bin is the path to the directory that holds our script. If we have our libraries in the same directory, our next line can be:

use lib $Bin;

If we have the libraries in a directory close to the script directory, we put the right path components together to make it work.

use lib "$Bin/lib";    # in a subdirectory

use lib "$Bin/../lib"; # up one, then down into lib

So, if we know the relative path from the script directory, we don't have to hardcode the whole path. This makes the script more portable.

10.5.2. Extending @INC with PERL5LIB

The Skipper must edit each program that uses his private libraries to include those lines from the previous section. If that seems like too much editing, he can instead set the PERL5LIB environment variable to the directory name. For example, in the C shell, he'd use the line:

setenv PERL5LIB /home/skipper/perl-lib

In Bourne-style shells, he'd use something like:

PERL5LIB=/home/skipper/perl-lib; export PERL5LIB

The Skipper can set PERL5LIB once and forget about it. However, unless Gilligan has the same PERL5LIB environment variable, his program will fail! While PERL5LIB is useful for personal use, we can't rely on it for programs we intend to share with others. (And we can't make our entire team of programmers add a common PERL5LIB variable. Believe us, we've tried.)

The PERL5LIB variable can include multiple directories separated by colons. Perl inserts all specified directories at the beginning of @INC.

While a system administrator might add a setting of PERL5LIB to a system-wide startup script, most people frown on that. The purpose of PERL5LIB is to enable non-administrators to extend Perl to recognize additional directories. If a system administrator wants additional directories, he merely needs to recompile and reinstall Perl.

10.5.3. Extending @INC with -I

If Gilligan recognizes that one of the Skipper's programs is missing the proper directive, Gilligan can either add the proper PERL5LIB variable or invoke Perl directly with one or more -I options. For example, to invoke the Skipper's get_us_home program, the command line might be something like:

perl -I/home/skipper/perl-lib /home/skipper/bin/get_us_home

Obviously, it's easier for Gilligan if the program itself defines the extra libraries. But sometimes just adding a -I fixes things right up.[*] This works even if Gilligan can't edit the Skipper's program. He still has to be able to read it, of course, but Gilligan can use this technique to try a new version of his library with the Skipper's program, for example.

[*] Extending @INC with either PERL5LIB orI also automatically adds the versionand architecture-specific subdirectories of the specified directories. Adding these directories automatically simplifies the task of installing Perl modules that include architecture- or version-sensitive components, such as compiled C code.


Previous
Table of Contents
Next
© 2000- NIV