前回までのあらすじ
ようやくlocal::lib童貞を捨てた - すぎゃーんメモから1.5ヶ月ほど経過。
やはりプロジェクト毎にモジュールのバージョンを揃えておきたくて、各プロジェクト用にモジュールをインストールしている。
アカウント作成して切り替え、という方法は早々に見切りをつけ、最近は
#!/bin/sh export MODULEBUILDRC="/Users/sugyan/local/.modulebuildrc" export PERL_MM_OPT="INSTALL_BASE=/Users/sugyan/local" export PERL5LIB="/Users/sugyan/local/lib/perl5:/Users/sugyan/local/lib/perl5/darwin-thread-multi-2level:$PERL5LIB" export PATH="/Users/sugyan/local/bin:$PATH" $@
のようにパスを追加するシェルスクリプトに引数をそのまま渡して、
$ local.sh perl hoge.pl
という具合に実行させるようにしていた。
本題
けどスマートな方法じゃないよなぁ、と思っていたところに、こんなやり方を教えていただいた!ありがとうございます!
local::lib を切り替える - unknownplace.org
早速ほぼ丸パクリで試してみた。
"$HOME/extlib/local"にプロジェクト関係なく共通で最新のモジュール群を、"$HOME/extlib/MyProject"にそのプロジェクト専用のモジュールをインストールしていくことにする。
最近話題のcpanminusを使ってちょっと古めのモジュールとか入れてみたりもしてみよう。
GitHub - miyagawa/cpanminus: cpanminus - get, unpack, build and install modules from CPAN
cpanminusを使うとメモリ制限のきついレンタルサーバーでもCPANモジュールが楽にインストールできる - otsune's SnakeOil - subtech
$ cpanm -l $HOME/extlib/local AnyEvent $ cpanm -l $HOME/extlib/MyProject http://search.cpan.org/CPAN/authors/id/M/ML/MLEHMANN/AnyEvent-5.11.tar.gz
"$HOME/.zshrc"にて切り替え用の関数とデフォルトのextlibなどを指定
export PATH=$PATH:$HOME/local/bin function locallib () { INSTALL_BASE=$1 if [ -d $INSTALL_BASE ]; then eval $(~/local/bin/use-locallib $INSTALL_BASE) fi } locallib $HOME/extlib/local
で、"$HOME/local/bin/use-locallib"コマンドは丸パクリ。
#!/usr/bin/env perl use strict; use warnings; use Pod::Usage; use Config; use File::Spec; my $install_base = $ARGV[0] or pod2usage(-1); $install_base = File::Spec->rel2abs($install_base); my $path = $ENV{PATH}; my $perl5lib = $ENV{PERL5LIB}; push @INC, File::Spec->catdir($install_base, 'lib', 'perl5'); require local::lib; my %env = local::lib->build_environment_vars_for($install_base, 1); # remove $PERL5LIB set by old local::lib if it exists. if (my $old_base = $ENV{PERL_MM_OPT}) { my %mmopt; for my $opt (split /:+/, $old_base) { my ($k, $v) = split /=/, $opt; $mmopt{$k} = $v; } if (my $old_installbase = $mmopt{INSTALL_BASE}) { if ($old_installbase eq $install_base) { # do nothing if install_base is equal to old one exit; } my @old_perl5lib = ( File::Spec->catdir($old_installbase, 'lib', 'perl5'), File::Spec->catdir($old_installbase, 'lib', 'perl5', $Config{archname}), ); $env{PERL5LIB} = do { my @env; ENV: for my $e (grep { $_ } split $Config{path_sep}, $env{PERL5LIB}) { for my $old (@old_perl5lib) { next ENV if $old eq $e; } push @env, $e; } join $Config{path_sep}, @env; }; my $old_path = File::Spec->catdir($old_installbase, 'bin'); $env{PATH} = do { my @p; for my $p (grep {$_} split $Config{path_sep}, $env{PATH}) { next if $p eq $old_path; push @p, $p; } join $Config{path_sep}, @p; }; } } while (my ($k, $v) = each %env) { print qq[export $k="$v"\n]; } =head1 NAME use-locallib - set/switch local::lib environment =head1 SYNOPSIS use-locallib (MODULE INSTALL BASE)
これで、
$ locallib $HOME/extlib/MyProject $ locallib $HOME/extlib/local
といったカンジで環境を切り替えられるようになる。
あとは、どの環境を使っているか間違わないようにPROMPTに表示させる。自分の場合は以下のような。
precmd() { LANG=en_US.UTF-8 vcs_info LOADAVG=$(sysctl -n vm.loadavg | perl -anpe '$_=$F[1]') if [ "$INSTALL_BASE" = "" ]; then CURRENT_LOCALLIB="" else CURRENT_LOCALLIB="%{${fg[magenta]}%}$(echo $INSTALL_BASE | sed -e "s|$HOME/||; s|extlib/||") %{$reset_color%}" fi PROMPT='${CURRENT_LOCALLIB}${vcs_info_msg_0_}%{${fg[yellow]}%}%* ($LOADAVG) %%%{$reset_color%} ' RPROMPT='%{${fg[green]}%}%/%{$reset_color%}' }
切り替えた先で入れたモジュールは他の環境と切り離されるので、各プロジェクト毎にモジュールのバージョンを調整できるようになる。
こんなカンジで使い分けられる!
結構イケてそうなので、しばらくこれでやっていってみます。