2015年6月26日金曜日

gccコマンドで引数-lを使ってリンクするときの注意点と、実行ファイルとライブラリの依存関係

例えば、次のような「test.c」というファイルがある場合。
log10(x)はmath.hをインクルードしなければ使えない関数である。

#include <stdio.h>
#include <math.h>

void main() {
    double x = 100;
    x = log10(x);
      printf("%f\n",x);
    return ;
}

これを端末で次のようにコンパイルしようとすると、
gcc -o test test.c
以下のエラーが出て失敗する。
 `log10' に対する定義されていない参照です
これは必要なライブラリとのリンクができなかったために起こる。

なので、引数-lを使って使うライブラリを指定する必要がある。
ここではlibm.aが必要なので次のどちらかのようにしてコンパイルすると、エラーは出ない。
 gcc -o test test.c -lm
 gcc test.c -lm -o test

ただし、順番を変えて次の場合はエラーが出て失敗する。
 gcc -o test -lm test.c
 gcc -lm -o test test.c 
 gcc -lm test.c -o test

一応、オブジェクトファイルを作ってから試してみたが、結果は同じ。
test.cよりも-lmが後に無いとダメらしい。
読み込んだ順番に処理するため、libm.aより後に読み込まれたものは関数が組み込まれないんだとか。(GCCコマンド・オプションのリンク処理用のオプションを参照。)

私のように「引数-lm入れればいいんでしょ〜」ぐらいの感覚で使ってしまうと、ドツボにハマるので気をつけましょう・・・・


ライブラリのことを調べていたら、依存関係を調べるコマンドを発見。
実行ファイルのライブラリの依存関係を調べるにはlddコマンドを利用するらしい。
ldd -v xxxx xxxxは実行ファイルオプション-vは詳細情報の追加
とすることで、リンクしている共有ライブラリを検索できる。

試した結果。
$ ldd test
linux-gate.so.1 =>  (0xb77cd000)
libm.so.6 => /lib/i386-linux-gnu/libm.so.6 (0xb7771000)
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb75c3000)
/lib/ld-linux.so.2 (0xb77d0000)


意味しているところは、testを実行するにあたり、
linux-gate.so.1
libm.so.6
libc.so.6
/lib/ld-linux.so.2
という共有ライブラリが必要であり、「=>」の後のパスは実際にリンクされたライブラリ。

「リンクさせたのはlibm.aじゃなかったの?」と思ってライブラリの場所を、
 sudo find / -name "libm.a" -ls
で探してみたら
 /usr/lib/i386-linux-gnu/libm.a
にあった。ARアーカイブらしい。
同じディレクトリに共有ライブラリlibm.soのリンクも発見。上記のアドレスはそのリンク元の模様。
何らかの処理でこうなっているのだろうが、よくわからん。

ちなみに、lddでコマンドは/binディレクトリに入って調べると、各コマンドに必要なライブラリを調べることができるようだ。

0 件のコメント:

コメントを投稿