続・玩式草子 ―戯れせんとや生まれけん―

第15回Days of WINE and Struggles[2]

前回に引き続き、Plamo Linux Multilib化の日記風記録です。日付は適当なものの、このあたりまではCLFSのドキュメントに沿った作業なので、実質3~4日程度で進みました。

7月YX日:CLFSの一時システム作り

先に紹介したようにCLFSでは、まず/mnt/clfs/cross-tools/以下に64/32ビット両対応のGCCを用意し、そのGCCを用いて/mnt/clfs/tools/以下に最小規模の起動可能なLinux環境一時システムを作る。そして、その一時システムを使って/mnt/clfsをルートパーティションとするLinuxのフルシステムを作りあげる、という手順を取る。

すなわち、/mnt/clfs/以下にはcross-tools/bin/のGCC(クロスツール用GCC)とtools/bin/のGCC(一時システム用GCC⁠⁠、/mnt/clfs/usr/bin/のGCC(フルシステム用GCC)の3種ができるわけだ。最小規模のツールから次第に機能を拡張していって、最終的に完全版を本来の場所に配置するこのあたりの手順は、⁠ブートストラップ」という言葉を地で行っているようで興味深い。

とりあえずクロスツール用GCCまではビルドできたので、次は/mnt/clfs/tools/以下に配置する一時システム用のツール作りとなる。その際は、再度GMPやMPFR、MPC、ISLといったGCC用のサポートライブラリからビルドを始め、一時システム用にbinutilsとGCCを作り直す。その後、bashやcoreutilsといった基本ツールとmakeやpatch、tar、sedといった開発用ツール類をビルドして、/mnt/clfsを起動(あるいはchroot)可能な状態にするようだ。

ちなみに手元では、Plamo Linuxをインストールした仮想環境(VirtualBox)を用意して、ホスト側からリモートログインしてCLFSの作業をしている。こうすれば、CLFSの内容を表示しているブラウザから、必要なコマンドをビルド用ターミナルにコピペできるので、タイプミスも生じなくて便利だ。

図1 コピペでCLFSのコマンド入力
図1 コピペでCLFSのコマンド入力

ソースコードは可能な限り最新版を使おうとしているので、CLFSに記載されているバージョンとは異なる場合が多いものの、バージョンに依存するパッチを当てる場合などを除き、ほぼ問題なくビルド、インストールはできた。

次はこの一時システムを自立可能なLinuxシステムにするための、作業ディレクトリや設定ファイル作りだ。CLFSに紹介されている通りに、/procや/sys、/devといったハードウェア情報を扱うためのディレクトリを作成し、mountのbindオプションでchroot先からも必要な情報が見えるようにしておく。

# mkdir -pv ${CLFS}/{dev,proc,run,sys}
...
# mount -v -o bind /dev ${CLFS}/dev
# mount -vt devpts -o gid=5,mode=620 devpts ${CLFS}/dev/pts
# mount -vt proc proc ${CLFS}/proc
# mount -vt tmpfs tmpfs ${CLFS}/run
# mount -vt sysfs sysfs ${CLFS}/sys

一般ユーザ(clfs)で作成したコマンド類の所有者をrootに変更したり、/etcや/varといった必須ディレクトリの作成、/etc/passwdや/etc/groupなどの設定ファイルの追加といった作業を進め、準備が整った一時システムにchrootすると、300強のコマンドが使えるLinux環境になっている。

# chroot /mnt/clfs /tools/bin/env -i   \
     HOME=/root TERM="${TERM}" PS1='\u:\w\$ ' \
     PATH=/bin:/usr/bin:/sbin:/usr/sbin:/tools/bin \
     /tools/bin/bash --login +h

root:/# ls
bin   cross-tools  etc   lib    media  opt   root  sbin     srv  tmp	  usr
boot  dev          home  lib64  mnt    proc  run   sources  sys  tools  var

root:/# ls /tools/bin
'['	        elfedit        linux64		 pr	        truncate
 addr2line      env	       ln		 printenv       tset
 ar	        expand	       locale		 printf         tsort
 ...
 
root:/# ls /tools/bin | wc -l
318

次は、この一時システムの/tools/bin/以下のコマンドを使って、/usr/bin/以下に正式なシステムを作っていくステップになる。

7月YY日:CLFSのフルシステム構築

CLFSではビルドエラーを発見するためのテストを重視しており、他のソフトウェアをインストールする前にテスト用のツール類をインストールする(9章⁠⁠。その後、基本的なLinuxシステムを構成するためのソフトウェアを32ビット版、64ビット版の順でビルドして、本来の置き場所である/usr/以下にインストールしていく(10章⁠⁠。

まず最初にGlibcを32ビット用、64ビット用にビルドし直し、GCCを構成するためのGMPやMPFRなども再度32/64ビット用にビルド、インストールし直す。GCCは4回目のビルドになる上、GMPなどのライブラリは32/64ビット用に2度づつビルドするため、手順の既視感が甚(はなは)だしい。しかしながら、各ステップごとに適用するパッチの有無が変わっていたり、インストール先等を指定する設定オプションが変っていたりするので、一度使ったソースコードは削除して展開し直し、記載されている手順を確認しつつ設定、ビルド、インストールを進めていく。

ビルド用のコマンドラインは一見同じように見えるものの、GCCに渡すオプションが変っていたり("-m32/-m64"⁠⁠、LDFLAGSに指定するライブラリが"/usr/lib"と"/usr/lib64"で入れ替わっていたり、32ビット用ではconfigure時に--hostオプションが必要だったり、と微妙に異なっている。

ライブラリのインストール先は--libdirオプションで切り替えて共存させているのに、実行ファイルのインストール先は/usr/bin/のままでいいのかな、と思ったものの、このあたりはビルド順が工夫されていて、まず32ビット版をビルド、インストールしてから、64ビット版をビルド、インストールすることで、先に/usr/bin/以下にインストールされた32ビット版の実行ファイルは、同名の64ビット版で上書きされる、という考え方らしい。

通常、実行ファイルは32ビット版でも64ビット版でも動作は変らないので、同名のコマンドを64ビット版で上書きしても構わないものの、リンク時に参照するライブラリの位置を返すconfig-XXX系のツールでは、32/64ビット版双方の実行ファイルが必要なことがある。

そのような場合に対応するために、CLFSではmultiarch_wrapperという独自のコマンドを用意している(CLFS 10.27章⁠⁠。このコマンドは50行弱のCプログラムで、USE_ARCHという環境変数に応じて、呼び出す実行ファイルを切り替える、という機能を持っている。

たとえば、32ビット版のperlを/usr/bin/perl-3264ビット版のperlを/usr/bin/perl-64という名前でインストールし、/usr/bin/perl/usr/bin/multiarch_wrapperにシンボリックリンクしておけば、

  $ USE_ARCH=32 /usr/bin/perl

とすると、/usr/bin/perlという名前で呼び出されたmultiarch_wrapperが、USE_ARCH=32の指定に従って32ビット版(/usr/bin/perl-32)を起動し、USE_ARCH=64とすると64ビット版(/usr/bin/perl-64)を起動する。

実用上、multiarch_wrapperが必要になるのは、pkg-config等の機能に頼らずに32ビット版ライブラリを作成する場合くらいだろうけど、切り替え機能はあれば便利なので、CLFSに従ってインストールしておく。

10章はCLFSの記述通りにビルド、インストールを進めていけばいいものの、ざっと数えたところ、32/64ビットのライブラリを作る必要があるソフトウェアが28種類、64ビット版のみでいいソフトウェアが35種類あるから、28x2 + 35の計91回、ビルド、インストール作業が必要になるようだ。まだまだ先は長い。

7月YZ日:CLFS環境完成とPlamo用ビルドツールの導入

CLFSの記述に従ってソフトウェアのビルド、インストールを進めてきたものの、今ごろになってイヤなことに気がついた。というのも、CLFSでは32ビット版のライブラリを/usr/lib/に収め、64ビット版のライブラリは/usr/lib64/に収めるという設定になっていることだ。

Plamo Linuxでも、32ビット版をメインに開発していた6.xまではこのスタイルで配置していたものの、64ビット版をメインにした7.xでは64ビット版のライブラリを/usr/lib/に収めているので、32ビット版のライブラリは/usr/lib32/に収めるようにしなければならない。

前のステップに戻って作り直した方がいいかな、と考えたものの、今作っているのはCLFS環境であってPlamo Linux用のパッケージではないし、Plamo用には再度クロスコンパイル用GCCパッケージから作り直すことになるので、CLFSの構築はクロスコンパイルの経験値を高めるための修行と割り切って、ビルド、インストールを続けることとした。

CLFS10章の最後の方になってくるとlibpipelinelibestrlibeeなど、あまり記憶にないライブラリも入ってくる。これらPlamo用にビルドしたことのないソフトウェアについては、今後パッケージ化する必要があるかどうかを考えないといけないだろう。

今回はchroot環境のまま運用するつもりなので、rsysloggrubsysvinitといったシステム運用/起動用のツールは不要と判断した。また、11章以降では起動用の各種スクリプトやネットワーク回りの設定等が続くものの、これらもCLFSを本格運用するつもりはないので不要と考え、とりあえず10章を終えたあたりでCLFS環境は完成とした。

さて、CLFS環境は完成したものの、本来の目標はPlamo LinuxのMultilib化なので、次はCLFS上でPlamo用のクロスコンパイルツールを作成することになる。Plamo用のパッケージ作りには多少手間がかかるかな、と心配したものの、やってみると意外と簡単で、パッケージを作成するためのmakepkgコマンドを含むパッケージ管理ツールpkgtoolsとビルドスクリプトの補助機能を提供するパッケージplamobuildをtarコマンドで展開すれば事足りた。このあたりは専用のパッケージツールを必要としないPlamo Linuxのメリットと言えそうだ。

まずは2つのパッケージをchroot環境内から利用できる場所に移しておく。

# cp pkgtools-7.0-x86_64-B3.txz plamobuild-1.4-noarch-B1.txz /mnt/clfs/sources

次に、chrootしたCLFS環境内で、これらのパッケージを"/"以下に展開する。

root@pl72:/mnt/clfs/sources# tar xvf pkgtools-7.0-x86_64-B3.txz -C /
sbin/
sbin/installer/
sbin/installer/busybox
...
root@pl72:/sources# tar xvf plamobuild-1.4-noarch-B1.txz -C /
usr/
usr/share/
usr/share/plamobuild_functions.sh
...

この状態でPlamo-7.x用のPlamoBuildスクリプトを試したら、そのままでパッケージ作成まで実行できた。

# cp PlamoBuild.binutils-2.32 /mnt/clfs/sources
root@pl72:/mnt/clfs/sources# ./PlamoBuild.binutils-2.32        
checking build system type... x86_64-pc-linux-gnu
checking host system type... x86_64-pc-linux-gnu
checking target system type... x86_64-pc-linux-gnu
checking for a BSD-compatible install... /tools/bin/install -c
checking whether ln works... yes
checking whether ln -s works... yes
....
/bin/sh ./libtool  --tag=CC   --mode=compile gcc -DHAVE_CONFIG_H -I. -I/sources/Binutils/binutils-2.32/bfd
   -DBINDIR='"/usr/bin"' -I. -I/sources/Binutils/binutils-2.32/bfd -I/sources/Binutils/binutils-2.32/bfd/../include
   -DHAVE_x86_64_elf64_vec -DHAVE_i386_elf32_vec -DHAVE_iamcu_elf32_vec -DHAVE_x86_64_elf32_vec -DHAVE_i386_pei_vec
   -DHAVE_x86_64_pei_vec -DHAVE_l1om_elf64_vec -DHAVE_k1om_elf64_vec -DHAVE_elf64_le_vec -DHAVE_elf64_be_vec
   -DHAVE_elf32_le_vec -DHAVE_elf32_be_vec -DHAVE_x86_64_pe_vec -DHAVE_x86_64_pe_be_vec -DHAVE_i386_pe_vec
   -DHAVE_plugin_vec   -W -Wall -Wstrict-prototypes -Wmissing-prototypes -Wshadow -Wstack-usage=262144
   -g -O2 -MT pe-x86_64.lo -MD -MP -MF .deps/pe-x86_64.Tpo -c -o pe-x86_64.lo
   /sources/binutils-2.32/bfd/pe-x86_64.c
...
pruning symlink in /sources/Binutils/work/usr/share/man/mann
basename:binutils
version:2.32
arch:x86_64
build:B1
ext:txz

root@pl72:/sources# tar tvf binutils-2.32-x86_64-B1.txz 
drwxr-xr-x root/root         0 2019-12-02 12:29 var/
drwxr-xr-x root/root         0 2019-12-02 12:29 var/local/
drwxr-xr-x root/root         0 2019-12-02 12:29 var/local/la-files/
-rwxr-xr-x root/root       980 2019-12-02 12:29 var/local/la-files/libbfd.la
-rwxr-xr-x root/root      1003 2019-12-02 12:29 var/local/la-files/libopcodes.la
drwxr-xr-x root/root         0 2019-12-02 12:29 usr/
drwxr-xr-x root/root         0 2019-12-02 12:29 usr/lib/
-rw-r--r-- root/root   2322920 2019-12-02 12:29 usr/lib/libopcodes.a
-rw-r--r-- root/root  12217270 2019-12-02 12:29 usr/lib/libbfd.a
...

Plamoの場合、tarとxzさえあれば手作業でもパッケージは作れるものの、使い慣れたPlamoBuildスクリプトが動けば設定情報等も保存できるので心強い。まずは、CLFSの手順をビルドスクリプトに反映してPlamo用のMultilib版GCCを作ることにしよう。


今回はCLFSの記述そのままの作業なので、あまりCLFSの内容は引かずに、筆者の感想を中心にまとめてみました。

CLFSやその元となったLFSは手順やパッチ等がよく考慮されていて、初見では何のためかわからなかった変更箇所が、だいぶ後になって「ああ、ここの処理のためだったのか」と気づくことがよくあります。

そのあたり、もう少し詳しい解説が欲しいな、と思う反面、すでに通読するには大変なサイズになっているので、詳しさと分量のバランスに配慮する編集者の苦労が偲ばれるところです。

おすすめ記事

記事・ニュース一覧