本連載では今回が2020年最初の回なので、ずいぶん遅ればせになるものの、皆さま、明けましておめでとうございます。筆者の怠惰と遅筆の故、不定期になりがちなこの連載ですが、今年もまったりとお付き合いいただければ幸いです。
さて、現在取りあげている話題は、最初の回で紹介したように、去年の夏ごろにビルドしたWINEの環境構築時のトラブルネタで、夏休みの宿題を冬休みを終えてから提出しているような間の悪さはあるものの(苦笑)、とりあえず最後まで進めてしまう予定です。
なお、記事中に出てくる作業ログは、記憶や作ったパッケージの記録を元に改めて再現しているため、日付などは執筆当時になっていることをご了承ください。
8月XX日:Plamo用Multilib環境の構築
一通りCLFSの構築は経験したので、いよいよ本来の目的であるPlamo LinuxのMultilib化の作業にかかる。CLFSの場合、一時システムの構築にのみ既存のLinux環境を利用し、以後はフルスクラッチで必要なコマンドを全てソースコードからビルドしていくのに対し、Plamo Linuxでは既存の64ビット用のバイナリはそのまま使う予定なので、多少は手順が省けるだろう。
CLFSの手順を改めて確認すると、32ビット版のglibcと32/64ビット両対応のGCCが用意できれば、以後の作業はPlamo Linuxの環境でも実行できそうなので、まずはCLFS環境で32ビット版のglibcと32/64ビット両対応のGCCをパッケージ化することにした。
Plamo Linuxのパッケージ作成ツールはCLFS環境でもそのまま動作するものの、ライブラリの配置がCLFSとは異なっているので、CLFSのオプション指定をそのままでは使えない。
glibcのディレクトリ指定オプションをあれこれ試行錯誤したところ、/usr/libと/usr/lib32の切り替えは--libdirと--libexecdirで、/libと/lib32の切り替えはlibc_cv_slibdirという変数で設定できることがわかった。また、バイナリ形式は-m32と-m64というオプションで切り替えられるので、起動するCコンパイラを指定する環境変数CCを"gcc -m32"、C++を指定するCXXを"g++ -m32"と指定すればいいようだ。加えてglibcでは、動作する環境を指定する"--host"オプションにi686-pc-linux-gnuのようなx86を示す識別子を指定する必要がある。これらの設定をビルドスクリプトに組み込むとこんな感じになった。
一方、GCCの場合、32/64ビットのライブラリの位置やビルドしたバイナリに埋め込むダイナミック・リンカー(32ビットではld-linux.so.2、64ビットではld-linux-x86-64.so.2)の位置はソースコード中に埋め込まれているためパッチファイル等での修正が必要となる。煩雑になるので詳細は省くものの、ソースコード中のgcc/config/i386/以下、linux.h、linux64.h、t-linux64の3つのファイルが要修正だった。
GCCのMultilib化は簡単で、configure時に"--disable-multilib"オプションを指定しなければ、glibcの32ビット版が存在する環境では自動的に32/64ビット両対応になるようビルドされる。
とりあえずこれらのオプションを指定して、CLFS上でglibcの32ビット版とGCCのmultilib版をビルド、パッケージ化し、できたパッケージをPlamo Linux上に持ち込んでインストールしてやれば、何とかPlamo Linux上でも32ビット版のバイナリが作成できるようになった。
8月XY日:Plamo用32ビット版パッケージの作成
CLFS上で作ったMultilib対応版GCCは、そのままPlamo Linux上でも動いたものの、念のため、Plamo上で再度binutilsやglibc、GCCを作り直して正式な開発環境とした。
テストとして、適当な64ビット版のビルドスクリプトに
の3行を追加して試してみると、思ったよりも簡単に32ビット版をビルドできる。
パッケージをあれこれビルドしながら試してみると、32ビット版に/usr/bin/以下や/etc/以下のファイルがあると64ビット版とダブってしまうことに気がついた。このあたり、CLFSでは32ビット版をインストールしてから64ビット版をインストールすることで暗黙のうちに上書きしてしまうものの、パッケージとして固める場合はあらかじめ削除しておく必要があるようだ。モノによっては"multiarch_wrapper"的な処理が必要となるものの、それらは個別対応することにして、"/lib32"や"/usr/lib32"以外のファイルやディレクトリは基本的に削除することにした。
さて、これからPlamo用に32ビット版のパッケージを作っていくものの、パッケージには一意に区別できる名前が必要になる。当初は「32ビット版だから、後ろに"_32"とでも付ければいいか」と、"gmp_32"とか"mpfr_32"みたいな名前を付けていたものの、バージョン番号と混同しやすい上に、64ビット版と区別が付きにくい。
そこでArch Linuxのスタイルに習って、32ビット版は"lib32_"を接頭辞として、アーキテクチャ名は"i686"、ビルド番号は"M"で表わし、"lib32_gmp-6.1.2-i686-M1.txz"、"lib32_mpfr-4.0.2-i686-M1.txz"といったパッケージ名にすることにした。現実問題、これらのパッケージには32ビット版のライブラリしか入っていないので、その意味でも妥当なネーミングだろう。
これらの設定をビルドスクリプトに反映してみると、64ビット版からの変更は思ったよりも小規模に収まった。たとえば、GCCをビルドする際に必要となるGNU MPC(任意精度演算ライブラリ)の場合、64ビット版の先頭部分はこのようになる。
一方、32ビット版では、
となって、パッケージ名に関する変更(3、8、9行目)以外はCC、CXX、libdirという変数を追加(18 - 20行目)する程度で32ビット版のビルドが可能になった。
また、不要なファイルを削除する処理も、"make install"後に不要なディレクトリを削除する処理(88行目)を追加すればよさそうだ。
個別調整が必要な場合もあるものの、たいていのソフトウェアはこれらの修正程度で32ビット版が作成できそうなので、CLFSに記載されている順番に従ってパッケージを作ってゆくことにした。
8月XZ日:CLFSのパッケージ化完成、しかし…
一度やったことがある上、32ビット版のみを作ればいいのでCLFSに記載されているソフトウェアのパッケージ化は順調に進み、数日程度で必要なパッケージは揃った。一部、32ビット版と64ビット版の双方が必要なコマンドがあり、CLFSに習ってmultiarch_wrapperを使うことにしたものの、既存の64ビット版のコマンドを改名するあたりの処理はやや強引なので、もう少し考えた方がいいかも知れない。
さて、これでmultilib化も完成したから、次は当初の目的だったWINEをビルドするか… と考えた時、大変なことに気がついてしまった。
というのも、WINEはGUIベースのOSであるWindowsのエミュレータであり、動作するためにはグラフィック回りのフル機能が必要だから、32ビット版のライブラリも、今までビルドしてきたCLFS程度ではなく、最低でもX Window Systemのライブラリ一式まで必要になる、ということだ。
加えて、TrueTypeフォントを使うにはFreeTypeやfontconfigが必要だし、それを画面に描画するにはpangoやgtk一式が必要となる。各種画像を表示するにはlibjpegやlibpngが、音声を扱うにはpulseaudioやgstreamerが必要、そのように考えていくと、WINEを動かすためには、32ビット版のPlamo Linuxを作り直す規模の作業が必要になりそうだ。
これは「夏休みの自由研究」には大きすぎる課題だったなぁ、と後悔しつつも、せっかくmultilib環境を作ったのだから「毒を食らわば皿まで」とばかりに、もう少し32ビット版のパッケージを作ってみることにした。
このあたりまで書いてきて、「何か既視感があるなぁ」と感じて調べてみたら、およそ10年前、「64ビット化への遠い道程」というタイトルで、32ビット環境で64ビットなバイナリを作る一連の記事を書いていました(苦笑)。
この10年の間に、32ビット環境から64ビット環境へ移行し、さらにその上で再度32ビット環境を作り直しているのかぁ…、と感慨に耽っているうち、10年前に書いた64ビット化シリーズの最初の記事も「第16回」だったことに気づき、あたかも果ての無い螺旋状の階段に囚われているかのような感覚に襲われました。