PlackやAnyEventなどなど新しめのモジュールを使いたいんだけど、既存モジュールのrpmを作っていくのが面倒な場合に、それらのモジュール群をlocal::libを使ってまとめてどこかにディレクトリに入れるバンドルパッケージRPMができないかと考えてやってみた。

んで、できたので、specファイルをさらしてみる

Summary:        bundle package of Plack+AnyEvent
Name:           perl-bundle-plack
Version:        0.3
Release:        1%{?dist}
License:        Artistic
Group:          Development/Libraries
Source:         http://search.cpan.org/CPAN/authors/id/A/AP/APEIRON/local-lib-1.004009.tar.gz
Patch10:        local-lib-1.004009_destdir.patch 
BuildRoot:      %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
BuildRequires:       perl(YAML)
BuildRequires:       perl(Config)
BuildRequires:       perl(File::Path)
BuildRequires:       perl(FindBin)
BuildRequires:       perl(ExtUtils::MakeMaker)
BuildRequires:       perl(ExtUtils::Install)
BuildRequires:       perl(ExtUtils::CBuilder)
BuildRequires:       perl(ExtUtils::ParseXS)
BuildRequires:       perl(Module::Build) >= 0.28
BuildRequires:       perl(CPAN)
AutoProv: no

%define buildhome %{_tmppath}/%{name}-%{version}-%{release}-home-%(%{__id_u} -n)
%define bundle_prefix /usr/local/bundle-plack
%define __perl_requires /usr/lib/rpm/perl.req --ignore_deps 'perl(Plack)'

%description
bundle package of Plack+AnyEvent

%prep
%setup -n local-lib-1.004009
%patch10 -p1

%build
[ "%buildroot" != "/" ] && rm -rf %buildroot
[ "%{buildhome}" != "/" ] && rm -rf %{buildhome}
export HOME=%{buildhome}
%{__mkdir_p} %{buildroot}%{bundle_prefix}
%{__mkdir_p} %{buildhome}/.cpan/CPAN

