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

最終的な C ライブラリがこれまでに構築できました。 ここでツールチェーンの調整を行います。 これを行うことで、新たに生成したプログラムが新たに生成したライブラリにリンクされます。

まず /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'

最後のコマンドの出力は以下のようになるはずです。

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