-
Notifications
You must be signed in to change notification settings - Fork 216
Install a sitecustomize.pl file with perlbrew
by @xdg
When perl is compiled with -Dusesitecustomize
it will look for a file in the $Config{sitelib}
directory called sitecustomize.pl
and execute it extremely early in the life of the interpreter. (See perldoc perlrun and the -f
switch for an explanation.)
Perlbrew 0.37 adds the --sitecustomize
installation option to specify a Perl file to be installed as sitecustomize.pl
. (Perlbrew will also set -Dusesitecustomize
automatically.)
$ perlbrew install perl-5.14.2 --sitecustomize /path/to/customize.pl
This is extremely useful for doing dynamic manipulation of the environment or perl globals. In particular, it can be used to modify @INC in a more customized way than can be achieved with PERL5LIB
.
Consider this usage example: A user wants to be able to install a command line perl application like App::Ack and have it be available regardless of which perl is active with Perlbrew. Further, the user would like to keep its dependencies isolated so that the Perlbrew-installed perl stays 'pure'.
A good way to install an isolated application is to use local::lib
with Perlbrew:
$ perlbrew lib create ack
$ perlbrew use perl-5.14.2@ack
$ cpanm App::Ack
This installs the 'ack' program to the bin
directory of the configured local library directory. If the user switches to another Perl or another local library directory, ack
won't be available. The user can't run ack
directly out of the local library bin
directory because PERL5LIB
won't be set correctly to find its dependencies.
There are many ways to solve this problem. One approach is to use a sitecustomize.pl
file. The following sitecustomize.pl
file checks to see if the executing script appears to be installed in a
local library that follows the INSTALL_BASE
convention. If so, it automatically adds the proper library path to @INC
:
use strict;
use Config;
use Cwd ();
my %seen;
my @bindirs =
grep { defined && !$seen{$_}++ }
map { $Config{"install". $_} }
map { ("${_}bin", "${_}script") } "", "site", "vendor";
my $script = Cwd::realpath($0);
if ( ! grep { /\Q$script\E/ } @bindirs ) {
my @path = split "/", $script;
if ( @path > 2 ) { # at least /bin/foo
pop @path; # get rid of script filename
my $installbase = join("/", @path[0 .. $#path-1], 'lib', 'perl5');
if ( $path[-1] eq 'bin' && -d $installbase ) {
require lib;
lib->import($installbase);
}
}
}
That lets the user switch Perlbrew perls but still run the original ack
program via an alias.
$ alias ack=`which ack`
$ perlbrew use perl-5.10.2
$ ack PATTERN
The ack
that is run via the alias has a shebang line (#!...
) that invoke the original perl, which will run sitecustomize.pl
, which will fix up @INC
and then ack
will run successfully, finding its dependencies in @INC
.