[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[plamo:12235] How to make packages



こじま@風邪と GPM でダウン中、、です。

# さっさとセキュリティ関係も含めてパッケージ類のアップデートをしないと
# いけないんだけど、今回はちょっと off topic な話題

某氏から Slackware 系のパッケージについての解説記事を頼まれていて以下
のようなものを書いてみました。内容的には以前に ML に流したものと同じで
すが、パッケージ作りについて興味ある人がいらっしゃれば参考になるかと思っ
て、こっちにも流してみます。

今週末くらいが締切(のはず、、^^;)なので、添削 & コメント等も歓迎します。

---------------------------------------------------------------------

◎◎tgz

Slackware系のディストリビューションが採用しているパッケージ形式はその
拡張子から tgz 形式と呼ばれています。しかし、tgz は独自のファイル形式
ではなく、インストールすべきファイル(バイナリと各種設定ファイル)とイン
ストール後に実行されるスクリプトを tar 形式で固めてから gzip で圧縮し
たファイルになっています。展開に必要なコマンドもほとんどの UNIX 系のシ
ステムには存在している tar と gzip だけなので、Linux 以外の環境で設定
ファイル等を参照したい場合なども簡単に展開して中身を見ることが可能です。

◎tgz ファイルの中身

tgz ファイルの中身は、インストールすべき各ファイルが / を起点とした相
対パスで指定された位置に配置されています。例えば、gzip.tgz の中身を 
tar tzvf コマンドで見ると、以下のようになっています。

kojima@sv# tar tzvf gzip.tgz 
drwxr-xr-x root/root         0 1999-04-06 07:30 usr/
drwxr-xr-x root/root         0 1995-08-07 07:46 usr/man/
drwxr-xr-x root/root         0 1999-04-06 07:30 usr/man/man1/
-rw-r--r-- root/root      1823 1999-04-06 07:30 usr/man/man1/zmore.1.gz
-rw-r--r-- root/root       545 1999-04-06 07:30 usr/man/man1/znew.1.gz
-rw-r--r-- root/root       528 1999-04-06 07:30 usr/man/man1/zgrep.1.gz
-rw-r--r-- root/root       716 1999-04-06 07:30 usr/man/man1/gzexe.1.gz
-rw-r--r-- root/root       421 1999-04-06 07:30 usr/man/man1/zdiff.1.gz
-rw-r--r-- root/root       378 1999-04-06 07:30 usr/man/man1/zforce.1.gz
-rw-r--r-- root/root      5403 1999-04-06 07:30 usr/man/man1/gzip.1.gz
drwxr-xr-x root/root         0 1999-04-06 07:30 usr/info/
-rw-r--r-- root/root     12556 1999-04-06 07:30 usr/info/gzip.info.gz
drwxr-xr-x root/bin          0 1994-03-16 09:33 usr/bin/
-rwxr-xr-x root/root      3840 2000-09-16 12:34 usr/bin/gzexe
-rwxr-xr-x root/root      1333 2000-09-16 12:34 usr/bin/zgrep
-rwxr-xr-x root/root      3502 2000-09-16 12:34 usr/bin/znew
-rwxr-xr-x root/root      1004 2000-09-16 12:34 usr/bin/zforce
-rwxr-xr-x root/root      2000 2000-09-16 12:34 usr/bin/zdiff
drwxr-xr-x root/bin          0 1994-03-16 09:33 bin/
-rwxr-xr-x root/root     57014 2000-09-16 12:34 bin/gzip
drwxr-xr-x root/root         0 2001-06-14 22:22 install/
-rw-r--r-- root/root       388 2001-06-14 22:22 install/doinst.sh

これらのファイルのうち、最後にある install/doinst.sh 以外のファイルは 
gzip のソースパッケージに由来するファイルです。install/doinst.sh ファ
イルは tgz ファイルの展開後に実行されるシェルスクリプトで、tar ファイ
ルに混ぜてしまうと危険なシンボリックリンクの作成等に用いられます。

このように tgz パッケージではソースコードを make ; make install してイ
ンストールされるファイル以外は含まないため、パッケージの内容やバージョ
ンの情報等は別途用意してやる必要があります。

◎パッケージに関する情報

tgz ファイルの場合、上述のようにパッケージに関する情報等は tgz ファイ
ル以外の部分に用意しなければなりませんが、そのために用いられるファイル
がそのパッケージがあるディレクトリの diskXXX と言うファイルです。この 
XXX の部分には、そのパッケージが属するディスクセットの名称(a1 や ap1 
等)が入ります。

diskXXX ファイルは、最初に CONTENTS で始まるそのディスクセットに含まれ
るパッケージの一覧を示す行があり、その後は各パッケージのバージョンや内
容等を記述した行が 11 行ずつ続きます。例えば、a1 ディスクセットの 
diska1 ファイルは以下のような内容になっています。

CONTENTS: aaa_base basebin baseutil bash bsdlpr complibs cpio devs e2fsbn elflibs etc find getty
 glibc2 grep grub gzip hdsetup ide jbase jman kbd ldso less notekern pcmcia prutil ps readln22 r
ecjis scsi sh_utils shadow sysklogd sysvinit tar tcsh txtutils zoneinfo gpm lilo konbin konfnt l
oadlin modules pnp
aaa_base: Linux の基本的なファイルシステムパッケージ
aaa_base: 
aaa_base: 基本的なディレクトリ構造を作成して、GNU mtools 3.7 や 
aaa_base: fdutils-5.2 zip201、 unzip512 など、必須のバイナリをイン
aaa_base: ストールします。
aaa_base: 
aaa_base: 
aaa_base: 
aaa_base: 
aaa_base: 
aaa_base: 
basebin:  /bin と /usr/bin へインストールする各種コマンド
basebin:  
basebin:  以下のようなシステムコマンドをまとめています.

後述する installpkg コマンドや pkgtool コマンドを用いてパッケージをイ
ンストールすると、このファイルの各パッケージの説明メッセージが画面に表
示されると共に、/var/log/packages ディレクトリにインストールしたパッケー
ジ名としてファイル名やサイズ、含まれるファイルのリストなどと共に登録さ
れます。

◎パッケージの操作方法

前述のように、tgz ファイルは tar と gzip のみで作成されているため、tar 
と gzip コマンドさえあれば手動でもインストールできますが、
/sbin/installpkg や /sbin/pkgtool コマンドを使ってインストールすると、
上記 /var/log/packages 以下にインストールしたファイルの情報が保存され、
不要になったパッケージは /sbin/removepkg コマンドで削除できるので便利
です。/var/log/packages ディレクトリには、インストールしたパッケージ名
のファイルが用意され、例えば find の場合は以下のような情報が記録されて
います。

パッケージ名:     find
圧縮時のパッケージのサイズ:     120 K
非圧縮時のパッケージのサイズ:     270 K
パッケージの所在: diska1
パッケージの内容:
find:     GNU find ユーティリティ 4.1
find:
find:     GNU 版の find, xargs, locate などのプログラム集です。
find:     find と xargs は、私の知る限り POSIX 1003.2 互換です。加
find:     えて、いくつかの Unix 由来の追加機能や GNU 独自の追加機
find:     能が入っています。
find:
FILE LIST:
./
usr/
usr/bin/
usr/bin/find
usr/bin/xargs
usr/bin/locate
usr/bin/updatedb
usr/man/
usr/man/man1/
usr/man/man1/xargs.1.gz
usr/man/man1/find.1.gz
.....

installpkg コマンドは指定したパッケージをインストールすると共に、
diska1 ファイルからこのパッケージに関する概要を抽出してこのファイルに
追加し、FILE LIST: 以下にインストールしたファイルを記録します。
removepkg コマンドはこのファイルを参照して、インストールしたファイルを
削除し、削除が成功すれば /var/log/packages 以下のファイルも削除してア
ンインストールを実行します。

パッケージ操作用ツールのうち installpkg と removepkg はパッケージ名を
引数として直接実行するコマンド、pkgtool はパッケージ管理ツールとしてこ
れらのコマンドを起動するラッパーになっています。pkgtool コマンドはパッ
ケージのインストール/アンインストール以外にインストールしたパッケージ
のリストや内容を表示する機能もあります。

これらパッケージ操作用ツールの実体はシェルスクリプトで、内部的に sed 
や head、cat と言った単機能のコマンドを組み合わせて複雑な処理を実現し
ています。パイプや一時ファイルなどを駆使して単機能ツールを組み合わせる
手法は UNIX の真骨頂であり、シェルスクリプトの教材としてこれらパッケー
ジ管理ツールの中身を調べてみるのも面白いかも知れません。

なお、installpkg/pkgtool を使う場合は自動的に処理されますが、手動で 
tgz ファイルをインストールする場合は以下の点に注意してください。

・パッケージは / を起点に配置されているので、tar で展開する場合、cd / 
  するか、-C オプションで / ディレクトリを指定して展開する必要があります。

・パッケージに /install/doinst.sh ファイルが存在する場合(存在しないこ
  ともあります)、パッケージを展開した後、/install/doinst.sh ファイルを
  実行(シェルスクリプトです)し、その後 rm -rf /install/ してください。

・手動でパッケージをインストールした場合、/var/log/packages 以下に情報
  が登録されないため、removepkg で削除することはできません。

◎◎ tgz パッケージの作成方法

tgz ファイルは基本的に make install で作成、インストールされるファイル
を固めただけなので tar と gzip を使って手動で作成することも可能ですが、
/sbin/makepkg というパッケージ作成用コマンドも用意されています。
makepkg コマンドを使えば、シンボリックリンクは自動的に 
install/doinst.sh スクリプトで作成するように設定されるのも便利な点です。

しかし makepkg コマンドはパッケージ名を引数に取り、カレントディレクト
リ以下のファイルを tar で固めて gzip で圧縮する機能しかありません。そ
のため、makepkg コマンドを実行するためには、実際に必要なファイル(実行
ファイルや設定ファイル)はあらかじめカレントディレクトリ以下に適切に配
置するという作業が必要になります。

「カレントディレクトリ以下に必要なファイルを配置する」ための決まった手
法は存在していませんが、最近の GNU configure スクリプトを採用している
ソフトウェアの場合、make install 時に prefix オプションでインストール
先のディレクトリを指定することができるので、この機能を使えば簡単にパッ
ケージを作成することができます。

以下に、例として gzip-1.2.4a.tar.gz をパッケージ化する手順を示します。
gzip-1.2.4a.tar.gz では make install 時の prefix オプションが有効なの
で、その機能を使ってカレントディレクトリの ./work/usr 以下にファイルを
インストールして、./work ディレクトリで makepkg コマンドを実行していま
す。

kojima@b5r# tar xvzpf gzip-1.2.4a.tar.gz 
gzip-1.2.4a/
gzip-1.2.4a/README
gzip-1.2.4a/NEWS
gzip-1.2.4a/INSTALL
....
kojima@b5r# cd gzip-1.2.4a
kojima@b5r# ./configure
checking for gcc
checking how to run the C preprocessor
checking for underline in external names
....
creating config.status
creating Makefile
kojima@b5r# make
gcc -c -DASMV -DSTDC_HEADERS=1 -DHAVE_UNISTD_H=1 -DDIRENT=1 -O gzip.c
gcc -c -DASMV -DSTDC_HEADERS=1 -DHAVE_UNISTD_H=1 -DDIRENT=1 -O zip.c
gcc -c -DASMV -DSTDC_HEADERS=1 -DHAVE_UNISTD_H=1 -DDIRENT=1 -O deflate.c
...
ln gzip gunzip
ln gzip zcat
kojima@b5r# mkdir -p work/usr
kojima@b5r# make install prefix=`pwd`/work/usr
if test ! -d /home/kojima/work/gzip-1.2.4a/work/usr/man; then \
   mkdir /home/kojima/work/gzip-1.2.4a/work/usr/man; fi
....
kojima@b5r# cd work/
kojima@b5r# ls usr/bin/
gunzip*  gzexe*   gzip*    zcat*    zcmp*    zdiff*   zforce*  zgrep*   zmore*   znew*
kojima@b5r# makepkg gzip.tgz

Slackware package maker, version 1.0.

Searching for symbolic links:

No symbolic links were found, so we won't make an installation script.
You can make your own later in ./install/doinst.sh and rebuild the
package if you like.

This next step is optional - you can set the directories in your package
to some sane permissions. If any of the directories in your package have
special permissions, then DO NOT reset them here!

Would you like to reset all directory permissions to 755 (drwxr-xr-x) and
directory ownerships to root.root ([y]es, [n]o)? y

mode of . retained as 0755 (rwxr-xr-x)
mode of ./usr retained as 0755 (rwxr-xr-x)
mode of ./usr/man retained as 0755 (rwxr-xr-x)
....

tar: gzip.tar is the archive; not dumped

Gzipping gzip.tar...

Renaming gzip.tar.gz to gzip.tgz...

Package creation complete.

kojima@b5r# ls
gzip.tgz  usr/

kojima@b5r# tar tzvf gzip.tgz 
drwxr-xr-x kojima/users      0 2001-11-01 18:58 ./
drwxr-xr-x kojima/users      0 2001-11-01 18:57 usr/
drwxr-xr-x kojima/users      0 2001-11-01 18:57 usr/man/
drwxr-xr-x kojima/users      0 2001-11-01 18:57 usr/man/man1/
-rw-r--r-- kojima/users  13923 2001-11-01 18:57 usr/man/man1/gzip.1
-rw-r--r-- kojima/users   1296 2001-11-01 18:57 usr/man/man1/gzexe.1
-rw-r--r-- kojima/users    802 2001-11-01 18:57 usr/man/man1/zdiff.1
....

上記の例では make install したファイルをそのままパッケージ化しています
が、make install だけではインストールされない文書類も usr/doc ディレク
トリにコピーしておけば参照が必要な時に便利ですし、man ページやドキュメ
ントの類いは gzip で圧縮、バイナリファイルは strip で不要なシンボルを
削除する等の処理をすれば多少なりともパッケージのサイズを減らすことが可
能です。

一方、make install 時に prefix オプションが効かないソフトウェアの場合
は必要なファイルをリストアップするのがかなり面倒になります。

ソフトウェアを実際にはインストールせず、ファイルがどこにインストールさ
れるかを調べる場合は make -n install コマンドを実行した際のログを保存し、
実行されている install コマンドをチェックするという方法があります。

ソフトウェアを実際にインストールしてしまっていい場合は find の -cnewer 
オプションが便利です。以下の例では /tmp/datetest ファイルが日時のチェッ
クファイルで、make install でインストールされた /tmp/datetest ファイル
よりも新しいファイルを表示します。

# touch /tmp/datetest
# make install
# find / -cnewer /tmp/datetest

これで見つかったファイルを適切なディレクトリ以下に配置して makepkg コ
マンドでパッケージ化することができます。

上記 find コマンドを使ってインストールしたファイルを検索する手順を自動
化するために instmon と呼ばれるスクリプトが開発されています
(http://hal.csd.auth.gr/~vvas/instmon/URL)。

instmon コマンドをオプションを指定せずに実行すると起動時間が記録された
上で sub shell が起動されます。その shell の中でインストール作業を行う
と、新しくインストールしたファイルや変更を加えたファイルの記録が残され、
インストール終了後、 sub shell を抜け、作成する形式を指定して(instmon 
は tar 以外にも rpm や deb 形式のファイルを作成することも可能です)
instmon コマンドを実行すれば、先の sub shell の中でインストールしたファ
イルを抽出してパッケージ化してくれます。

bash-2.04# instmon
/usr/local/bin/instmon: type: strace: not found
/usr/local/bin/instmon: type: installwatch: not found
instmon: Monitoring package strace-4.4 ...
instmon: Recording timestamp ...
instmon: Spawning /bin/bash ...
instmon: Perform the installation, then type `exit' to continue ...
bash-2.04# make install
/bin/install -c strace /usr/local/bin/strace
/bin/install -c ./strace-graph /usr/local/bin/strace-graph
/bin/install -c -m 644 ./strace.1 /usr/local/man/man1/strace.1
bash-2.04# exit
exit
instmon: Detecting changes ...
instmon: Finished.

bash-2.04# instmon --tar           
instmon: Acting on package strace-4.4 ...
instmon: Creating tar archive in /tmp ...
instmon: Finished.

bash-2.04# tar tvf /tmp/strace-4.4.tar 
-rwxr-xr-x root/root    159427 2001-11-02 10:28 usr/local/bin/strace
-rwxr-xr-x root/root      8323 2001-11-02 10:28 usr/local/bin/strace-graph
-rw-r--r-- root/root     18571 2001-11-02 10:28 usr/local/man/man1/strace.1

インストールするファイルが単純な場合は instmon が作成した tar ファイル
をそのまま圧縮して tgz 形式にすることも可能ですが、シンボリックリンク
等がある場合は作成した tar ファイルを適当なディレクトリに展開し、
makepkg コマンドで tgz 化する方が確実でしょう。

make install コマンドで直接インストールしたソフトウェアは pkgtool 等で
検出できないため削除が難しいという問題がありますが、make install でイ
ンストールした後に instmon 等を使ってパッケージ化し、再度 installpkg 
でファイル類を上書きするようにインストールしておけば pkgtool や 
removepkg コマンドで削除可能になります。

◎終りに

Slackware 系のパッケージは rpm や deb のように洗練されたパッケージ管理
の仕組みは用意されていませんが、その分、誰でも簡単に自分用のパッケージ
を作成することができるでしょう。PC-UNIX の面白さの一つは、自分が使うソ
フトは自分の環境に合わせて構築することができることです。与えられたコン
パイル済みのバイナリパッケージをインストールすることに飽きたら、ぜひ一
度自分の手でソースコードからコンパイルしてパッケージを作ってみてくださ
い。そうすることで、Linux の新しい面白さが見えてくるに違いありません。

Follow-Ups
[plamo:12296] Re: How to make packages, KAWABATA, Ken-ichi

[検索ページ] [メール一覧]
Plamo ML 公開システム