Chinaunix首页 | 论坛 | 博客
  • 博客访问: 3045928
  • 博文数量: 535
  • 博客积分: 15788
  • 博客等级: 上将
  • 技术积分: 6507
  • 用 户 组: 普通用户
  • 注册时间: 2007-03-07 09:11
文章分类

全部博文(535)

文章存档

2016年(1)

2015年(1)

2014年(10)

2013年(26)

2012年(43)

2011年(86)

2010年(76)

2009年(136)

2008年(97)

2007年(59)

分类:

2009-03-27 10:14:40

3.8. Installing Modules from CPAN

Installing a simple module from CPAN can be straightforward: we download the module distribution archive, unpack it, and change into its directory. We use wget here, but it doesn't matter which tool you use.

$ wget 
$ tar -xzf HTTP-Cookies-Safari-1.10.tar.gz
$ cd HTTP-Cookies-Safari-1.10s

From there we go one of two ways (which we'll explain in detail in ). If we find a file named Makefile.PL, we run this series of commands to build, test, and finally install the source:

$ perl Makefile.PL
$ make
$ make test
$ make install

If we don't have permission to install modules in the system-wide directories, we can tell Perl to install them under another path by using the PREFIX argument:

These directories were set when the administrator installed Perl, and we can see them with perl -V.

$ perl Makefile.PL PREFIX=/Users/home/Ginger

To make Perl look in that directory for modules, we can set the PERL5LIB environment variable. Perl adds those directories to its module directory search list.

$ export PERL5LIB=/Users/home/Ginger

We can also use the lib pragma to add to the module search path, although this is not as friendly, since we have to change the code, but also because it might not be the same directory on other machines where we want to run the code.

#!/usr/bin/perl
use lib qw(/Users/home/Ginger);

Backing up for a minute, if we found a Build.PL file instead of a Makefile.PL, the process is the same. These distributions use Module::Build to build and install code. Since Module::Build is not a core Perl module, we have to install it before we can install the distribution that needs it.

At least not yet. It should be part of Perl 5.10, though.

$ perl Build.PL
$ perl Build
$ perl Build test
$ perl Build install

To install into our private directories using Module::Build, we add the install_base parameter. We tell Perl how to find modules the same way we did before.

$ perl Build.PL --install_base /Users/home/Ginger

Sometimes we find both Makefile.PL and Build.PL in a distribution. What do we do then? We can use either one. Play favorites, if you like.




3.9. Setting the Path at the Right Time

Perl finds modules by looking through the directories in the special Perl array, @INC. The use statement executes at compile time, so it looks at the module search path, @INC, at compile time. That can break our program in hard-to-understand ways unless we take @INC into consideration.

For example, suppose we have our own directory under /home/gilligan/lib, and we place our own Navigation::SeatOfPants module in /home/gilligan/lib/Navigation/SeatOfPants.pm. When we load our module, Perl won't find it.

use Navigation::SeatOfPants;

Perl complains to us that it can't find the module in @INC and shows us all of the directories it has in that array.

Can't locate Navigation/SeatofPants.pm in @INC (@INC contains: ...)

You might think that we should just add our module directory to @INC before we call the use. However, even adding:

unshift @INC, '/home/gilligan/lib';   # broken
use Navigation::SeatOfPants;

doesn't work. Why? Because the unshift happens at runtime, long after the use was attempted at compile time. The two statements are lexically adjacent but not temporally adjacent. Just because we wrote them next to each other doesn't mean they execute in that order. We want to change @INC before the use executes. One way to fix this is to add a BEGIN block around the push:

BEGIN { unshift @INC, '/home/gilligan/lib'; }
use Navigation::SeatOfPants;

Now the BEGIN block compiles and executes at compile time, setting up the proper path for the following use.

However, this is noisy and prone to require far more explanation than you might be comfortable with, especially for the maintenance programmer who has to edit your code later. Let's replace all that clutter with that simple pragma we used before:

use lib '/home/gilligan/lib';
use Navigation::SeatOfPants;

Here, the lib pragma takes one or more arguments and adds them at the beginning of the @INC array, just like unshift did before. It works because it executes at compile time, not runtime. Hence, it's ready in time for the use immediately following.

use lib also unshifts an architecture-dependent library below the requested library, making it more valuable than the explicit counterpart presented earlier.

Because a use lib pragma will pretty much always have a site-dependent pathname, it is traditional and we encourage you to put it near the top of the file. This makes it easier to find and update when we need to move the file to a new system or when the lib directory's name changes. (Of course, we can eliminate use lib entirely if we can install our modules in standard @INC locations, but that's not always practical.)

Think of use lib as not "use this library" but rather "use this path to find my libraries (and modules)." Too often, we see code written like:

use lib '/home/gilligan/lib/Navigation/SeatOfPants.pm'; # WRONG

and then the programmer wonders why it didn't pull in the definitions. Be aware that use lib indeed runs at compile time, so this also doesn't work:

my $LIB_DIR = '/home/gilligan/lib';
...
use lib $LIB_DIR;     # BROKEN
use Navigation::SeatOfPants;

Certainly, Perl establishes the declaration of the $LIB_DIR variable at compile time (so we won't get an error with use strict, although the actual use lib should complain), but the actual assignment of the /home/gilligan/lib/ value doesn't happen until runtime. Oops, too late again!

At this point, we need to put something inside a BEGIN block or perhaps rely on yet another compile-time operation: setting a constant with use constant:

use constant LIB_DIR => '/home/gilligan/lib';
...
use lib LIB_DIR;
use Navigation::SeatOfPants;

There. Fixed again. That is, until we need the library to depend on the result of a calculation. (Where will it all end? Somebody stop the madness!) This should handle about 99 percent of our needs.

3.9.1. Handling Module Dependencies

We just saw that if we try to install a module that uses Module::Build, we have to install Module::Build first. That's a mild case of the general dependency headache, and all the coconuts on our castaways' island aren't going to fix it. We might have to install several other modules too, each of which, in turn, depends on even more modules.

Fortunately, we have tools to help us. The CPAN.pm module has been part of the core distribution since Perl 5.004. It gives us an interactive module installation shell.

$ perl -MCPAN -e shell
cpan shell -- CPAN exploration and modules installation (v1.7601)
ReadLine support available (try 'install Bundle::CPAN')

cpan>

To install a module along with its dependencies, we issue the install command with the name of the module. Now, CPAN.pm handles all the work of downloading, unpacking, building, testing, and installing the module, and it does so recursively for all its dependencies.

cpan> install CGI::Prototype

That's a bit too much work, though, so brian created the cpan script, which also comes with Perl. We simply list the modules we want to install, and it handles it for us.

$ cpan CGI::Prototype HTTP::Cookies::Safari Test::Pod

Another tool, CPANPLUS, is a complete rewrite of CPAN.pm, but it isn't part of the core distribution as we write this.

$ perl -MCPANPLUS -e shell
CPANPLUS::Shell::Default -- CPAN exploration and modules installation (v0.03)
*** Please report bugs to .
*** Using CPANPLUS::Backend v0.049.
*** ReadLine support available (try 'i Term::ReadLine::Perl').

CPAN Terminal>

To install a module, we use the i command.

CPAN Terminal> i CGI::Prototype

The CPANPLUS module also comes with a convenience script, called cpanp. If we give it the i switch and a list of modules, it installs them just like before.

$ cpanp i CGI::Prototype HTTP::Cookies::Safari Test::Pod

阅读(1307) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~