玩式草子─ソフトウェアとたわむれる日々

第4回Plamo Linux 4.7とPlamoのビルドスクリプト

過去2回に渡ってソフトウェアのトラブル対策の話題を取りあげましたが、それらを何とか乗り越えて、無事Plamo Linuxの新版である4.7を10月の初めにリリースすることができました。そこで今回は、Plamo Linuxがらみの話をしてみましょう。

Plamo Linuxについて

本連載を読まれている方はご存じのことと思いますが、Plamo Linuxとは、私がとりまとめ役になって開発を続けているLinuxディストリビューションです。

Plamo Linuxのきっかけは、当時のメジャー・ディストリビューションだったSlackware Linuxを使いやすくするために、インストーラを日本語化しようとしたことでした。その後、インストーラだけでなく、パッケージもあらかじめ日本語に対応したものに入れ替えるために、Slackwareから独立して独自の道を歩むことになりました。

公開当初は、インストール直後から日本語が使えるディストリビューションとしてそれなりに使われたものの、より進んだパッケージ管理システムと大規模な開発者リソースを持ったRed Hat LinuxやDebian GNU/Linuxが普及し、それらの国際化が進んで日本語も問題なく使えるようになるにつれて、Plamo Linuxの影は薄くなってきました。

最近はソフトウェアの大規模化、高機能化が進み、複雑な設定や絡みあった依存性に閉口することも多いのですが、昔から使い続けてくれるユーザもいますし、協力を惜しまないメンテナの方々もいます。何よりも、自分にとって手になじんだ環境を守りつつ最近の便利なソフトウェアも使いたい、そういうわがままからコツコツと続けているうちに、いつの間にか10年以上の月日が経ってしまいました。

ちなみに、Plamo Linuxのリリース歴はメンテナの一人でもある加藤さんが@niftyのTimeLineとしてまとめてくれているので、興味ある方はご覧ください。下図はそのうちのここ2年ほどの部分です。

図1 @niftyのPlamo LinuxのTimeLine
図1 @niftyのPlamo LinuxのTimeLine

Plamo Linux 4.7

Plamo Linux 4.7は、今年の2月ごろに公開した4.6の次にあたる公式リリース版です。GCCやglibc2といった主要パーツがバージョンアップしているため、バージョン番号は4.61ではなく4.7としましたが、含まれているパッケージ類は4.6と大きく変わらず、やや見切り発車的だった4.6の不具合を修正した、かなり扱いやすいバージョンになっていると思います。

GNOME環境では、本連載でも取りあげたfile-rollerアーカイバと共に、gThumb画像ビューワがEUC-JPな日本語ファイル名を正しく扱えない問題にも対処しましたし、KDE環境は、新しくメンテナにご参加いただいた本多さんの御尽力で、ライブラリレベルでの文字コードの扱いがずいぶん改善し、4.6ではしばしば発生していたEUC-JPなファイル名の文字化けがほとんど見られなくなりました。

図2 KDE-4.3.1の画面例
図2 KDE-4.3.1の画面例

先に紹介したタイムラインを見ても、2007/10に公開された4.22から、インストーラやパッケージ構成に大きな変更を加えた4.5までは1年ほど空きましたが、その後は約半年ぐらいの間隔で4.6, 4.7と進むことができました。

一方、4.7公開後にXのサーバをxorg-server-1.6系に更新したり、KDEも4.3.2に更新されるなど、すでに開発版にはかなり大きな更新が入っているので、そう遠くないうちにメンテナンスリリースを出す必要がありそうです。OSSの開発が盛んになるのはいいことですが、それらに追従し続けるのはなかなか大変です。

パッケージ形式とビルドシステム

Plamoの新版の宣伝だけでは「玩式草子」のネタにならないので、今回はPlamo Linuxの裏方であるビルドシステムについて紹介してみます。その前に少しLinuxの代表的なパッケージ形式について復習しておきましょう。

TGZ形式

Slackware/Plamo Linuxが採用しているパッケージ形式で、インストールしたいファイルを適切なディレクトリ構造に配置した上でtarコマンドで固め、それをgzipで圧縮した形式です。

この形式はLinuxの基本コマンドであるtarとgzipさえあれば操作できるので作成も展開も容易ですが、元々バイナリパッケージ配布用に考えられた形式ではないので、ライブラリやコマンドの依存関係をチェックしたりインストール情報を保存するような機能はありません。そのためSlackwareではinstallpkg/removepkgという専用のツールを用意して、installpkgでインストールしたパッケージの情報を/var/log/packages/ディレクトリに保存し、removepkgでこの情報を元にインストールしたファイルを削除するようになっています。

これらのツールはPlamo Linuxでもそのまま流用しています。

