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),
もっとスマートな方法があればだれか教えてくださいませ(_ _)