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

第6回ビルド、ビルド、ビルド! ─あるいは賽の河原の小石積み[その1]

前回までに、Plamo Linuxで使っているビルドスクリプトや、ビルドスクリプトを作るためのメタビルドスクリプトについて紹介しました。

これらのスクリプトを使えば大量のパッケージを効率よく作ることができます。しかし、実際のパッケージビルドの際には予想外のトラブルが発生することも多々あります。そのような例として、今回と次回に渡ってX Window Systemの最新版であるX11R7.5をビルドした時の話を紹介しましょう。

X11R7.5について

X11R7.5はX Window Systemの最新リリース版で、11がXのプロトコルバージョン、7.5がリリースバージョンを示します。

X Window Systemは、もともとマサチューセッツ工科大学(MIT)がキャンパス中のコンピュータをネットワークで結んで、どこからでも自由にコンピュータ環境を利用できることを目指したアテナ・プロジェクトのウィンドウ環境として開発されたウィンドウシステムです。

そのような由来を持つため、当初からネットワーク透過性(ネットワーク上の別のマシンで起動したコマンドを手元に表示できる)と特定の機種に依存しない移植性の高さ(当時のMITのキャンパスにはさまざまなメーカのコンピュータがあった)を念頭に置いて開発されました。

また、自由な利用を許可するMIT Licenseで ソースコードを公開したこともあり、80年代後半のワークステーションブームの波に乗って、XはみるみるうちにUNIX系OSのウィンドウシステムとして事実上の標準の地位を獲得しました。

その後、アテナ・プロジェクトが完成し、MITが開発から身を引くことで、X Window Systemの開発主体はさまざまに変わっていきました。また、元々のX Window Systemはワークステーション用に開発されていましたが、広く普及してきたPC UNIX用にXの開発を続けようというXFree86プロジェクトが立ちあがったりと、さまざまな紆余曲折を経て、現在ではX.Org Foundationが開発主体となり、freedesktop.orgの元でオープンソースソフトウェアとしての開発が進められています。

