Clarifying local::lib and cpan in Chapter 2

local::lib is highlighted in Intermediate Perl when I go through the CPAN tools in Chapter 2. Each of the tools has a slightly different set of features and I try to steal the good one. I added a local::lib to cpan so you can add the local::lib defaults for a one-shot installation process. This steals a feature from cpanm which has a --local-lib option:

% cpan -I Dancer

This version of cpan comes with v5.14, but you can always get the latest by installing App::Cpan.

AndrĂ© Philipp, who’s been submitted good corrections to Intermediate Perl, noticed a weird usage pattern. He did what local::lib suggested by setting the environment variables for his session:

export PERL_MB_OPT='--install_base /home/amelia/perl5'
export PERL_MM_OPT='INSTALL_BASE=/home/amelia/perl5'
export PERL5LIB='/home/amelia/perl5/lib/perl5/i386-linux:/home/amelia/perl5/lib/perl5'
export PATH="/home/amelia/perl5/bin:$PATH"

As session settings, cpan picks up and respects those. Actually, cpan doesn’t care about any of them, but the things it starts, such as Module::Build, do. There’s not much magic to local::lib; it merely sets environment variables.

Since AndrĂ© had set these, cpan‘s -I switch didn’t seem to do anything because he was always installing into the local::lib directories. The tools don’t care who set the environment variables as long as they are set.

If I always want to install into the local::lib directories, the session settings are fine and that’s what I should do. I, however, don’t always want to do that. In fact, I almost never want to do that. I added the -I switch for one off use assuming that I hadn’t set anything else to trigger local::lib.

The trick, then, is to manage expectations. If I map the various things a person might configure and how those interact, I found out that my -I feature might have some problems. What if I set the environment and use -I at the same time?

I’ve colored one endpoint red because I don’t know what happens there. It depends on what local::lib will do. People don’t care about that those. They have expectations about the interface. Someone used to unix tools will expect the closer settings will override distant ones. A tool will use command-line settings over environment over configuration files. That is, more transient settings override more permanent ones.

What does local::lib do in that case? I start by merely loading the module and doing nothing else. In that case, local::lib prints its settings:

% perl5.14.2 -Mlocal::lib
Attempting to create directory /Users/brian/perl5
export PERL_LOCAL_LIB_ROOT="/Users/brian/perl5";
export PERL_MB_OPT="--install_base /Users/brian/perl5";
export PERL_MM_OPT="INSTALL_BASE=/Users/brian/perl5";
export PERL5LIB="/Users/brian/perl5/lib/perl5/darwin-2level:/Users/brian/perl5/lib/perl5";
export PATH="/Users/brian/perl5/bin:$PATH";

What happens if I fool with the PERL_MM_OPT? local::lib replaces the environment variable, in all cases:

% export PERL_MM_OPT=/env/setting/perlmmopt
% perl5.14.2 -Mlocal::lib -E 'say $ENV{PERL_MM_OPT}'
INSTALL_BASE=/Users/brian/perl5
% perl5.14.2 -Mlocal::lib=~brian -E 'say $ENV{PERL_MM_OPT}'
INSTALL_BASE=/Users/brian

I don’t know if anyone expects this. I would have expected local::lib to use default settings already specified in the environment. The documentation doesn’t say which way it will go, although it says “On import, local::lib sets the following environment variables to appropriate values”. It doesn’t say what appropriate values are or that it replaces existing values with new ones.

There’s no reason I should really expect that, and that’s the problem with expectations. People expect different things because they have different assumptions and starting points, even if they don’t think they do. When I added that feature to cpan, I assumed it would be straightforward. I had my own assumptions, despite being the person (the author) who’s supposed to make all of that apparent.

I don’t think that local::lib is doing anything wrong. If it did it some other way, a different group of people would be confused because they would assume something else. There’s really no way to win. The best any interface can do is make it suck less.

Leave a Reply

Your email address will not be published. Required fields are marked *