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

第38回Plamo Linuxのビルドスクリプトとパッケージ管理ツールその1]

日中は厳しい残暑が続くものの、朝晩はずいぶん涼しくなり、2台のマシンに火を入れても作業できるようになってきました。8月の上旬には非常勤講師の仕事の方も一段落したので、しばらくの間停滞していた32ビット版のパッケージ作り作業に復帰し、とりあえず32ビット版でもXfce-4.10が動く程度にはパッケージを揃えてみました。

図1 Xfce-4.10 on Plamo/32
図1 Xfce-4.10 on Plamo/32

このひと月ばかり、ずっとパッケージ作りに励んでいましたが、どれくらいパッケージを作ったかな、と思ってplamo.linet.gr.jpのそれぞれのディレクトリを調べてみたところ、

% find x86_64 -type f -user kojima -mtime -40 -name "*txz" | wc -l
367
% find x86 -type f -user kojima -mtime -40 -name "*txz" | wc -l
467

となり、800を越えるパッケージを更新していたようです。

もちろん、パッケージは「速く作る」ことよりもきちんと作ることが大事なのは言うまでもありませんが、X Window SystemやXfce,KDEといった関連するソフトウェアが多数におよぶ大規模なシステムの場合、ある程度まとめてパッケージを作らないと動作テストすらできません。

このひと月ほどの間に、64ビット環境ではKDE-4.9.0を、32ビット環境ではX11R77Xfceを動作できるようにしたので、これだけ多くのパッケージを短期間のうちに更新することになったのでしょう。

これくらいのペースでパッケージを作ろうとすると、一々手動でconfigureやmakeをしていては大変なので、ビルドスクリプトで自動化することが必須になります。

Plamo Linuxで採用しているtgz/txz形式のパッケージはrpmやdebに比べて非力ですが、その分作成するのも簡単で、最近のソフトウェアではほぼ自動的にパッケージを作成することができます。今回から何回かに分けてPlamo Linuxのビルドスクリプトとパッケージ管理システムについて解説してみましょう。

PlamoBuildスクリプトの使い方

Plamo Linuxのパッケージを作るためのビルドスクリプトは、それぞれのパッケージごとにPlamoBuild."パッケージ名-バージョン番号"という名前で、/usr/share/doc/以下の"パッケージ名-バージョン番号"ディレクトリ以下にgzip形式で圧縮して収められています。

たとえば、XfceのファイルマネジャーであるThunar-1.4.0の場合、/usr/share/doc/Thunar-1.4.0/PlamoBuild.Thunar-1.4.0.gz がビルドスクリプトです。なお、このディレクトリにはビルドスクリプト以外にも、ソースコードに添付されていたREADME等のファイルが圧縮して収められています。

$ ls /usr/share/doc/Thunar-1.4.0/
AUTHORS.gz      HACKING.gz                   README.gtkrc     TODO.gz
COPYING.LIB.gz  INSTALL.gz                   README.gz        Thunar-1.4.0-filename-order.patch.gz
COPYING.gz      NEWS.gz                      README.thunarrc
ChangeLog.gz    PlamoBuild.Thunar-1.4.0.gz*  THANKS.gz

PlamoBuildスクリプトは、完結したシェルスクリプトとして設計されているので、ビルドスクリプトからパッケージを再構築するのは簡単です。ビルドスクリプトは、downloadconfigbuildpackageの4つのコマンドを指定でき、それぞれソースコードのダウンロード、configure等の実行、コンパイル、ビルドしたファイルのパッケージ化、の処理を行います。

例として、先に見たPlamoBuild.Thunar-1.4.0.gzを用いてパッケージの再構築をしてみましょう。

まず適当なディレクトリを用意して、そこにビルドスクリプトをコピー、展開しておきます。

$ mkdir /mnt/Srcs/T/Thunar ; cd /mnt/Srcs/T/Thunar
$ cp /usr/share/doc/Thunar-1.4.0/PlamoBuild.Thunar-1.4.0.gz . 
$ gunzip PlamoBuild.Thunar-1.4.0.gz

