seraphyの日記

日記というよりは過去を振り返るときのための単なる備忘録

gccで共有ライブラリを創る。

linuxの共有ライブラリは「lib*.so」という名前でなければならない。
実際にはバージョンやリビジョンをふくむ名前を作成し、そのリンク*1を作成する。

[参考リンク]
http://www.linux.or.jp/JF/JFdocs/Program-Library-HOWTO/shared-libraries.html (http://www.linux.or.jp/JF/JFdocs/Program-Library-HOWTO/shared-libraries.html)

  • 共有ライブラリの作成
cd lib
gcc -fPIC -c ../src/*.c
gcc -shared -Wl,-soname,libmysharedlib.so.1 -o libmysharedlib.so.1.0.1 *.o -lc

PICはgccのヘルプによれば、「位置独立おり、分岐において大きなディスプレースメントを要求する場合にも適応します。」とのこと。
-Wl,... がリンカへのオプションとなり、-soname,libmysharedlib.so.1インターフェイスのバージョンをふくむライブラリ名となり、-o libmysharedlib.so.1.0.1 でリビジョン、ビルドナンバーをふくむ実際のファイル名となる。
-lc はC言語ライブラリのリンク。

  • バージョン名のハードリンクの作成
/sbin/ldconfig -n .
ln libmysharedlib.so.1 libmysharedlib.so

ldconfigは、*.so.*から、バージョン名だけのハードリンクを作成する。
-n を付けなければ、/usr/binなどの既定のフォルダに作用しキャッシュを更新する。
-nを付けた場合は、指定のディレクトリだけを処理し、キャッシュは更新しない。
コンパイル時には「*.so」の名前で共有ライブラリが検索されるため、必ず*.soのハードリンクを作成する。
コンパイルされた実行ファイルは「*.so.?」のバージョン付きの名前で環境変数LD_LIBRARY_PATHに基づき共有ライブラリを検索/ロードする。

  • クライアントのビルド
gcc client.c -Llib -lmysharedlib

-lmysharedlib でlibmysharedlib.soをリンクするように指示する。-Llib で共有ライブラリの位置を指示する。
相対パスでも大丈夫のようだ。

  • 共有ライブラリのロードの確認
$ ldd a.out
   linux-gate.so.1 =>  (0x008b4000)
   libmysharedlib.so.1 => lib/libmysharedlib.so.1 (0x006c7000)
   libc.so.6 => /lib/libc.so.6 (0x00111000)
   /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x0065d000)

環境変数 LD_LIBRARY_PATH でライブラリは検索されるので、あとで配置をかえてもロードできるようだ。
これを利用すれば、WindowsのSxS*2みたいに使えるようだ。

*1:共有ライブラリのリンクは、ハードリンクでなければならないようだ。シンボリックリンクではロードできなかった。なので、デバイスをまたがってはいけない。

*2:サイド バイ サイド、Windowsのおいて、DLLをEXEのいるディレクトリを優先でロードする設定/機能のこと。同一のモジュール名であっても独立して読みこまれる。これにより、他のアプリのインストーラにより共有モジュールが更新されることで巻き添えを喰うことがなくなる。この設定をすると、事実上、共有ではなくなるからだ。Windows2000以降でサポート。Win98でもSxSの原型があるようだが、よくわからない。