CPANモジュールPlackをDebianパッケージ化

今回はPlackDebianパッケージ化してみる。

とりあえず何も考えずいつもどおり dh-make-perl と debuild を実行して dpkg でインストールしてみる。

$ dh-make-perl --cpan Plack
$ ls
Plack-0.9941 libplack-perl_0.9941.orig.tar.gz
$ cd Plack-0.9941/
$ debuild -rfakeroot -uc -us
$ cd ../
$ ls | grep plack
libplack-perl_0.9941-1.diff.gz
libplack-perl_0.9941-1.dsc
libplack-perl_0.9941-1_all.deb
libplack-perl_0.9941-1_i386.build
libplack-perl_0.9941-1_i386.changes
libplack-perl_0.9941.orig.tar.gz
$ sudo dpkg -i libplack-perl_0.9941-1_all.deb
(libplack-perl_0.9941-1_all.deb から) libplack-perl を展開しています...
dpkg: 依存関係の問題により libplack-perl の設定ができません:
libplack-perl は以下に依存 (depends) します: libparent-perl ...しかし:
パッケージ libparent-perl はまだインストールされていません。
libplack-perl は以下に依存 (depends) します: liburi-perl (>= 1.36) ...しかし:
システム上の liburi-perl のバージョン は 1.35.dfsg.1-1 です。
libplack-perl は以下に依存 (depends) します: libdevel-stacktrace-perl ...しかし:
パッケージ libdevel-stacktrace-perl はまだインストールされていません。
libplack-perl は以下に依存 (depends) します: libhttp-body-perl (>= 1.06) ...しかし:
パッケージ libhttp-body-perl はまだインストールされていません。
libplack-perl は以下に依存 (depends) します: libfile-sharedir-perl (>= 1.00) ...しかし:
パッケージ libfile-sharedir-perl はまだインストールされていません。
libplack-perl は以下に依存 (depends) します: libwww-perl (>= 5.814) ...しかし:
システム上の libwww-perl のバージョン は 5.813-1 です。
dpkg: libplack-perl の処理中にエラーが発生しました (--install):
依存関係の問題 - 設定を見送ります
man-db のトリガを処理しています ...
以下のパッケージの処理中にエラーが発生しました:
libplack-perl

上記のように依存しているパッケージがインストールされていないと怒られます。
Debianではインストールを試みて依存しているパッケージが分かれば下記コマンドで必要パッケージをインストールしてくれます。

$ sudo apt-get -f install
(省略)
以下のパッケージは「削除」されます:
libplack-perl
以下のパッケージが新たにインストールされます:
libdevel-stacktrace-perl libparent-perl
(省略)

そしてもう1度 libplack-perl をインストールしてみる。

$ sudo dpkg -i libplack-perl_0.9941-1_all.deb
(libplack-perl_0.9941-1_all.deb から) libplack-perl を展開しています...
dpkg: 依存関係の問題により libplack-perl の設定ができません:
libplack-perl は以下に依存 (depends) します: liburi-perl (>= 1.36) ...しかし:
システム上の liburi-perl のバージョン は 1.35.dfsg.1-1 です。
libplack-perl は以下に依存 (depends) します: libhttp-body-perl (>= 1.06) ...しかし:
パッケージ libhttp-body-perl はまだインストールされていません。
libplack-perl は以下に依存 (depends) します: libfile-sharedir-perl (>= 1.00) ...しかし:
パッケージ libfile-sharedir-perl はまだインストールされていません。
libplack-perl は以下に依存 (depends) します: libwww-perl (>= 5.814) ...しかし:
システム上の libwww-perl のバージョン は 5.813-1 です。
dpkg: libplack-perl の処理中にエラーが発生しました (--install):
依存関係の問題 - 設定を見送ります
man-db のトリガを処理しています ...
以下のパッケージの処理中にエラーが発生しました:
libplack-perl

今度は依存パッケージのバージョンが古いと怒られました。
しかしlennyにはまだ新しいバージョンのパッケージがありません。
そこで新しいバージョンのパッケージをソールからビルドしたいと思います。

今回、バージョンが古くて依存しているパッケージは下記の4つです。

liburi-perl (>= 1.36)
libhttp-body-perl (>= 1.06)
libfile-sharedir-perl (>= 1.00)
libwww-perl (>= 5.814)

そこで下記のように dh-make-perl, debuild, dpkg を使って最新モジュールをパッケージとしてインストールします。

$ dh-make-perl --cpan URI
$ dh-make-perl --cpan HTTP::Body
$ dh-make-perl --cpan File::ShareDir
$ dh-make-perl --cpan LWP