次に、downloadを指定してこのビルドスクリプトを実行します。後述しますが、ビルドスクリプトにはソースコードの入手先が記載されているので、指定されたURLからソースコードをダウンロードし、自動的に展開します。

$ ./PlamoBuild.Thunar-1.4.0 download
--2012-09-26 15:03:38--  http://archive.xfce.org/src/xfce/thunar/1.4/Thunar-1.4.0.tar.bz2
archive.xfce.org (archive.xfce.org) をDNSに問いあわせています... 138.48.2.107
archive.xfce.org (archive.xfce.org)|138.48.2.107|:80 に接続しています... 接続しました。
HTTP による接続要求を送信しました、応答を待っています... 302 Found
場所: http://mirror.yongbok.net/X11/xfce-mirror/src/xfce/thunar/1.4/Thunar-1.4.0.tar.bz2
...
100%[======================================>] 1,915,160   25.4K/s 時間 73s     

2012-09-26 15:04:53 (25.5 KB/s) - `Thunar-1.4.0.tar.bz2' へ保存完了 [1915160/1915160]

Thunar-1.4.0/
Thunar-1.4.0/plugins/
Thunar-1.4.0/plugins/thunar-sendto-email/
Thunar-1.4.0/plugins/thunar-sendto-email/thunar-sendto-email.desktop.in.in
...
Thunar-1.4.0/acinclude.m4
Thunar-1.4.0/README
$ ls
PlamoBuild.Thunar-1.4.0*  Thunar-1.4.0/  Thunar-1.4.0.tar.bz2

次にconfigを指定してビルドスクリプトを実行し、コンパイルするための準備作業を行います。ソースコードにパッチをあてる場合、この段階でパッチファイルが適用されるので、ビルドスクリプトと同じディレクトリにパッチファイルを用意しておく必要があります。Thunar-1.4.0の場合は、日本語等の非ラテン語のファイル名が正しい順番に表示されない問題を修正するパッチが公開されており、このパッチファイルもビルドスクリプトと同じ/usr/share/doc/Thunar-1.4.0/ディレクトリに保存されているので、ソースコードと同じディレクトリに用意しておきます。

$ cp /usr/share/doc/Thunar-1.4.0/Thunar-1.4.0-filename-order.patch.gz .
$ gunzip Thunar-1.4.0-filename-order.patch.gz

なお、パッチファイルの有無についてもビルドスクリプトに記載されており、詳細については後述します。

ビルドスクリプトの引数にconfigを指定して実行すると、64ビット版の場合はbuild/、32ビット版の場合はbuild32/というディレクトリを作成し、ダウンロードしてきたソースコードをコピーして、パッチファイルを適用した上でconfigureを実行します。

$ ./PlamoBuild.Thunar-1.4.0 config
patching file thunar/thunar-file.c
patching file thunar/thunar-file.h
patching file thunar/thunar-file.c
checking build system type... x86_64-unknown-linux-gnu
checking host system type... x86_64-unknown-linux-gnu
...
* Trash Panel Applet:                 yes
* User Customizable Actions:          yes
* Wallpaper support:                  yes
$

次にbuildを指定して実際のコンパイル作業を行います。

$ ./PlamoBuild.Thunar-1.4.0 build
make  all-recursive
make[1]: ディレクトリ `/mnt2/Srcs/T/Thunar/build' に入ります
Making all in icons
...
ITMRG  Thunar-folder-handler.desktop
rm Thunar-folder-handler.desktop.in Thunar.desktop.in Thunar-bulk-rename.desktop.in
make[2]: ディレクトリ `/mnt2/Srcs/T/Thunar/build' から出ます
make[1]: ディレクトリ `/mnt2/Srcs/T/Thunar/build' から出ます
$

最後にpackageを指定して、作成したバイナリファイルをパッケージ化します。packageを指定すると、まず「root権限でパッケージを作成するかどうか」を問われます。実際にインストールするパッケージを作る際は、インストールするファイルのuidやパーミッションを正しく設定するためにroot権限が必要になりますが、試しに作成してみる場合は一般ユーザのままでも構いません。

