ライブラリ、リンク


プログラムのコンパイルも終わりました。 あとは、必要なものを取りまとめて(リンク)、実行可能な状況に持っていくだけです。 リンクの対象となるのは、 先ほど出来たオブジェクトファイルと、オブジェクトファイルの集合体であるライブラリです。 で、実行するのに必要なもの(変数、関数)をかき集めてつなぐ操作がリンクです。

まずは、オブジェクトファイルがどのような情報をもっているか、nm コマンドで見てみましょう。

kamada@cygwin% nm hello.o
....
00000010 T _main
         U _printf
....
という結果が返ってきます。 内容としては、 main関数の定義を含んでいる。printf関数を利用しているがその定義は持っていない。 といったところです。

さて、printfですがどこにあるかというと、標準ライブラリのなかにあります。 例えば、"/usr/lib/libc.a" というファイルの中にあるわけです。 ためしに、

kamada@cygwin% nm /usr/lib/libc.a
とやってみると、いろんな情報が入っていることが分かることでしょう。あまりにも多いので、 grep コマンドで "T _printf" という文字列を探してみると、
kamada@cygwin% nm /usr/lib/libc.a | grep "T _printf"
00000000 T _printf
という感じで printf 関数が含まれていることが分かります。 つまり、ユーザのプログラムは、必要な標準ライブラリをリンクした上で、 実行されることになると言うわけです。

ところで、皆さん、三角関数などの数学演算パッケージを使うときは、

kamada@cygwin% gcc ...... -lm
などと書くと思います。この -l というオプションはライブラリをリンクしてねというオプションです。 この場合、例えば "/usr/lib/libm.a" というライブラリをリンクすることになり、 その中にあるライブラリを使えるようになると言うわけです。

というわけで、これで実行ファイルができあがったわけです。 これで、無事 hello world がうごくというわけです。めでたしめでたし。

実は、上の文章では、微妙な言い回して問題を避けていた話があります。 その面倒くさい話をすこしだけしておきます。 リンクの方法には、 コンパイル時点でリンクする静的にリンクする方法(static link)と、 プログラムが実行される直前(load時)に動的にリンクする方法(dynamic link)があります。 UNIX 系の libXXXXX.a というファイルや MS-Windows の XXXX.lib というファイルは静的に 利用するためのライブラリですが、 libXXXXX.so (UNIX系)や XXXXX.dll (MS Windows)というライブラリは動的にリンクするために利用されます。 動的にリンクすることで、実行ファイルを小さく抑えられるなどなどの利点があるわけです。 UNIX 系の環境では、標準ライブラリなどは動的にリンクされることが多いです。


練習問題:

とりあえず、以前につくった C のプログラムについて、実際に変換過程を見てみましょう。 余力のある人は、Cygwin, Linux, IRIX+MIPS(shusaku) などのコンパイル結果などを見比べるのも 悪くないでしょう。

2001.9.25/ Tomio KAMADA: kamada@cs.kobe-u.ac.jp