$ cd URI-1.54/
$ debuild -rfakeroot -uc -us
$ cd ../
$ cd HTTP-Body-1.07/
$ debuild -rfakeroot -uc -us
$ cd ../
$ cd File-ShareDir-1.02/
$ debuild -rfakeroot -uc -us
$ cd ../
$ cd libwww-perl-5.836/
$ debuild -rfakeroot -uc -us
$ cd ../

$ sudo dpkg -i liburi-perl_1.54-1_all.deb libfile-sharedir-perl_1.02-1_all.deb libhttp-body-perl_1.07-1_all.deb libwww-perl_5.836-1_all.deb
(省略)
dpkg: 依存関係の問題により libfile-sharedir-perl の設定ができません:
libfile-sharedir-perl は以下に依存 (depends) します: libclass-inspector-perl (>= 1.12) ...しかし:
パッケージ libclass-inspector-perl はまだインストールされていません。
(省略)

しかし libfile-sharedir-perl の依存パッケージ libclass-inspector-perl がインストールされていないと怒られた。
せっかくなので libclass-inspector-perlCPAN からダウンロードしてビルド・インストールを行う。

$ dh-make-perl --cpan Class::Inspector
$ cd Class-Inspector-1.24
$ debuild -rfakeroot -uc -us
$ cd ../
$ sudo dpkg -i liburi-perl_1.54-1_all.deb libfile-sharedir-perl_1.02-1_all.deb libhttp-body-perl_1.07-1_all.deb libwww-perl_5.836-1_all.deb libclass-inspector-perl_1.24-1_all.deb

最後に目的の libplack-perl をインストールする。

$ sudo dpkg -i libplack-perl_0.9941-1_all.deb

無事に Plackdebパッケージとしてインストールできた。

Debian では dh-make-perl, debuild, dpkg でCPANモジュールをdebパッケージとしてインストールできる。

他にも gdebi というローカルdebファイルの依存パッケージを自動でインストールしてくれるツールもあったりするが、これはまた次回時間のあるときに書こうと思う。

とりあえず今回はここまで。

いきなりDebianでCPANモジュールをパッケージ化

さっそくですが個人メモとしてCPANモジュールをDebianパッケージにする方法を書いてみる。

Debian には dh-make-perl というCPANモジュールをdeb化するために便利なツールがある。

$ dh-make-perl --cpan AnyEvent
(省略)
I would like to connect to one of the following sites to get 'authors/id/M/ML/MLEHMANN/AnyEvent-5.271.tar.gz':

http://www.perl.org/CPAN/
ftp://ftp.perl.org/pub/CPAN/

Is it OK to try to connect to the Internet? [yes]
(省略)
$ ls
AnyEvent-5.271 libanyevent-perl_5.271.orig.tar.gz

これを実行するとDebianパッケージ化に必要な debian/rules, debian/control などを自動で作ってくれる。

その後、下記を実行すると debファイルが作成される。

$ cd AnyEvent-5.271/
$ debuild -rfakeroot -uc -us
$ cd ../
$ ls | grep anyevent
libanyevent-perl_5.271-1.diff.gz
libanyevent-perl_5.271-1.dsc
libanyevent-perl_5.271-1_all.deb
libanyevent-perl_5.271-1_i386.build
libanyevent-perl_5.271-1_i386.changes
libanyevent-perl_5.271.orig.tar.gz

あとはこれをインストールすればOK

$ sudo dpkg -i libanyevent-perl_5.271-1_all.deb

念のため確認。

$ dpkg -l libanyevent-perl
ii libanyevent-per 5.271-1 simpler/faster/newer/cooler AnyEvent API

自作パッケージかどうかも確認。

$ apt-cache show libanyevent-perl
Package: libanyevent-perl
Status: install ok installed
Priority: optional
Section: perl
Installed-Size: 852
Maintainer: hayashi
Architecture: all
Version: 5.271-1
Depends: perl (>= 5.6.0-16)
Description: simpler/faster/newer/cooler AnyEvent API
This module documents the new simpler AnyEvent API.
.
The rationale for the new API is that experience with EV shows that
this API actually "works", despite it's lack of extensibility, leading to
a shorter, easier and faster API.
.
The main difference to AnyEvent is that instead of method calls, function
calls are used, and that no named arguments are used.
.
This makes calls to watcher creation functions really short, which can
make a program more readable, despite the lack of named parameters.
Function calls also allow more static type checking than method calls, so
many mistakes are caught at compiletime with this API.
.
This description was automagically extracted from the module by dh-make-perl.
Homepage: http://search.cpan.org/dist/AnyEvent/

問題なくインストールできた。

もちろんperldocも。

$ perldoc AnyEvent