RPM形式

元々はRed Hat社が考案したパッケージ形式(Redhat Package Manager)でしたが、後に仕様を公開し、誰でも自由に使えるようにしたため、最近のLinuxでは最も広く用いられているパッケージ形式です。

RPMはTGZ形式の問題点を十分検討した上で考案されたパッケージ形式で、インストールするファイルはtarではなくCPIO形式でまとめて圧縮されており、パッケージの先頭部にライブラリやコマンドの依存関係など、管理に必要な情報が付加されています。そのため、RPM形式のファイルを操作するには専用のコマンドrpmが必要になります。なお、ヘッダ部分の管理情報を剥いてしまえばcpioコマンドでファイルを取り出すことも可能です。

RPM形式では、1つのパッケージ内に管理に必要な情報を全て盛りこんであるので、rpmファイルはシステムに関する暗黙の前提なしに、完結したパッケージとして利用できるようになっています。一方、そのような情報をきちんと盛り込むためには専用のSPECファイルが必要で、SPECファイルを書くにはそれなりの知識と経験が必要になります。

DEB形式

元々Debian GNU/Linuxで考案されたパッケージ形式で、インストールすべきバイナリファイルをまとめたtar.gzファイル(data.tar.gz)と、管理情報等をまとめたファイル(control.tar.gz)arで固めた形式になっています。

DEB形式のパッケージも、本来はdpkg等の専用コマンドを利用して操作することを前提に作成されていますが、それら専用コマンドが無い環境でも、基本コマンドであるtargziparがあれば展開できるように設計されているのは思慮深いところです。

DEB形式のパッケージを作るためには、標準のMakefile以外にさまざまな設定ファイルが必要です。作業のかなりの部分はdh_makeコマンド等で自動化されるものの、Debian独自のルールに十分精通している必要があります。


上述のように、元々ソースコードを配布するために利用されていたTGZ形式は、パッケージを作るために特別な知識は必要ないものの、パッケージ管理に必要な機能を持たないため、それらを外部から補ってやる必要があります。補うのはツールであったり、ユーザの知識だったりします。

一方、最初からパッケージ配布用に考案されたRPMやDEBの形式は、単独のパッケージ内に管理に必要な情報を持つものの、パッケージの作成にはそれぞれ個別の知識が必要になります。

RPMやDEB形式ではパッケージの形式だけでなく、それらのパッケージを作るための手法も提供しています。たとえば、RPM形式ならばパッケージを作成するためにはSPECファイルが必要となります。このSPECファイルには、ソースコードの在所やパッチファイルとその当て方、必要なライブラリとそのバージョン、コンパイル時のオプションなどの情報を記載することができ、一度完成してしまえば設定を調整してコンパイルし直すのにも便利ですし、SPECファイルを使えば誰でもメンテナと同じ設定でパッケージを作成し直すこともできます。

Plamoの場合、元々のSlackware同様、TGZ形式を採用していますが、RPMやDEBの高機能に魅かれて手習いでいくつかSPECファイルを書いてみたこともあります。しかし、実際にSPECファイルを書いてみると、書かねばならないことが結構あって大変で、開発者リソースが豊富な大手ディストリビューションならばともかく、Plamoの規模ではとても対応できそうにありません。

Plamo Linuxのビルドシステム

最近のPlamo Linuxを構成しているパッケージは1300を越えており、それら全てにSPECファイルを書くことは作業量的にも不可能です。しかし、コンパイル時の設定くらいは残しておかないと将来のバージョンアップ時にも不便なため、しばらく前から私が作るパッケージはPlamoBuildというシェルスクリプトでビルドするようにしています。

最近のほとんどのソフトウェアには configure スクリプトが添付しており、

 ./configure && make && sudo make install

くらいでインストールできるようになっています。

そこで、この処理を中心に、ファイルのインストール先を設定したり、インストールしたマニュアルやドキュメント類を圧縮したり、バイナリファイルから不要なデバッグ情報を削除する等の処理を追加していきました。

そうやってパッケージをビルドしているうちに、スクリプト内で汎用的に使い回せる部分とソフトウェアごとに調整が必要な部分が見えてきました。それらを踏まえて、メンテナの田向さんがテンプレート用スクリプトを作ってくれました。このスクリプトでは、パッケージごとに調整しなければならない部分は先頭付近(ヘッダ部)にまとめられています。

たとえば、gzip-1.3.12用のPlamoBuildスクリプト(PlamoBuild.gzip-1.3.12)のヘッダ部はこんな風になっています。

