前々回にFreeBSDでの静的ライブラリと動的ライブラリについて書いた。
そのときに、OS Xでもほぼ同じ、と書いたのだが、ここでは違いについて書く。
まず、FreeBSDやLinuxでは動的ライブラリのファイル名は *.so
だが、OS Xでは *.dylib
である。(試しに*.so
にしても動いたので、拡張子はなんでも良いようだが)
そして、ライブラリの依存関係を調べるコマンドは ldd
ではなく otool -L
を使う。
リンク時のオプションで -L と -l を使うのは同じ。
ldには-rpath
オプションはあるが -rpath-link
オプションはない。(リンク時には-Lオプションと標準パスだけで探すらしい)
そして、-rpathオプションの扱いもFreeBSDとは違う。
基本
動的ライブラリの作成
前々回と同じソースで、libfunc2.dylibを生成してみる
% cc -c -fPIC func2.c
% cc -shared -install_name @rpath/libfunc2.dylib -o libfunc2.dylib func2.o
FreeBSDとの違いは、-install_nameオプションでライブラリのinstall nameを指定すること。
動的ライブラリのリンク
% cc -o test2 test2.c -L. -lfunc2 -Wl,-rpath,.
これで何が起きるかと言うと、実行ファイルのリンク時に指定した-rpathオプションのパス(.)が、ライブラリの@rpath
と置き換えられる。
このため、実行時には./libfunc2.dylibを見つけて動的リンクしてくれる。
% otool -L test2
test2:
@rpath/libfunc2.dylib (compatibility version 0.0.0, current version 0.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1197.1.1)
% otool -L libfunc2.dylib
libfunc2.dylib:
@rpath/libfunc2.dylib (compatibility version 0.0.0, current version 0.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1197.1.1)
% otool -D libfunc2.dylib
libfunc2.dylib:
@rpath/libfunc2.dylib
otool -D
は、動的ライブラリのid nameを表示するコマンド。
ライブラリが固定のディレクトリにインストールされる場合、わざわざ@rpath
を使う必要はないので、以下のように書くことができる。
% cc -c -fPIC func2.c
% cc -shared -install_name ./libfunc2.dylib -o libfunc2.dylib func2.o
% cc -o test2 test2.c -L. -lfunc2
この場合は実行ファイルのリンク時に-rpathオプションは不要になる。(実際には./
ではなくインストールディレクトリを指定すること)
たぶん、通常のコマンドラインアプリを作成する分には、ここまでの知識があれば良い。(むしろ、OS Xの場合は-rpathを使わない方が簡単だと思う)
しかし、OS Xの場合は、一般に配布されるアプリケーションは.appと言う形式になる。
.appは、実際にはディレクトリで、中には実行ファイルの他に必要なライブラリや、リソースファイルなどが含まれている。
このようなときに、.appがどこに置かれても動作するためには、ライブラリが/usr/local/libや/opt/local/libにあることが期待できず、.app内の相対パスで指定されなければならない。
man dyld
すると、@rpath
の他に、@executable_path
や@loader_path
と言うものが見つかる。それぞれ、実行ファイルのパスや、フレームワークのパスに置き換えられる。
ただ、通常.appを作成するときには、XcodeやQt Creatorなどを使用すると思うので、自分でこの辺の細かい指定をすることはあまりないのではないかと思う。
ライブラリを作成するときに、こんなものもあったかな〜と思い出すくらいで良いのでは。(と言うか、現時点であまり理解していない)
libtool
OS Xも、Xcodeを入れると(?)、/usr/bin/libtoolが入る。
が、このlibtoolがGNUのlibtoolとは違うもののようで、同じ使い方はできない。
OS Xのlibtoolができることは、動的ライブラリを作ることと、静的ライブラリを作ることだけである。
*.lo
も *.la
も作らないので、同じ名前の完全な別物と考えた方が良いだろう。
% cc -c -fPIC test4.c
% libtool -dynamic -o libfunc4.dylib -install_name /usr/local/lib/libfunc4.dylib func4.o
ld: warning: -macosx_version_min not specified, assuming 10.10
% cc -o test4 test4.c -L. -lfunc4
ここで試した内容は、githubの osx ブランチにcommitしてある。
https://github.com/false-git/libstudy/tree/osx