6.10. ツールチェーンの再調整

最終的な C ライブラリがこれまでに構築できました。 ここでツールチェーンの調整を再度行います。 これを行うことで、新たに生成したプログラムが新たに生成したライブラリにリンクされます。 この作業は 第5章 の冒頭にて行った「調整」作業と同様のことです。 ただし調整される方向が逆になります。 第5章 では、ホストシステムの /{,usr/}lib ディレクトリを新しく作った /tools/lib ディレクトリに仕向けていました。 今度は同じ /tools/lib ディレクトリを LFS の /{,usr/}lib ディレクトリに向けます。

まず /tools ディレクトリにあるリンカのバックアップをとっておき、第5章にて作成した調整済みリンカに置き換えます。 /tools/$(gcc-dumpmachine)/bin ディレクトリにあるリンカに対してのシンボリックリンクも正しく生成しておきます。

mv -v /tools/bin/{ld,ld-old}
mv -v /tools/$(gcc -dumpmachine)/bin/{ld,ld-old}
mv -v /tools/bin/{ld-new,ld}
ln -sv /tools/bin/ld /tools/$(gcc -dumpmachine)/bin/ld

次に GCC スペックファイルを修正し、新しいダイナミックリンカを指し示すようにします。 単純に 「/tools」 という記述を取り除けば、ダイナミックリンカへの正しい参照となります。 またスペックファイルを修正することで GCC がヘッダファイル、および Glibc の起動ファイルを適切に探し出せるようになります。 以下の sed によりこれを実現します。

gcc -dumpspecs | sed -e 's@/tools@@g' \
    -e '/\*startfile_prefix_spec:/{n;s@.*@/usr/lib/ @}' \
    -e '/\*cpp:/{n;s@$@ -isystem /usr/include@}' > \
    `dirname $(gcc --print-libgcc-file-name)`/specs

スペックファイルの内容を実際に確認して、今変更した内容が正しく反映されていることを確認しておいてください。

この時点において、調整したツールチェーンの基本的な (コンパイルやリンクなどの) 機能が正しく動作していることを確認する必要があります。 これを行うために以下の健全性検査を実行します。

echo 'main(){}' > dummy.c
cc dummy.c -v -Wl,--verbose &> dummy.log
readelf -l a.out | grep ': /lib'

問題なく動作した場合はエラーがなかったということで、最後のコマンドから出力される結果は以下のようになるはずです。 (ダイナミックリンカの名前はプラットフォームによって違っているかもしれません。)

[Requesting program interpreter: /lib/ld-linux.so.2]

ダイナミックリンカのディレクトリは、今度は /lib となっているはずです。

ここで起動ファイルが正しく用いられていることを確認します。

grep -o '/usr/lib.*/crt[1in].*succeeded' dummy.log

問題なく動作した場合はエラーがなかったということで、上のコマンドの出力は以下のようになるはずです。

/usr/lib/crt1.o succeeded
/usr/lib/crti.o succeeded
/usr/lib/crtn.o succeeded

コンパイラが正しいヘッダファイルを読み取っているかどうかを検査します。

grep -B1 '^ /usr/include' dummy.log

上のコマンドは正常に終了すると、以下の出力を返します。

#include <...> search starts here:
 /usr/include

次に、新たなリンカが正しいパスを検索して用いられているかどうかを検査します。

grep 'SEARCH.*/usr/lib' dummy.log |sed 's|; |\n|g'

問題なく動作した場合はエラーがなかったということで、最後のコマンドの出力は以下のようになるはずです。 (作業するプラットフォームに応じて「三つの組 (target triplet)」の表記は異なります。)

SEARCH_DIR("/tools/i686-pc-linux-gnu/lib")
SEARCH_DIR("/usr/lib")
SEARCH_DIR("/lib");

次に libc が正しく用いられていることを確認します。

grep "/lib.*/libc.so.6 " dummy.log

問題なく動作した場合はエラーがなかったということで、最後のコマンドの出力は以下のようになるはずです。 (64 ビットマシンであれば lib64 ディレクトリとなるはずです。)

attempt to open /lib/libc.so.6 succeeded

最後に GCC が正しくダイナミックリンカを用いているかを確認します。

grep found dummy.log

問題なく動作した場合はエラーがなかったということで、上のコマンドの出力は以下のようになるはずです。 (ダイナミックリンカの名前はプラットフォームによって違っているかもしれません。 また 64 ビットマシンであれば lib64 ディレクトリとなるはずです。)

found ld-linux.so.2 at /lib/ld-linux.so.2

出力結果が上と異なっていたり、出力が全く得られなかったりした場合は、何かが根本的に間違っているということです。 どこに問題があるのか調査・再試行を行って解消してください。 最もありがちな理由は、スペックファイルの修正を誤っていることです。 問題を残したままこの先には進まないでください。

すべてが正しく動作したら、テストに用いたファイルを削除します。

rm -v dummy.c a.out dummy.log