2013/11/17 自作共有ライブラリを使用するためには | 何が善で何が悪か
仕事場で、C++の共有ライブラリのテストをすることがあった。

僕は、今までC++(C)言語を使ってきたことがなく(挫折したからです。)、
共有ライブラリ?ヘッダファイル?という状態でした。

チームのメンバーにもC++に精通している人がいないので、とりあえず、色々と調査。

用語
ヘッダファイル(~.h)
共有ライブラリ(~.so)
静的ライブラリ(~.a)
オブジェクトファイル(~.o)


イメージとしては、
1.自作したヘッダファイル(ここではtest.hとする)と、元のソース(ここではtest.ccとする)を作成
2.元のソースをコンパイルし、共有ライブラリを作成
3.共有ライブラリを任意の場所(/home/xxxx/lib/)に配置(ライブラリが増えてきた時に管理やすいように)
4.共有ライブラリを使用するソース(ここではmain.cとする)を作成
5.コンパイル
で、ここで問題が発生する。


$ gcc -I/home/devman/include/ -L/home/devman/lib/ -ltest main.cc -o main 

/tmp/cc0wJA6D.o:(.eh_frame+0x12): undefined reference to `__gxx_personality_v0'


エラーになる…`__gxx_personality_v0'が定義されてないよ…
こんなの分かんないよ…使ってないし…とか思いながら、とりあえず…検索…

すると、gccのバージョンによって、このエラーが出ることが分かった。
解決方法としては、libstdc++ をというライブラリを追加してやると良いらしい。

$ gcc -I/home/devman/include/ -L/home/devman/lib/ -ltest -lstdc++ main.cc -o main 

$ ls

main  main.cc   test.cc

おぉ!上手くコンパイル出来た!

それで、実行してみる…
$ ./main

./main: error while loading shared libraries: libtest.so: cannot open shared object file: No such file or directory

ホヒホヒ(^^;)
何故や…何故なんだ…
とりあえず、調べる…
すると、lddというコマンドを打つことで、シンボリックリンクが貼られているかどうかが分かるとのことだったので、言われた通りにやってみる

$ ldd main

linux-vdso.so.1 =>  (0x00007fff89126000)

libtest.so => not found

libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x0000003b02c00000)

libc.so.6 => /lib64/libc.so.6 (0x0000003aff800000)

libm.so.6 => /lib64/libm.so.6 (0x0000003b00400000)

/lib64/ld-linux-x86-64.so.2 (0x0000003aff000000)

libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x0000003b02400000)

ホヒ(^^;)
libtest.so => not found
not foundホヒ^^;

これで、理由が分かった。現在の状態だと、libtest.soにリンクが貼られていない状態なので、mianを実行しようとしても、エラーになっていたみたい。

なので、

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/devman/lib/

こんな感じで、パスを張ってあげると

$ ldd main

linux-vdso.so.1 =>  (0x00007fffab5ff000)

libtest.so => /home/devman/lib/libtest.so (0x00007f05cc248000)

libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x0000003b02c00000)

libc.so.6 => /lib64/libc.so.6 (0x0000003aff800000)

libm.so.6 => /lib64/libm.so.6 (0x0000003b00400000)

/lib64/ld-linux-x86-64.so.2 (0x0000003aff000000)

libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x0000003b02400000)

上手くリンクが貼られたみたいです。

うーん、コンパイルしている時に、オプションで
-I/home/devman/include/ -L/home/devman/lib/
みたいな感じで、ライブラリのある場所を指定しているし、コンパイルしたら
勝手にリンク貼ってくれないんですかね…
何か自分が間違っているのかもしれませんが…
まだ、謎です…

とりあえず、mainを実行してみる…

$ ./main

hoge

hoge

hoge

hoge

hoge

おぉ!上手く実行できた!(この共有ライブラリでは、hogeを5回表示させるというファンクションを作成しています)


よし、出来た。

分かったこと

$ gcc -I/home/devman/include/ -L/home/devman/lib/ -ltest main.cc -o main 

-I(大文字のi)にはヘッダファイルのある場所を指定
-Lにはライブラリがある場所を指定 
-l(小文字のL)には共有ライブラリを指定する。-lはlibの省略形はがある。なので、今回作成した共有ライブラリ、libtestを指定する時は、-ltestとする(-llibtestとかすると-liblibtestってなっちゃう)

・リンク大事
・lddコマンド
・なんとなくのヘッダファイルとライブラリの概念


まだ、全然理解できていない気がするけど、とりあえず、先に進みます。
ホヒホヒ(^^)