$ ./PlamoBuild.Thunar-1.4.0 package
Do you want to package as root? [y/N] 
Making install in icons
make[1]: ディレクトリ `/mnt2/Srcs/T/Thunar/build/icons' に入ります
Making install in 16x16
...
pruning symlink in /mnt2/Srcs/T/Thunar/work/usr/share/man/mann
basename:Thunar
version:1.4.0
arch:x86_64
build:P4
ext:txz

以上の操作でThunar-1.4.0のx86_64環境用パッケージが作成できました。

$ ls -l *txz
-rw-r--r-- 1 kojima users 955,932  9月 27日  08:01 Thunar-1.4.0-x86_64-P4.txz

作成したパッケージは、インストールすべきファイルやディレクトリをtar形式に固めてxzで圧縮しているだけなので、tarコマンドだけで内容一覧が表示できます。

$ tar tvf Thunar-1.4.0-x86_64-P4.txz
drwxr-xr-x kojima/users      0 2012-09-27 09:00:00 usr/
drwxr-xr-x kojima/users      0 2012-09-27 09:00:00 usr/share/
drwxr-xr-x kojima/users      0 2012-09-27 09:00:00 usr/share/icons/
...
drwxr-xr-x kojima/users      0 2012-09-27 08:01:11 install/
-rw-r--r-- kojima/users    285 2012-09-27 09:00:00 install/doinst.sh

PlamoBuildスクリプトは、引数を指定せずに起動すればconfig, build, packageの順に実行するので、ソースコードやパッチファイルなどをあらかじめ用意しておけば、ほぼ自動的にパッケージが作成できます。このビルドスクリプトのおかげで、最初に述べたようなパッケージの大量生産が可能だったわけです。

PlamoBuildスクリプトの内側

次に、このビルドスクリプトの内部をもう少し詳しく紹介しましょう。PlamoBuildスクリプトは350行ほどの規模のシェルスクリプトですが、多くの部分は汎用的な処理で、パッケージごとに調整が必要な部分はごくわずかです。

以下では、先に紹介したPlamoBuild.Thunar-1.4.0を用いて、パッケージごとに調整が必要な部分について簡単に紹介してみます。

スクリプトのヘッダ

ビルドスクリプトの先頭の15行ほどがパッケージに関する情報の定義部分です。GNU autotoolsを採用し、configureを利用して必要な設定を行うソフトウェアの場合、この部分をパッケージごとに調整するだけでビルドスクリプトを作成することができます。

 1  #!/bin/sh
 2  ##############################################################
 3  url='http://archive.xfce.org/src/xfce/thunar/1.4/Thunar-1.4.0.tar.bz2'
 4  pkgbase=Thunar
 5  vers=1.4.0
 6  arch=x86_64
 7  #arch=i586
 8  build=P4
 9  src=Thunar-1.4.0
10  OPT_CONFIG="--docdir=/usr/share/doc/${src} --disable-static"
11  DOCS='AUTHORS COPYING COPYING.LIB ChangeLog HACKING INSTALL NEWS README THANKS TODO'
12  patchfiles='Thunar-1.4.0-filename-order.patch'
13  compress=txz
14  ##############################################################
15 

3行目の"url="行がソースコードの入手先です。ビルドスクリプトではwgetを用いてソースコードをダウンロードするので、wgetが理解できる形でURLを指定しておく必要があります。

4行目から8行目がパッケージ名に関する情報で、この例では"Thunar"パッケージの、バージョン"1.4.0"、"x86_64"用で、ビルド番号は"P4"であることを示します。スクリプトが作成するパッケージ名は、13行目に指定している拡張子を付けて、$pkgbase-$vers-$arch-$build.$txzの形(今回の例では Thunar-1.4.0-x86_64-P4.txz)になります。

"arch="はCPUの種類の指定で"x86_64"か"i586"になります。指定によってconfigureやmake時のオプションが調整され、バイナリファイルが32ビット用、64ビット用にコンパイルされます。上記の例では6行目をコメントアウトして、7行目のコメントを外すと、同じスクリプトから32ビット用のバイナリファイルが生成できます。ただし、64ビット環境で32ビット用のバイナリを生成する、といったクロスコンパイルには対応していないので、それぞれの環境の元でビルドする必要があります。

"build="の指定は、バージョンは同じでも設定オプションを調整したりパッチを適用するなどして修正し、パッケージを再作成した際に区別するためのビルド番号です。

9行目の"src="はソースコードが存在するディレクトリ名を指定します。ビルドスクリプトはこのディレクトリ以下のファイルをビルド用の作業ディレクトリにコピーして、コンパイル作業を行います。

10行目の"OPT_CONFIG="は、configureスクリプトに渡すオプションです。後述するように、--prefixや--sysconfdirなどの標準的なオプションはあらかじめ指定されているので、そのパッケージ独自のオプションなどを指定する際に利用します。

11行目はバイナリファイルと共にインストールするドキュメント類の指定です。ここで指定したREADMEやNEWS、COPYINGなどのファイルが、バイナリファイルと共に/usr/share/doc/以下のディレクトリに配置されるようにパッケージに組み込まれます。

12行目は適用するパッチファイルの指定で、パッチファイルが複数の場合は空白で区切って並べておくと順に適用します。

13行目は圧縮形式の指定で、gzip形式のtgzとxz形式のtxzを指定可能です。圧縮にはずいぶん時間がかかるものの、圧縮率はかなり高いので、xzを用いたtxzが最近の主流です。

configの処理

configを指定した際の処理が195行目から225行目の部分です。

195  if [ $opt_config -eq 1 ] ; then
196    for i in `seq 0 $((${#B[@]} - 1))` ; do
197     if [ -d ${B[$i]} ] ; then rm -rf ${B[$i]} ; fi ; cp -a ${S[$i]} ${B[$i]}
198    done
199  ######################################################################
200  # * ./configure を行う前に適用したい設定やパッチなどがある場合はここに
201  #   記述します。
202  ######################################################################
203    for i in `seq 0 $((${#B[@]} - 1))` ; do
204      cd ${B[$i]}
205      for patch in $patchfiles ; do
206         patch -p1 207     done
208  
209      # if [ -f autogen.sh ] ; then
210      #   sh ./autogen.sh
211      # fi
212  
213      if [ -x configure ] ; then
214         export PKG_CONFIG_PATH=/usr/${libdir}/pkgconfig:/usr/share/pkgconfig:/opt/kde/${libdir}/pkgconfig
215         export LDFLAGS='-Wl,--as-needed' 
216         export CC="gcc -isystem /usr/include $target" 
217         export CXX="g++ -isystem /usr/include $target "
218         ./configure --prefix=/usr --libdir=/usr/${libdir} --sysconfdir=/etc --localstatedir=/var --mandir='${prefix}'/share/man ${OPT_CONFIG[$i]}
219     fi
220     if [ $? != 0 ]; then
221         echo "configure error. $0 script stop"
222         exit 255
223     fi
224    done
225  fi

この部分では、まずコンパイル作業用のディレクトリ(64ビット用のビルドではbuild、32ビット用ではbuild32)を用意して、9行目で指定したソースコードのあるディレクトリ($S)からcp -a でソースコードをコピーしています。

その後、204行目でコンパイル作業用のディレクトリに移動して、12行目に指定したパッチファイルを順に適用し(205~207行目)ソースコードの中にconfigureスクリプトが用意されていれば、PKG_CONFIG_PATHやLDFLAGS等の環境変数を設定した上でconfigureスクリプトを実行します(218行目⁠⁠。この際、--prefix、--libdir、--sysconfdir、--localstatedir、--mandirの指定で、ビルドしたファイルや設定ファイル、manページ等の配置をPlamo Linuxの標準的な位置に指定しています。なお、${libdir}はアーキテクチャに合わせて32ビット版ではlib、64ビット版ではlib64になります。

215行目のLDFLAGSで指定している'-Wl,--as-needed'は、オブジェクトファイルのリンク時に使用されるオプションで、実際に参照しているシンボルを持つライブラリのみをリンクせよという指示です。

216行目と217行目はgccやg++に与えるオプションの指定で、$targetは32ビット版ならば-m32、64ビット版ならば-m64に設定されます。220行目から223行目でconfigureの結果を調べ、0以外ならば異常終了したと判断して終了します。

ビルドとパッケージ化

configureが終われば次はコンパイル作業ですが、これはmakeを実行すればいいだけなのでごくシンプルです。ビルドスクリプトも9行ほどです。

226  if [ $opt_build -eq 1 ] ; then
227   for i in `seq 0 $((${#B[@]} - 1))` ; do
228      cd ${B[$i]}
229      if [ -f Makefile ] ; then
230        export LDFLAGS='-Wl,--as-needed'
231        make -j3
232      fi
233    done
234  fi

231行目のmake -j3は、コンパイル作業を3つまで同時に進めよという指示です。最近のCPUはデュアルコアやクアッドコアが一般的なので、CPUの数に合わせて作業を並列化することで処理を高速化することができます。ただし、ソースコードの作りによっては、並列化によりビルドの順番が狂ってエラーになることもあります。

パッケージ化の作業はやや複雑ですが、基本的には

250      if [ -f Makefile ] ; then
251        export LDFLAGS='-Wl,--as-needed'
252        make install DESTDIR=$P
253      fi

という形でインストール先のディレクトリをDESTDIRオプションで指定してmake installを実行し、Makefileが想定しているファイル群をDESTDIR以下にインストールした上で、

303    for i in `seq 0 $((${#DOCS[@]} - 1))` ; do
304      for j in ${DOCS[$i]} ; do
305        for k in ${S[$i]}/$j ; do
306          install2 $k $docdir/${src[$i]}/${k#${S[$i]}/}
307          touch -r $k $docdir/${src[$i]}/${k#${S[$i]}/}
308          gzip_one $docdir/${src[$i]}/${k#${S[$i]}/}
309        done
310      done
311      if [ $i -eq 0 ] ; then
312        install $myname $docdir/$src
313        touch -t `date '+%m%d0900'` $docdir/$src/$myname
314        gzip_one $docdir/$src/$myname
315      else
316        ln $docdir/$src/$myname.gz $docdir/${src[$i]}
317     fi
318      ( cd $docdir ; find ${src[$i]} -type d -exec touch -r $W/{} {} \; )
319    done
320  
321    for patch in $patchfiles ; do
322        cp $W/$patch $docdir/$src/$patch
323        gzip_one $docdir/$src/$patch
324    done
325 

11行目の$DOCSや12行目の$patchfilesで指定したファイルを$P/usr/share/docs/"パッケージ名-バージョン番号" ディレクトリ($docdir/$src)にコピーした上で、

351    cd $P
352    /sbin/makepkg ../$pkg.$compress <<EOF
353  y
354  1
355  EOF
356  
357  fi

パッケージ作成用ディレクトリに移動して、/sbin/makepkgでそのディレクトリ以下のファイルを13行目に指定した圧縮形式で圧縮します。

352行目で使っている/sbin/makepkgはPlamo Linux独自のコマンドですが、これも独立したシェルスクリプトなので、このスクリプトが入っているhdsetupパッケージから取り出して適当なディレクトリに置いてやれば、Plamo Linux以外の環境でもtgz/txz形式のパッケージが作成できるはずです。独自のパッケージは作ってみたいけどrpmの仕組みやspecファイルを勉強するのは大変、という人は、ぜひPlamoBuildスクリプトを試してみてください。


今回紹介したビルドスクリプトはconfigureとmakeだけでビルドできるもっとも簡単なタイプでしたが、実際にパッケージ作りをやっていると、状況に応じてさまざまな工夫を加える必要もよくあります。次回はそのような細工が必要だったビルドスクリプトを取りあげてみます。

おすすめ記事

記事・ニュース一覧