Search on the blog

2014年3月15日土曜日

-lmとは何か

 gccでコンパイルするときにつける-lmについて調べてみました。
libm.aというライブラリをリンクしているということは知ってました(※1)が、.aファイルが何者なのか?どうやって作るのか?は知らなかったので、いい勉強になりました。
 ついでに、.aファイルを自分で作ってみました。

-lmとは?
まず、-lオプションについて。
-lxxxというオプションをつけると、リンカがlibxxx.aというファイルを探してリンクしてくれます(※2)。

どこを探すかというと、デフォルトで設定されているパスを探します。

$ gcc --print-search-dirs

というコマンドを実行すると、gccがプログラム/ライブラリを検索するパスの一覧が表示されます。
デフォルトの検索パスに含まれていない場所も検索するようにしたい場合は、-Lオプションを使ってパスを指定することが出来ます。

.aファイルの拡張子aは「archive」の意味です。
.aファイルはarコマンドで作成することが出来ます。また、arコマンドを使うと、archiveの中身を確認することも出来ます。

例えば、-lmでリンクされるlibm.aの中身を確認すると、

$ ar -t `locate libm.a | head -n 1`
k_standard.o
s_lib_version.o
s_matherr.o
s_signgam.o
.....

のようにオブジェクトファイルが含まれていることが分かります。
オブジェクトファイルが大量にarchiveされていますが、実際にリンクされるのはリンク先で使用されるオブジェクトファイルのみです。

ライブラリには静的ライブラリと動的ライブラリが存在します。
*.aファイルは静的ライブラリ。動的ライブラリは*.soというファイル名です。
リンカは、まず動的ライブラリ、次に静的ライブラリという順番でライブラリを検索します。
静的ファイルは実行ファイルの内部にリンクされます。これに対して、動的ライブラリはランタイムでリンクされます。

静的ライブラリを作る
以下の4つのオブジェクトファイルをarchiveすることにします。
  • add.o
  • sub.o
  • mul.o
  • div.o
それぞれのファイルには、int同士の加減乗除を行う関数を定義しておきます。

で、これらをarchiveします。
$ ar -q -v libhoge.a *.o
a - add.o
a - div.o
a - mul.o
a - sub.o

テスト用関数を書きます。
#include <stdio.h>

int main() {
    int a, b;
    a = 10;
    b = 2;

    printf("%d + %d = %d\n", a, b, add(a, b));
    printf("%d - %d = %d\n", a, b, sub(a, b));
    printf("%d * %d = %d\n", a, b, mul(a, b));
    printf("%d / %d = %d\n", a, b, div(a, b));

    return 0;
}
で、コンパイルします。
libhoge.aファイルはmain.cファイルと同じ階層に保存します。libhoge.aファイルのパスが検索されるように、-Lオプションで-L.と指定します。

$ gcc main.c -L. -lhoge -o test

正常に動作しました。

訂正
(※1) -lmでlibm.aがリンクされるというのは間違いでした。libm.soという動的ライブラリが存在するので、libm.soが動的にリンクされます。
(※2) これは間違いです。正しくは、「-lxxxというオプションをつけると、リンカはまずlibxxx.soというファイルを探してそれがあればリンクします。もし無ければ、libxxx.aというファイルを探してリンクします。」

0 件のコメント:

コメントを投稿