実はPlackやCoroをパッケージ化しようとしたのだがlenny提供のパッケージバージョンが古かったりテストでこけたりとうまくいかなかった。
またdpkgでインストールしているので依存関係のあるパッケージを自動でインストールしてくれない。
そこで次回はPlackdeb化を通してlennyで提供していないバージョンのモジュールをソースから入れる方法とdpkgではなく自動で依存関係のあるパッケージを入れてくれるツールを紹介しようと思う。

CPANモジュールImagerでpngのコメントを取得できるようにする。

CPANモジュールのImagerにはpngファイルを扱う機能が実装されている。
しかし、ソースを読んでみるとpngファイルのテキストデータを保持する「tEXt」チャンクの情報を取得する方法が提供されていない。
正確に言うと pHYs チャンクのみ処理するようにしていて他のチャンク処理は実装されていない。
そこで今回、(自分用に。。。) tEXt チャンク(テキストデータ) をperl側から取得できるようにソースを書き換える。

まずはCPANからImagerソースを取得する。

$ dh-make-perl --cpan Imager
$ ls
Imager-0.75  libimager-perl_0.75.orig.tar.gz
$ cd Imager-0.75

pngファイルの処理を行っているのは png.c になる。
このソースの「get_png_tags」関数で Imager オブジェクトの tags 配列の配列に pHYs チャンクの値を設定しているので、ここに tEXt チャンクの値を設定する処理を実装する。
ソースは下記のように変更した。

static void get_png_tags(i_img *im, png_structp png_ptr, png_infop info_ptr) {
  png_uint_32 xres, yres;
  int unit_type;

+  png_textp text_ptr;
+  int num_text;
+
  i_tags_add(&im->tags, "i_format", 0, "png", -1, 0);
  if (png_get_pHYs(png_ptr, info_ptr, &xres, &yres, &unit_type)) {
    mm_log((1,"pHYs (%d, %d) %d\n", xres, yres, unit_type));
    if (unit_type == PNG_RESOLUTION_METER) {
      i_tags_set_float2(&im->tags, "i_xres", 0, xres * 0.0254, 5); 
      i_tags_set_float2(&im->tags, "i_yres", 0, yres * 0.0254, 5); 
    }   
    else {
      i_tags_addn(&im->tags, "i_xres", 0, xres);
      i_tags_addn(&im->tags, "i_yres", 0, yres);
      i_tags_addn(&im->tags, "i_aspect_only", 0, 1);
    }
  }
+  if (png_get_text(png_ptr, info_ptr, &text_ptr, &num_text)) {
+    int i;
+    for (i = 0; i < num_text; i++) {
+      mm_log((1, "text %d %s %s %d\n",
+        i, text_ptr[i].key, text_ptr[i].text, text_ptr[i].text_length));
+      i_tags_add(&im->tags, text_ptr[i].key, 0, text_ptr[i].text, text_ptr[i].text_length, 0);
+    }
+  }
}

では実際に利用するためにビルド・インストールを行う。
まずは念のためバージョン番号をインクリメントする。

$ dch -i
+libimager-perl (0.75-2) unstable; urgency=low
+
+  * support for tEXt chunk of png 
+
+ -- hayashi <hayashi@deb1.1.168.192.in-addr.arpa>  Sun, 18 Jul 2010 23:46:18 +0900
+
libimager-perl (0.75-1) unstable; urgency=low

  * Initial Release.

 -- hayashi <hayashi@deb1.1.168.192.in-addr.arpa>  Sun, 18 Jul 2010 23:16:11 +0900

そしてビルド・インストール。

$ debuild -rfakeroot -uc -us
$ cd ../
$ sudo dpkg -i libimager-perl_0.75-2_i386.deb
$ dpkg -l libimager-perl
ii  libimager-perl  0.75-2          Perl extension for Generating 24 bit Images

では実際にperl側から使ってみる。
perl側の実装は下記のようにした。

#!/usr/bin/perl

use strict;
use warnings;

use Data::Dumper;

use Imager;

my $img = Imager->new(file => "a.png");
my %tags = map @$_, $img->tags();
print Dumper(\%tags);

png の tEXt チャンク未対応の Imager だと

$VAR1 = {
          'i_format' => 'png'
        };

という結果だが png の tEXt チャンク対応の Imager だと

$VAR1 = {
          'Software' => 'Adobe ImageReady',
          'i_format' => 'png'
        };

と「Software」の値が取れている。

まとめ

CPANモジュールImagerはlibpngを利用してpngファイルをパースしたり変形したりいろいろできる。
扱えるファイルフォーマットが多い分、細かい部分の実装は後回しになっている感じがする。
libpngやImagerのソースを追うことで実際の処理が理解できてとても勉強になった。
ソースを読んでいくと意外に理解できることが分かったのでどんどん読んでブログにフィードバックしていこうと思う。
(自分の勉強のために。。。)