上述のように、X Window Systemはネットワーク透過性を重視した設計になっており、画面描画等の機能は全てプロトコルとして定義されています。X11とはそのプロトコルの基本部分がバージョン11であることを示し、このプロトコルは1987年に完成して、X11という名称はその当時から変っていません。その後、このプロトコルに従ったサーバやクライアントの開発が進むと、それらはまとめてR2(X11R2⁠⁠、R3(X11R3)として公開されていきました。

X11R7.5はX11プロトコルを採用したメジャーバージョン7マイナーバージョン5を意味します。なお、Xプロトコルの基本部分は1987年に完成したと述べましたが、動画処理や解像度の動的変更といった新しい機能は拡張プロトコルとして定義され、新機能の追加は現在も続いています。

元々のXのソースコードは、MITを中心とした開発チームが全てを管理していたため、画面描画を担当するXサーバから、xeyeやxcalcといったクライアント、各種フォントやアイコンデータ、kinput2等のインプットメソッドまでが1つのディレクトリ以下にまとめられ、"make World" 一発でビルドできるようになっていました(一枚岩的設計⁠⁠。

しかし、開発者が世界中に分散してバザールモデルの開発スタイルへ移行するに伴い、分散開発が困難な一枚岩的設計から、アプリケーションごとにソースコードを細かく分割していくモジュール的設計に全体構成が変更されました。モジュール的設計への全面的な移行はX11R7の公開時に行われ、当初はチグハグな部分も散見されてかなり戸惑いましたが、5度目のリリースとなる最近ではようやく落ちついてきたようです。

ビルドの準備

X Window Systemのソースコードはftp.x.orgやそのミラーサイト(今回はftp.kddlabs.co.jpを利用しました)で公開されています。

前節で紹介したように、現在のX Window Systemのソースコードは細かく分割されており、X11R7.5として公開されたソースコードは395個に達しています。これらを一々手動でダウンロードしようとすると結構手間なので、今回は以下のような処理で一括ダウンロードしてみました。

$ mkdir X11R7.5 ; cd X11R7.5
$  for i in app data doc driver font lib proto util xserver ; do
 >   mkdir $i
 >   pushd $i
 >       wget --retr-symlink ftp://ftp.kddlabs.co.jp/pub/X/ftp.x.org/pub/X11R7.5/src/$i/'*.tar.bz2'
 >   popd
 > done

最近のXのソースコードは、FTPサイトの/pub/individual/の下にapp/やdata/、doc/といった種類ごとのディレクトリに分割して配置され、各ディレクトリには、その分類に属するソフトウェアのソースコードが過去に公開されたバージョンも含めて置かれています。"X11R7.5"としてのリリースは、/pub/X11R7.5/src/ 以下に app/ や data/, doc/ といった同様のディレクトリを配置して、それぞれのソースコードのうち、このリリースに含まれるバージョンへのシンボリックリンクをこれらディレクトリに配置する、といった構造で公開されています。

そのため、上記のスクリプトではwgetに--retr-symlinkオプションを指定してリンク先の実体を入手するようにしました。また、ソースコードはgzipで圧縮したものとbzip2で圧縮したものの2種が用意されているので、'*tar.bz2'を指定してbzip2で圧縮したもののみをダウンロードするように指示しています。

X11R7.5/src/everything/以下には、このリリースに含まれる全てのソースコードへのシンボリックリンクが含まれていますが、後述するようにX Window Systemのビルドには順番が重要なので、分類されたディレクトリを利用しています。

これらのソースコードに対して、前回紹介したメタビルドスクリプトを用いてPlamoBuildスクリプトを作っていくわけですが、util/ディレクトリにあるutil-macrosmakedependは、他のソースコードを configure する時に必要なマクロ定義等が含まれているので、まず最初にインストールしておく必要があります。そのため、まずそれらをパッケージ化しインストールしておいた上で、残りのソースコードに対して、まとめてメタビルドスクリプトを適用しました。

$ for i in app data doc driver font lib proto xserver ; do
 > pushd $i
 > for j in *.tar.bz2 ; do
 >     ../make_PlamoBuild.py -t X $j
 > done
 > popd
 > done
~/X11R75/app ~/X11R75
dirname =  bdftopcf-1.0.2
making PlamoBuild.bdftopcf-1.0.2 ...
...

このループもやっていることは簡単で、ダウンロードしてきたソースコードを保存しているそれぞれのディレクトリに移動して、そのディレクトリにあるソースコード全てに対してメタビルドスクリプトを実行しているだけです。

なお、今回用いたメタビルドスクリプトは、URL行も自動的に生成するために、以下のような処理を追加したカスタマイズ版を用いました。このように試しながら修正を簡単に行えるのが、Python等のスクリプト言語の魅力です。

リスト1 make_PlamoBuild.pyの修正部分
    current_dir = os.getcwd()
    dir_name = os.path.basename(current_dir)
    url = 'ftp://ftp.kddlabs.co.jp/pub/X/ftp.x.org/pub/X11R7.5/src/' + dir_name + '/' + filename + '-' + vers + '.tar.bz2'
    header = make_headers(url, filename, vers, READMEs, patches)

メタビルドスクリプトはソースコードの展開処理も行うので、スクリプト実行後のそれぞれのディレクトリには、ソースコードごとのPlamoBuildスクリプトと展開したソースコードのディレクトリができます。

$ ls -l app/
合計 5,079,040
-rwxr-xr-x 1 kojima users   9,626  1月  3日  22:25 PlamoBuild.bdftopcf-1.0.2*
-rwxr-xr-x 1 kojima users   9,623  1月  3日  22:25 PlamoBuild.iceauth-1.0.3*
 ....
drwxr-xr-x 2 kojima users   4,096  1月  3日  21:56 bdftopcf-1.0.2/
-rw-r--r-- 1 kojima users  95,983 10月 27日  10:15 bdftopcf-1.0.2.tar.bz2
drwxr-xr-x 2 kojima users   4,096  1月  3日  22:22 iceauth-1.0.3/
-rw-r--r-- 1 kojima users 106,197 10月 27日  10:15 iceauth-1.0.3.tar.bz2
 ...

ビルドスクリプトの先頭のurl行も正しく設定できているようです。

リスト2 url行が設定されたビルドスクリプトの例
#!/bin/sh
##############################################################
url=ftp://ftp.kddlabs.co.jp/pub/X/ftp.x.org/pub/X11R7.5/src/app/bdftopcf-1.0.2.tar.bz2
pkgbase=bdftopcf
vers=1.0.2
arch=i586
build=P1
src=bdftopcf-1.0.2
OPT_CONFIG='--build=i586-pc-linux --disable-static'
DOCS='AUTHORS COPYING ChangeLog INSTALL NEWS README'
...

これでX11R7.5をビルドするのに必要な準備は整いました。

ビルド、ビルド、ビルド(その1)

あとは生成したPlamoBuildスクリプトを動かしてビルドしていけばいいのですが、X Window Systemの場合、上述したように、まずプロトコルの定義があって、そのプロトコルを処理するためのライブラリがあり、アプリケーションやサーバはそれらライブラリの上に構築されているといった依存関係があるので、ビルドする順番には注意が必要です。

過去の経験からすると、最初に proto/ ディレクトリのソースコードをビルド、インストールし、次にlib/以下、その次にapp/とxserver/、xserverをビルドしてからdriver/をビルドし、data/、doc/、font/といった部分は最後に回すのがよさそうです。

本来は、それぞれのビルドスクリプトごとにconfigureで指定可能なオプション等を調整した方がていねいなのですが、何しろコンパイルすべきソースが大量なので、今回は以下のようなスクリプト(build_pkgs.sh)を使って、各ディレクトリごとにデフォルトの設定のままビルドスクリプトを流してみることにします。

リスト3 build_pkgs.sh
#!/bin/sh
for i in PlamoBuild* ; do
    echo "executing $i"
    ./$i

   pkgbase=`grep "^pkgbase=" $i  | cut -f2 -d"="`
   vers=`grep "^vers=" $i | cut -f2 -d"="`
   arch=`grep "^arch=" $i | cut -f2 -d"="`
   build=`grep "^build=" $i | cut -f2 -d"="`
   pkgname=$pkgbase'-'$vers'-'$arch'-'$build'.tgz'

   echo "updating $pkgname"
   updatepkg -f $pkgname
done

このスクリプトの処理も見ればわかるレベルでしょう。pkgnameを生成する部分がやや煩雑ですが、ビルドスクリプトの先頭部分から必要なデータを取り出して作成されるパッケージ名を作り、そのパッケージ名を使ってupdatepkgコマンドでインストールするようにしてみました。

まずはproto/から

それではproto/以下の26個のソースコードからビルド、インストールしていきます。パッケージの作成やインストールにはroot権限が必要になるので、sudoコマンド経由でbuild_pkgs.shを流します。後で確認できるように、ログファイルも記録しておきましょう。

% cd proto
% sudo ../build_pkgs.sh 2>&1 | tee -a build.log
パスワード: *****
executing PlamoBuild.applewmproto-1.4.1
configure: WARNING: unrecognized options: --disable-static
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
....
pruning symlink in /home/kojima/X11R75/proto/work/usr/share/man/man9
pruning symlink in /home/kojima/X11R75/proto/work/usr/share/man/mann
Making ../applewmproto-1.4.1-i586-P1.tgz...

updating applewmproto-1.4.1-i586-P1.tgz

Removing package applewmproto...
Removing files:
  --> Deleting usr/X11R7/include/X11/extensions/applewmconst.h
  --> Deleting usr/X11R7/include/X11/extensions/applewmproto.h
 ....
applewmproto-1.4.1-i586-P1 のインストール中
PACKAGE DESCRIPTION:

executing PlamoBuild.bigreqsproto-1.1.0
configure: WARNING: unrecognized options: --disable-static
....

ログファイルを調べるとconfigure時にWARNINGメッセージが出ているようですが、パッケージそのものの作成には特に問題はなく、proto/ 以下のビルドとインストールは終了していました。

次はlib/に移って、同様に35個のパッケージのビルドとインストールを進めていきます。

厳密に言うと、ライブラリの間にもlibXtやlibXmuがより基盤部になるので先にビルドする必要があり、その基盤の上でlibXawがビルドできる、という順番がありますが、今回はあらかじめX11R7.4をインストールしたPlamo-4.71環境上でビルドしたので、ライブラリのビルド順はあまり気にせず、ビルド処理を二度流せばいいか、的な感覚でビルドしています。

% cd ../lib
% sudo ../build_pkgs.sh 2>&1 | tee -a build.log
パスワード: *****
executing PlamoBuild.libAppleWM-1.4.0
checking for a BSD-compatible install... /usr/bin/install -c
 ...

ビルドエラーへの対応

数時間かけて一度目のビルドとインストールは終了しましたが、ログファイルを調べると、以下の3つの場所でエラーが出ているようです。

リスト4 libAppleWM-1.4.0のエラー
Making all in src
make[2]: ディレクトリ `/home/kojima/X11R75/lib/build/src' に入ります
  CC     libAppleWM_la-applewm.lo
applewm.c:37:36: error: X11/extensions/applewm.h: そのようなファイルやディレクトリはありません
applewm.c:43:34: error: HIServices/Processes.h: そのようなファイルやディレクトリはありません
applewm.c: In function 'wire_to_event':
applewm.c:86: error: 'XAppleWMNotifyEvent' undeclared (first use in this function)
applewm.c:86: error: (Each undeclared identifier is reported only once
リスト5 libXfont-1.4.1のエラー
I/O error : Attempt to load network entity http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd
warning: failed to load external entity "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd"
validity error : Could not load the external subset "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd"
Document /home/kojima/X11R75/lib/build/./doc/fontlib.xml does not validate
make[2]: *** [doc/fontlib.html] エラー 13
make[2]: *** 未完了のジョブを待っています....
リスト6 libXpm-3.5.8のエラー
make[2]: ディレクトリ `/home/kojima/X11R75/lib/build/sxpm' に入ります
  CC     sxpm.o
  GEN    sxpm.1
  GEN    sxpm.po
  CCLD   sxpm
/usr/X11R7/lib/libSM.so: undefined reference to `uuid_generate'
/usr/X11R7/lib/libSM.so: undefined reference to `uuid_unparse_lower'
collect2: ld returned 1 exit status
make[2]: *** [sxpm] エラー 1

エラーメッセージによると、libAppleWM-1.4.0のエラーはapplewm.hというヘッダファイルがないことによるエラーlibXfont-1.4.1のエラーはXMLの定義ファイルを読めないことによるエラーlibXpm-3.5.8のエラーはリンクしようとしたライブラリに参照しているシンボルが存在しないことによるエラーのようです。

applewm.hというヘッダファイルは何に含まれているのだろう?とGoogle等で調べてみると、このlibAppleWMというライブラリはMac OS X環境用のため、Linuxではビルドする必要がないようです。とりあえず、このライブラリ用のソースコードとビルドスクリプトは別の場所に移しておけばいいでしょう。

libXfontののエラーは、configureのオプションを調べると--disable-devel-docsという指定をすればXMLベースのドキュメントの生成を抑制できることがわかったので、ビルドスクリプトにこのオプションを追加してビルドし直しました。

libXpmのエラーは、Plamo-4.71でインストールしているlibuuid のバージョンに関わる問題です。Plamo-4.71ではUUID(Universally Uniq IDentifier:汎用一意識別子)を作るためのライブラリとしてe2fsprogs由来のlibuuid.so.1とOSSP UUID由来のlibuuid.so.16の2種がインストールされており、後者のlibuuid.so.16がデフォルトで使われるようになっていますが、libXpm-3.5.8ではe2fsprogs由来のlibuuid.so.1のみに存在するシンボルを参照しているようです。

このエラーは今までにも何度か経験したことがあって、たいていの場合libuuid.so.16を含むuuidパッケージを削除し、libuuid.so.1を含むe2fsprogsパッケージを再インストールして、libuuid.so.1が使われるようにしてやれば解決したので、今回もそのように対応することにしました。

% sudo removepkg uuid
パスワード:

Removing package uuid...
Removing files:
...
% sudo updatepkg -f e2fsprogs-1.41.6-i586-P1.tgz
Removing package e2fsprogs...
...
e2fsprogs-1.41.6-i586-P1 のインストール中
...

libuuidを入れ変えた上でPlamoBuild.libXpm-3.5.8を再実行してやると、

% ./PlamoBuild.libXpm-3.5.8
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
...
 GEN    sxpm.1
 CCLD   sxpm
libtool: link: cannot find the library `/usr/lib/libuuid.la' or unhandled argument `/usr/lib/libuuid.la'
make[2]: *** [sxpm] エラー 1
make[2]: ディレクトリ `/home/kojima/X11R75/lib/build/sxpm' から出ます

あれれ、今度は/usr/lib/libuuid.la が無いというエラーになってしまいました。

このla という拡張子を持つファイルはGNU libtoolsが参照する仮想ライブラリファイルです。このファイルは GNU libtools を使って共有ライブラリを作る際に作成され、そのライブラリの場所や依存している外部ライブラリなどの情報を記録しています。改めてパッケージを調べてみると、OSSP UUID由来のlibuuidにはlaファイルが付属するものの、e2fsprogs由来のlibuuidにはlaファイルがありません。

共有ライブラリにlaファイルを作るかどうかはソフトウェアの開発者に委ねられているので、e2fsprogsの開発者はlaファイルを作らない、という選択をしたのでしょう。本来、仮想ライブラリであるlaファイルは、共有ライブラリの機能を持たないOS環境でも、機能を持つOS環境と同等の操作をするために取り入れられたものなので、共有ライブラリの利用が前提となっているLinux環境では特に必要ないファイルとも言えます。

libuuid.laが無い状態でビルドしているのにlibuuid.laを参照してしまうということは、今ビルドしているsxpmの範囲ではなく、sxpmが参照しているコンパイル済みのライブラリの中にlibuuid.laを参照しているものが存在しているはずです。sxpmが参照しているライブラリをきちんと調べるにはMakefileを調べる必要がありますが、たぶんX Window System関連のライブラリだろうとあたりを付けて調べてみると、確かにlibuuid.laを参照しているものが散見されます。

% grep libuuid /usr/X11/lib/lib*.la
/usr/X11/lib/libSM.la:dependency_libs=' -L/usr/X11R7/lib /usr/X11R7/lib/libICE.la /usr/lib/libuuid.la'
/usr/X11/lib/libXaw6.la:dependency_libs=' -L/usr/X11R7/lib /usr/X11R7/lib/libXmu.la -L/lib -luuid /usr/X11R7/lib/libXext.la  
   /usr/X11R7/lib/libXt.la /usr/X11R7/lib/libX11.la /usr/X11R7/lib/libxcb.la /usr/X11R7/lib/libXau.la /usr/X11R7/lib/libXdmcp.la -ldl 
  /usr/X11R7/lib/libSM.la /usr/lib/libuuid.la /usr/X11R7/lib/libICE.la'
......

とりあえず解決

これらの参照を解消するためには、libuuid.laがない状態で、これらのライブラリを再ビルドしてやる必要があります。どうせ二度流すつもりだったからいいか、と再度build_pkgs.shスクリプトを流してlib/以下をビルドし直し始めましたが、今度はlibXawが

checking for XAW7... configure: error: Package requirements (xproto x11 xext xextproto xt xmu xpm) were not met:

No package 'xpm' found

Consider adjusting the PKG_CONFIG_PATH environment variable if you
installed software in a non-standard prefix.

とエラーを出してビルドに失敗してしまいました。このエラーメッセージを見ると、libXaw7を作るためにはxpmパッケージがあらかじめインストールされていないといけないようです。

libXpmがlibXawに残っているlibuuid.laの参照のためにビルドできないのに、libXawがlibXpmが無いとビルドできない、というのは依存関係のループだよなぁ…、と首をかしげつつ、libXpmのビルドスクリプトを改めて流してみると、sxpmコマンドはビルドされないように設定されたものの、ライブラリ自体はビルド可能で、libXaw7がconfigure時にチェックしているxpm.pcファイルも生成できました。

sxpmコマンドが不要なら、そもそもuuidパッケージを削除する必要は無かったのかも…と思いつつ、乗りかかった船なので、再度ライブラリをビルドし直していき、libXawやlibXmuからlibuuid.laの参照をなくした上で、libXpmを再々度ビルドすることで、無事sxpmも含めたlibXpmパッケージが完成しました。

xpm.pcのような⁠xxx.pc⁠というファイルは、freedesktop.orgが提唱しているpkgconfigという仕組み用のデータファイルで、 先に紹介したGNU libtoolsが作成する仮想ライブラリファイルと同様、ソフトウェアのバージョンやインストールされた場所、依存する外部ライブラリ等の情報を記録しています。仮想ライブラリファイル(la ファイル)が共有ライブラリの処理に限定されるのに対して、pkgconfigの対象はライブラリ以外の一般コマンドにも拡大されており、最近のソフトウェアの多くはpkgconfigを使って必要なコマンドやライブラリの有無をチェックするようになっています。

ビルドは続くよ…

ここまででX11R7.5のプロトコル部とライブラリ部までは完成したので、次はこれらのライブラリを参照するアプリケーションやXサーバのビルドです。app/ディレクトリ以下に集められている38個のアプリケーションは特に問題なくbuild_pkgs.shスクリプトで全てビルド、インストールできましたが、X Window Systemの中心的な役割を果たすxorg-serverのビルドでは、またトラブルに見舞われることになりました。

ずいぶん長くなってしまったので、それらについては回を改めて紹介することにしましょう。

おすすめ記事

記事・ニュース一覧