cat <<EOF > %{buildhome}/.cpan/CPAN/MyConfig.pm
\$CPAN::Config = {
  'urllist' => [q[ftp://ftp.jaist.ac.jp/pub/CPAN/], q[ftp://ftp.riken.jp/lang/CPAN/]],
};
1;
__END__
EOF

perl -Ilib Makefile.PL  --bootstrap=%{buildroot}%{bundle_prefix}
make
make install
rm -rf %{buildroot}%{bundle_prefix}/.modulebuildrc

%install
export HOME=%{buildhome}
export ORIGINAL_PREFIX=%{bundle_prefix}
export DESTDIR=%{buildroot}
sed -i "s/'urllist' => \[\],/'urllist' => [q[ftp:\/\/ftp.jaist.ac.jp\/pub\/CPAN\/], q[ftp:\/\/ftp.nara.wide.ad.jp\/pub\/CPAN\/], q[ftp:\/\/ftp.riken.jp\/lang\/CPAN\/]],/" %{buildhome}/.cpan/CPAN/MyConfig.pm

perl -I%{buildroot}%{bundle_prefix}/lib/perl5 -Mlocal::lib=--self-contained,%{buildroot}%{bundle_prefix} -MCPAN -e '
$ENV{PERL_MM_OPT} .= " INSTALLMAN1DIR=none INSTALLMAN3DIR=none";
$ENV{PERL_MM_USE_DEFAULT} = 1;
for my $m (qw/EV IO::AIO AnyEvent AnyEvent::AIO Coro 
              HTTP::Parser::XS Plack Plack::Request Plack::Server::AnyEvent/){
    CPAN::Shell->rematein("notest", "install", $m);
}
'
#↑にいれるモジュールを書く

find %{buildroot}%{bundle_prefix} -name *.so -type f | xargs -I{} sed -i "s@%{buildroot}@@g"  {}
sed -i "s@%{buildroot}@@g" %{buildroot}%{bundle_prefix}/.modulebuildrc

find %{buildroot} -name perllocal.pod -or -name .packlist | xargs rm -f
find %{buildroot}%{bundle_prefix} -type f -print |
        sed "s@^$RPM_BUILD_ROOT@@g" |
        grep -v ^%{_mandir} |
        grep -v perllocal.pod |
        grep -v "\.packlist" > %{name}.files
if [ "$(cat %{name}.files)X" = "X" ] ; then
    echo "ERROR: EMPTY FILE LIST"
    exit -1
fi

%clean
rm -rf %{buildroot}
rm -rf %{buildhome}
%post

%preun

%postun

%files -f %{name}.files
%defattr(-, root, root, -)
%dir %{bundle_prefix}

%changelog

どこかからのコピペが混ざっていたりと、あまりきれいではないけど。このspecファイルによって、/usr/local/bundle-plack以下にlocal::libと依存モジュールがすべてインストールできる。

使用するときは、普通のlocal::libと同じようにshellだったら

eval $(perl -I/usr/local/bundle-plack/lib/perl5 -Mlocal::lib=/usr/local/bundle-plack)

とやればOK。

この方式を利用することで、サービスで用いている他のモジュールに影響することなく、新しいモジュールをインストールでき、一部の必要としているところだけに適用できるってのがいいですね。

以下はlocal::libにあてているpatch

diff -ur local-lib-1.004009.orig/lib/local/lib.pm local-lib-1.004009/lib/local/lib.pm
--- local-lib-1.004009.orig/lib/local/lib.pm    2009-11-08 10:27:23.000000000 +0900
+++ local-lib-1.004009/lib/local/lib.pm 2009-11-26 11:59:21.000000000 +0900
@@ -235,6 +235,20 @@
   File::Spec->catdir($class->install_base_perl_path($path), $Config{archname});
 }

+sub install_base_path {
+    my ($class, $path) = @_;
+    $ENV{ORIGINAL_PREFIX} ? $ENV{ORIGINAL_PREFIX} : $path;
+}
+
+sub destdir {
+    my ( $class ) = @_;
+    if ( $ENV{DESTDIR} && $ENV{DESTDIR} !~ m!/$! ) {
+        $ENV{DESTDIR} .= '/';
+    } 
+    $ENV{DESTDIR};
+}
+
+
 sub ensure_dir_structure_for {
   my ($class, $path) = @_;
   unless (-d $path) {
@@ -253,8 +267,11 @@
     warn "Attempting to create file ${modulebuildrc_path}\n";
     open MODULEBUILDRC, '>', $modulebuildrc_path
       || Carp::croak("Couldn't open ${modulebuildrc_path} for writing: $!");
-    print MODULEBUILDRC qq{install  --install_base  ${path}\n}
+    print MODULEBUILDRC qq{install  --install_base  } . $class->install_base_path(${path}) . qq{\n}
       || Carp::croak("Couldn't write line to ${modulebuildrc_path}: $!");
+    if ( my $destdir = $class->destdir ) {
+        print MODULEBUILDRC qq!         --destdir $destdir\n!;
+    }
     close MODULEBUILDRC
       || Carp::croak("Couldn't close file ${modulebuildrc_path}: $@");
   }
@@ -344,9 +361,10 @@

 sub build_environment_vars_for {
   my ($class, $path, $interpolate) = @_;
+  my $destdir = ( $class->destdir ) ? " DESTDIR=" . $class->destdir : "";
   return (
     MODULEBUILDRC => $class->modulebuildrc_path($path),
-    PERL_MM_OPT => "INSTALL_BASE=${path}",
+    PERL_MM_OPT => "INSTALL_BASE=" . $class->install_base_path(${path}) . $destdir,
     PERL5LIB => join($Config{path_sep},
                   $class->install_base_perl_path($path),
                   $class->install_base_arch_path($path),

もっとスマートな方法があればだれか教えてくださいませ(_ _)

このブログ記事について

このページは、Masahiro Naganoが2010年2月19日 17:36に書いたブログ記事です。

ひとつ前のブログ記事は「memcachedのプロトコル変更の件」です。

次のブログ記事は「WEB+DB PRESS Vol.55「大規模Webサービスの裏側」最終回」です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。

ウェブページ

OpenID対応しています OpenIDについて
Powered by Movable Type 4.27-ja