リスト1 PlamoBuildスクリプトのヘッダ部の例(PlamoBuild.gzip-1.3.12)
 #!/bin/sh
 ##############################################################
 url='ftp://ftp.gnu.org/gnu/gzip/gzip-1.3.12.tar.gz'
 pkgbase=gzip
 vers=1.3.12
 arch=i586
 build=P3
 src=gzip-1.3.12
 OPT_CONFIG=''
 DOCS='AUTHORS COPYING ChangeLog INSTALL NEWS README README-alpha THANKS TODO'
 patchfiles='gzip-1.3.12_futimens.patch gzip-1.3.12_zdiff.patch'
 ##############################################################

各行を簡単に紹介しておきましょう。

url行は、ソースコードのインターネット上での在処を指定します。

pkgbaseからbuildまでの行はパッケージ名の生成に使われます。

srcはソースコードの存在するディレクトリ名です。

OPT_CONFIGは configure スクリプトに与えるオプションを指定します。

なお、Plamo Linuxでの標準的なファイル配置にするためのオプション(--prefix=/usr等)は、configureスクリプトに直接与えるようになっているため、指定は不要です。

DOCSはこのパッケージでインストールされるドキュメントファイルの指定です。

patchfilesは、configureの前にソースコードに適用するパッチファイルの指定です。

これらの部分をそれぞれのソースコードに合わせて調整するだけで、PlamoBuild.templateはたいていのパッケージをビルドできるようになっています。

このPlamoBuildスクリプトは、download, config, build, package の4つの引数によって動作を指定できます。

download を指定するとヘッダ部のurl行で指定した場所からwgetでファイルをダウンロードして、展開してくれます。

 % ./PlamoBuild.gzip-1.3.12 download
 --2009-10-31 10:51:38--  ftp://ftp.gnu.org/gnu/gzip/gzip-1.3.12.tar.gz
            => `gzip-1.3.12.tar.gz'
 ftp.gnu.org をDNSに問いあわせています... 140.186.70.20
 ftp.gnu.org|140.186.70.20|:21 に接続しています... 接続しました。
 anonymous としてログインしています... ログインしました!
 ==> SYST ... 完了しました。    ==> PWD ... 完了しました。
 ==> TYPE I ... 完了しました。  ==> CWD /gnu/gzip ... 完了しました。
 ==> SIZE gzip-1.3.12.tar.gz ... 462169
 ==> PASV ... 完了しました。    ==> RETR gzip-1.3.12.tar.gz ... 完了しました。
 長さ: 462169 (451K)
 
 100%[======================================>] 462,169      260K/s 時間 1.7s    
 
 2009-10-31 10:51:43 (260 KB/s) - `gzip-1.3.12.tar.gz' へ保存終了 [462169]

 gzip-1.3.12/
 gzip-1.3.12/amiga/
 gzip-1.3.12/amiga/match.a
 gzip-1.3.12/amiga/Makefile.gcc
 ...

config を指定すると、ソースコードのディレクトリ(上記ヘッダ部分でのsrc行で指定したディレクトリ)以下のファイルを、新しく作ったbuildディレクトリ以下にコピーし、patchfiles行で指定したパッチを当ててから、configureスクリプトを実行し、ビルドに必要なMakefileの類いを生成します。

build を指定すると、上記で作成したbuildディレクトリに移動してmakeコマンドを実行します。

package を指定すると、build ディレクトリに移動した上で、インストール用の作業領域をDESTDIRに指定して make installを実行し、作成したバイナリファイルなど必要なファイルを指定したディレクトリにインストールします。

