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.