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

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

この記事を読むのに必要な時間:およそ 7 分

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を指定しておく必要があります。

最近ではgitやcvs,svnといったソースコード管理システムを用いてソースコードを入手するソフトウェアプロジェクトも増えていますが,それらには手動で対応する必要があります。

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="はソースコードが存在するディレクトリ名を指定します。ビルドスクリプトはこのディレクトリ以下のファイルをビルド用の作業ディレクトリにコピーして,コンパイル作業を行います。

cmakeを使っている場合など一部例外もありますが,それらは別途解説します。

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 < $W/$patch
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 でソースコードをコピーしています。

複数のソースコードを跨ってビルドするパッケージのために,スクリプト中では$Bをリストのように(${B[$i]})使っていますが,最近ではそういうパッケージはほとんど無いので,$Bも$Sも1つのディレクトリ(buildかbuild32とソースコードのあるディレクトリ)と考えて構いません。

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

著者プロフィール

こじまみつひろ

Plamo Linuxとりまとめ役。もともとは人類学的にハッカー文化を研究しようとしていたものの,いつの間にかミイラ取りがミイラになってOSSの世界にどっぷりと漬かってしまいました。最近は田舎に隠棲して半農半自営な生活をしながらソフトウェアと戯れています。

URLhttp://www.linet.gr.jp/~kojima/Plamo/index.html