合わせて、指定したドキュメント類のインストールと圧縮、バイナリファイルのstrip処理などを行った上で、パッケージ作成用の /sbin/makepkg コマンドを実行して、ヘッダ部の pkgbase, vers, arch, build の各行で指定した名称のパッケージ(今回の例では gzip-1.3.12-i586-P3.tgzを作成します。

引数を指定しなければ、PlamoBuildスクリプトはconfig, build, packageの処理を順に行うようになっています。

 % ./PlamoBuild.gzip-1.3.12 
 patching file gzip.c
 patching file lib/utimens.c
 patching file lib/utimens.h
 patching file zdiff.in
 checking for a BSD-compatible install... /usr/bin/install -c
 checking whether build environment is sane... yes
 checking for a thread-safe mkdir -p... /bin/mkdir -p
 checking for gawk... gawk
 ...
 config.status: executing depfiles commands
 Making all in lib
 make[1]: ディレクトリ `/share/Srcs//Work/build/lib' に入ります
 rm -f fcntl.h-t fcntl.h
 rm -f stdlib.h-t stdlib.h
 { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
 ..
 gcc -std=gnu99  -g -O2   -o gzip bits.o crypt.o deflate.o gzip.o inflate.o lzw.o trees.o unlzh.o unlzw.o unpack.o unzip.o util.o zip.o lib/libgzip.a 
 make[1]: ディレクトリ `/share/Srcs//Work/build' から出ます
 Do you want to package as root? [y/N] 

パッケージ作成時にはroot権限で正式なパッケージを作るか、一般ユーザ権限でパッケージ作成のテストを実行するかを問われます。インストール作業用の領域は一般ユーザでも書き込めるので、まずは一般ユーザ権限で一度パッケージを作成してみた上でroot権限で再度作成するのがお勧めです。

 Do you want to package as root? [y/N] 
 Making install in lib
 make[1]: ディレクトリ `/share/Srcs/Work/build/lib' に入ります
 make  install-am
 make[2]: ディレクトリ `/share/Srcs/Work/build/lib' に入ります
 ...
 pruning symlink in /share/Srcs/Work/work/usr/share/man/man9
 pruning symlink in /share/Srcs/Work/work/usr/share/man/mann
 Making ../gzip-1.3.12-i586-P3.tgz...

最終的にはmakepkgコマンドがシンボリックリンクを刈りとって、TGZ形式のパッケージを作成します。


最近は少なくなったものの、make install 時に DESTDIR= の指定を見ずに、設定ファイル等を決め打ちで/etc等にインストールするお行儀の悪いソフトウェアも残っているので、それらをチェックするためにも、一般ユーザ権限でmake installして、DESTDIR=で指定した領域以外に書き込みが生じないかを確認する方が安全です。

ただし、一般ユーザ権限で作成したパッケージはファイルの属性が正しく設定されないため、そのままではパッケージとして不適切です。

 % tar tvf gzip-1.3.12-i586-P3.tgz 
 drwxr-xr-x kojima/users      0 2009-10-31 11:23:31 bin/
 -rw-r--r-- kojima/users      0 2009-10-31 09:00:00 bin/gzip
 -rw-r--r-- kojima/users      0 2009-10-31 09:00:00 bin/gunzip
 ...

そのため、きちんとパッケージが作成されることを確認した上で、再度パッケージ作成処理をroot権限で実行します。

 % ./PlamoBuild.gzip-1.3.12 package
 Do you want to package as root? [y/N] y
 パスワード: *****
 Making install in lib
 make[1]: ディレクトリ `/share/Srcs/Work/build/lib' に入ります
 make  install-am
 ...

root権限で作成したパッケージは、必要な属性情報が正しく設定されますので、こうして作成したパッケージはinstallpkgupdatepkg でインストールできます。

 % tar tvf gzip-1.3.12-i586-P3.tgz 
 drwxr-xr-x root/root         0 2009-10-31 11:27:47 bin/
 -rw-r--r-- root/root         0 2009-10-31 09:00:00 bin/gzip
 -rw-r--r-- root/root         0 2009-10-31 09:00:00 bin/gunzip
 ...

なお、updatepkg はPlamo-4.6あたりで追加したコマンドで、古いパッケージをremovepkgで削除した上で、新しいパッケージをinstallpkgします。また、Plamo-4.7ではパッケージのインストール/アンインストールの記録を/var/log/install.log に記録するようにしたので、いつパッケージを更新したか等を確認することも容易になりました。

PlamoBuildスクリプトの置き場所

PlamoBuildスクリプトは、/usr/share/doc/ディレクトリに置かれた、それぞれのパッケージごとのドキュメントファイルのディレクトリに、圧縮した状態でインストールされます。

今回紹介したPlamoBuild.gzip-1.3.12の場合、/usr/share/doc/gzip-1.3.12/PlamoBuild.gzip-1.3.12.gz に置かれています。

 % ls /usr/share/doc/gzip-1.3.12/
 AUTHORS.gz    INSTALL.gz                  README-alpha.gz  TODO.gz
 COPYING.gz    NEWS.gz                     README.gz        gzip-1.3.12_futimens.patch.gz
 ChangeLog.gz  PlamoBuild.gzip-1.3.12.gz*  THANKS.gz        gzip-1.3.12_zdiff.patch.gz

このディレクトリにはパッケージ作成に使ったパッチファイルも置かれているので、手元のディレクトリに展開したビルドスクリプトとパッチファイルを配置した上で、PlamoBuildスクリプトを実行すれば、お手元の環境で、私がビルドしたのと同じ設定でパッケージを再生成することができます。

Plamo Linuxの場合、パッケージをどのような方式でビルドするかは各メンテナにお任せしているので、必ずしも全てのパッケージに今回紹介したビルドスクリプトが含まれているわけではありません。また、パッケージによっては、そのソフトウェアの流儀に合わすために、よりカスタマイズしたスクリプトを使っていることもありますので、興味ある人はぜひ確認してみてください。

おすすめ記事

記事・ニュース一覧