5.2. ツールチェーンの技術的情報

本節ではシステムをビルドする原理や技術的な詳細について説明します。 この節のすべてをすぐに理解する必要はありません。 この先、実際の作業を行っていけば、いろいろな情報が明らかになってくるはずです。 各作業を進めながら、いつでもこの節に戻って読み直してみてください。

第5章の最終目標は一時的なシステム環境を構築することです。 この一時的なシステムはシステム構築のための十分なツール類を有していて、ホストシステムとは切り離されたものです。 この環境へは chroot によって移行します。この環境は第6章において、クリーンでトラブルのない LFS システムの構築を行う土台となるものです。 構築手順の説明においては、初心者の方であっても失敗を最小限にとどめ、同時に最大限の学習材料となるように心がけています。

[注記]

注記

これより先に進む前に、作業するプラットフォームの三つの組 (target triplet)で表される名称を確認してください。 三つの組config.guess スクリプトを実行することで簡単に確認できます。 そのスクリプトは多くのパッケージのソースに含まれています。 Binutils パッケージのソースを伸張 (解凍) し ./config.guess スクリプトを実行してその出力を確認してみてください。 例えば 32 ビット Intel プロセッサーでは i686-pc-linux-gnu のような出力が得られます。 64 ビット システムでは x86_64-pc-linux-gnu のようになります。

利用しているプラットフォームに応じたダイナミックリンカー (dynamic linker) の名前についても確認してください。 ダイナミックローダー (dynamic loader) とも表現されるものです。(Binutils が提供する標準的なリンカー ld とは異なりますので注意してください。) Glibc が提供するこのダイナミックリンカーは、プログラムが必要としている共有ライブラリを見つけ出してロードし、実行のための準備を行った上で実際に実行します。 32 ビットマシンのダイナミックリンカーの名前は ld-linux.so.2 といったものになります (64 ビットシステムでは ld-linux-x86-64.so.2)。 確実にその名前を調べるなら、ホストシステム内のどれでも良いので実行モジュールを選んで readelf -l <実行モジュール名> | grep interpreter と入力します。 出力される結果を確認してください。 あらゆるプラットフォームの情報を知りたいなら Glibc のソースディレクトリのルートにある shlib-versions ファイルに記されています。

第5章におけるビルド手順がどのように機能するのか、その技術的な情報を以下に示します。

Binutils をまず初めにインストールします。 この後の GCC や Glibc の configure スクリプトの実行ではアセンブラーやリンカーに対するさまざまな機能テストが行われるためで、そこではどの機能が利用可能または利用不能であるかが確認されます。 ただ重要なのは Binutils を一番初めにビルドするという点だけではありません。 Gcc や Glibc の configure が正しく処理されなかったとすると、ツールチェーンがわずかながらも不完全な状態で生成されてしまいます。 この状態は、すべてのビルド作業を終えた最後になって、大きな不具合となって現れてくることになります。 テストスイートを実行することが欠かせません。 これを実行しておけば、この先に行う多くの作業に入る前に不備があることが分かるからです。

Binutils はアセンブラーとリンカーを二箇所にインストールします。 /tools/bin/tools/$LFS_TGT/bin です。 これらは一方が他方のハードリンクとなっています。 リンカーの重要なところはライブラリを検索する順番です。 ld コマンドに --verbose オプションをつけて実行すれば詳しい情報が得られます。 例えば ld --verbose | grep SEARCH を実行すると、検索するライブラリのパスとその検索順を示してくれます。 ダミープログラムをコンパイルして ld--verbose オプションをつけてリンクを行うと、どのファイルがリンクされたが分かります。 例えば gcc dummy.c -Wl,--verbose 2>&1 | grep succeeded と実行すれば、リンカーの処理中にオープンに成功したファイルがすべて表示されます。

次にインストールするのは GCC です。 configure の実行時には以下のような出力が行われます。

checking what assembler to use... /tools/i686-lfs-linux-gnu/bin/as
checking what linker to use... /tools/i686-lfs-linux-gnu/bin/ld

これを示すのには重要な意味があります。 GCC の configure スクリプトは、利用するツール類を探し出す際に PATH ディレクトリを参照していないということです。 しかし gcc の実際の処理にあたっては、その検索パスが必ず使われるわけでもありません。 gcc が利用する標準的なリンカーを確認するには gcc -print-prog-name=ld を実行します。

さらに詳細な情報を知りたいときは、ダミープログラムをコンパイルする際に -v オプションをつけて実行します。 例えば gcc -v dummy.c と入力すると、プリプロセッサー、コンパイル、アセンブルの各処理工程が示されますが、さらに gcc がインクルードした検索パスとその読み込み順も示されます。

次に健全化された (sanitized) Linux API ヘッダーをインストールします。 これにより、標準 C ライブラリ (Glibc) が Linux カーネルが提供する機能とのインターフェースを可能とします。

次のパッケージは Glibc です。 Glibc 構築の際に気にかけるべき重要なものは、コンパイラー、バイナリツール、カーネルヘッダーです。 コンパイラーについては、一般にはあまり問題にはなりません。 Glibc は常に configure スクリプトにて指定される --host パラメーターに関連づけしたコンパイラーを用いるからです。 我々の作業においてそのコンパイラーとは i686-lfs-linux-gnu-gcc になります。 バイナリツールとカーネルヘッダーは多少複雑です。 従って無理なことはせずに有効な configure オプションを選択することが必要です。 configure 実行の後は glibc-build ディレクトリにある config.make ファイルに重要な情報が示されているので確認してみてください。 なお CC="i686-lfs-gnu-gcc" とすれば、どこにある実行モジュールを利用するかを制御でき -nostdinc-isystem を指定すれば、コンパイラーに対してインクルードファイルの検索パスを制御できます。 これらの指定は Glibc パッケージの重要な面を示しています。 Glibc がビルドされるメカニズムは自己完結したビルドが行われるものであり、ツールチェーンのデフォルト設定には基本的に依存しないことを示しています。

Binutils の2回めのビルドにおいては ld コマンドのライブラリ検索パスを設定するために configure の --with-lib-path スイッチを指定します。

GCC の第2回目のビルドにおいても、ソースを修正して新しいダイナミックリンカーが用いられるようにします。 これをもし誤ってしまうと、ホストシステムの /lib ディレクトリが埋め込まれたダイナミックリンカーを用いるものとして GCC が生成されてしまいます。 こうしてしまうと、ホストシステムに依存しない形を目指すという目的が達成できません。 これ以降、コアとなるツールチェーンは、自己完結し (self-contained)、自分だけで処理できる (self-hosted) ものとなります。 第5章の残りのパッケージは /tools にある新たな Glibc を用いてビルドされます。

第6章での chroot による環境下では、実質的なパッケージとして Glibc を初めにビルドします。 これは上に述べているように自己完結した性質を目指すためです。 /usr に Glibc をインストールしたら、ツールチェーンのデフォルトディレクトリの変更を行い LFS システムを構築する残りのパッケージをビルドしていきます。