ライブラリは、アプリケーション開発を補助する便利な機能が詰まった サブルーティン群。
OSXで使われる ライブラリは、その使われ方によって、3つの形式に分類されます。
種類 | ライブラリ本体 の拡張子 | インストールされる場所 |
静的( static )ライブラリ | .a | システム内 usr/local/lib |
共有(shared)/動的(dynamic)ライブラリ | .dylib | プログラムに関連した 任意の場所 |
フレームワーク( framework) | .framework | システム内 /Library/Frameworks
特定ユーザーだけが利用する場合は
/Users/ユーザー名/Library/Frameworks |
拡張子によって、これがどんなライブラリか見分ける事が出来ます。
静的ライブラリでは、ライブラリ本体とは別に、ヘッダファイルも
/usr/local/include/ という場所にインストールされます。
仕組み
ライブラリの主な使われ方を具体的に説明すると
|
静的ライブラリ
ライブラリはコンパイル時に、アプリケーションの内部に埋め込まれる形となり、
アプリケーション単体さえあれば、ライブラリの機能が使える。
|
|
共有(動的)ライブラリ
コンパイルされた アプリケーション と ライブラリは 別々で、アプリケーションの実行時にライブラリが外部から読み込まれる。アプリケーションを実行するには、ライブラリもインストールされてないといけない。
|
このうち、
動的ライブラリ と呼ばれるものは、
共有ライブラリの一種で、
アプリの起動時に読み込まれるのが、共有ライブラリ
それ以外の時に読み込まれるものが、動的ライブラリ
とされています。
また、どの形式でインストールするかは、ユーザーがライブラリのビルド時にオプションを付けて指定する事ができます。これはライブラリのドキュメントにあるコマンドに従います。
(拡張ライブラリの中には、親ライブラリと同じタイプの形式でリンクしないと、動作やインストールが失敗するものがあります。 これを防ぐためには、静的・動的ライブラリ両形式でインストールするといいかもしれません。)
しかし、他の人が配布しているライブラリを、自分のプログラムに組み込んで配布したりする時は注意しなければいけません。ライセンスは、自分の作ったプログラムを他の人にどのような方法でこれを使ってもらいたいかを記した決まり事です。
目的・用途、ライセンスの組み合わせによってはGPLやLGPLライセンスのライブラリと一緒には使えないこともあります。たいていはライブラリに付いてくるドキュメントに書いてあるので、配布の前にはよく内容を確かめておきましょう。
アプリケーションやライブラリを配布する場合には使用目的(商用なのか、フリーなのか)をはっきりさせておくのと、 必要なライブラリをユーザーにそろえてもらうか、 ライブラリをアプリに内包してユーザーのインストールの負担をさせないか、そしてライセンスに違反しない使い方で組み込む必要があります。
フレームワークを説明する前に「バンドル」
bundle (バンドル)とは 動的ロードモジュール とよばれ、
OSXアプリに関する リソースなど複数のファイルがパッケージ(格納)された
特殊な拡張子を持ったディレクトリのことで、アプリケーション実行時に動的に読み込まれる。拡張子は特に決められていないが「.bundle」が推奨されている。
また、外見はアプリケーションファイル1個に見えて、実体は、アプリ本体を含む関連ファイルがパッケージ(格納)されたアーカイブ のことを アプリケーション バンドル(Application bundle) と呼びます。Finder上ではフォルダのようにみえて中身を開いて閲覧することができます。
フレームワークとは
フレームワークとは、 bundle(バンドル) の形式をとっていて、
リソース情報と一緒に動的に 読み込まれる 共有ライブラリのことをいう。
拡張子は 「.framework」。
それぞれのライブラリの形式を、分かりやすく図にすると次のようになる。
具体的には、 bundle ディレクトリの中に、「ライブラリ」と「ヘッダ」と「リソース」のエイリアス と「バージョン情報」 のディレクトリがある。
「バージョン情報」ディレクトリの中には、ヘッダとリソースと共有ライブラリの本体が格納されている。
フレームワークには、 「 埋め込みフレームワーク 」というものがあり、
これはコンパイル時に アプリケーション バンドル(Application bundle) として 埋め込まれるフレームワークのことをいう。
もうひとつの特徴は、 フレームワークは include する際に 記述するヘッダファイル名が
#include<フレームワーク名/ヘッダ名> という形式で書かれるということ。
例えば xxx というフレームワークのxxx.h という名前のヘッダファイルを include する時は
#include<xxx/xxx.h>
と 書かれる。
他の例:
#include<GLUT/glut.h>
#include<OpenGL/glext.h>
#include<Carbon/Carbon.h>
#include<SDL/SDL.h>
#import<Allegro/allegro.h>
もし #include<glut.h> とすると、フレームワークのGLUTライブラリとは別形式でインストールされた GLUTライブラリ を指していることになる。
MacOSX と Windows で読み込むヘッダ名が違うことがある(OpenGL等)ので注意。
▼includeするヘッダの覚え書き
#include<header.h> : C言語ヘッダファイル
#include<header.hpp> : C++言語ヘッダファイル
#include<header> : 標準C++ライブラリの場合(拡張子がつかない)
#include<framework/header.h> : frameworkを使う場合
#import <framework/header.h> : ObjC/Cocoa の場合
▼拡張子の覚え書き
〜.h/〜.hpp : ヘッダファイル/C++ヘッダファイル
〜.m/〜.mm :Objective-C ソース/ ObjectiveC++ のソース
〜.c /〜.cpp :C言語ソース/C++言語ソース
〜.s :アセンブラソース
〜.r :リソースファイル(for Carbon)
〜.pbproj :ProjectBuilder時代の
〜.xcode :Xcode プロジェクトファイルv1.x
〜.xcodeproj :Xcode プロジェクトファイルv2.x
〜.o :オブジェクトファイル(obj) (.out とする場合も)
これはコンパイルされた結果生成されるバイナリデータで、これらをアーカイブすることで、ライブラリやアプリケーションを作成します。
〜.a :静的ライブラリ
〜.so.(ver) :共有ライブラリ(UNIX)
〜(ver).dylib :共有ライブラリ(OSX)
〜.bundle :動的ロードモジュール(バンドル)
〜.framework :フレームワーク 、外見はフォルダ
〜.app :アプリケーションバンドル、外見はアプリケーション
CFLAGS /usr/local/include ヘッダファイルのありか
LDFLAGS -L/usr/local/lib ライブラリファイルのありか
ライブラリを使う方法。ここでは、プログラム内から使う方法ではなくプログラムを書いたあとでアプリケーションを作るために、
コンパイル時に行なう指定のことをいいます。
gcc系のコンパイラを使うなら、どれでも共通するやり方です。
(Xcodeは、コンパイルに必要なコマンドを自動的に生成したり、コンパイルのオプションやフラグなどをGUIから指定することができます、このリンカフラグというのは、ターミナル上でmakeやコンパイルを行なうときのコマンドにも使われるものと同じです。)
gccでは
リンカフラグのオプションを指定することで、コンパイル時にライブラリをリンクすることができます。
Xcode の場合は
「ファイルとディレクトリ」ツリーの「ターゲット」から、「リンカフラグの設定」を見ると設定欄が見つかると思います。
例えば、
xxx というライブラリをインストールしていて、コンパイル時にリンク させるには…
「lib
xxx.dylib」 という 共有ライブラリとしてインストールした場合:
ソースには、#include<xxx.h>
リンカフラグに -lxxxを追加。
「lib
xxx.a」 という静的ライブラリとしてインストールした:
ソースには、#include<xxx.h>
リンカフラグに -L/usr/local/lib/ と -lxxxを追加。
「
xxx.framework」 というフレームワークとしてインストールした:
ソースには、#include<xxx/xxx.h>
Xcodeの「ファイルとディレクトリ」ツリーの「フレームワーク」に xxx.framework を登録。
また、 リンカフラグの設定に、 -framework xxx というオプションを追加する。
自分でオリジナルのライブラリを開発したり、
配布されているライブラリが、OSX 対応の makefile が用意されていない 場合は、
自分でライブラリをコンパイル・インストールしなければならない。
しかし、たいていはライブラリをインストールする時に makefile スクリプトが自動的にライブラリのコンパイルから
インストールまで面倒をみてくれるので、始めのうちは、知らなくても問題ないと思う。
コンパイル時に gcc にどんな オブションが必要なのかは、 makefile や、インストール時のログを見て調べると参考になるかもしれない。
以下は、情報が少ないので草稿以前のメモ(あまりあてにならない)。静的ライブラリの作り方は、わりと簡単ですが。。。。他はよくわからない
静的ライブラリ
拡張子:
libxxx.a (UNIX , OSX )
xxx.lib (Windows)
作り方: ar コマンドにより .o ファイルをアーカイブ化
共有ライブラリ-Shared object-(起動時に動的にロードされる)
動的ライブラリ(共有ライブラリの一種 で、起動時以外にロードされる )
OSX Darwin では、動的ロードモジュール:bundle というのがあり、共有ライブラリとは区別される → フレームワーク
動的ライブラリにまつわるものとして static linker (ld) と、dynamic linker (dyld)の2つのリンカがある。
static linkerは build 時に使われ、シンボル(関数名を呼び出すしるし)が記録されたテーブルによってリンクされる。この時見つからないものは undifined symbol となる。
dynamic linker (dyld)は、アプリケーションの実行時に使用され、必要なライブラリをメモリ上のアドレスに配置する。
この時、アプリケーションのアドレスと重なってはいけない
Xcodeには、動的ライブラリ用のテンプレートも用意されているようなので、それを使って ライブラリを作成するのが手っ取り早いかも。
UNIX と OSX 拡張子 と命名規則
UNIX と OSX では、共有ライブラリのファイルの命名規則が違う。具体的には次のようになる
libxxx.so.バージョン番号 (unix) UNIX の ELF システムでは 最後にくる。
libxxx.バージョン番号.dylib (OSX Darwin ), Darwin (OSX )の Mach-0 では、拡張子の前にくる。
libxxx.dll (Windows)
このバージョン番号は、ピリオドで区切られた、3つの数字(例 6.3.2.)で、
詳細は以下の通りである。
例えば、 libfreetype.6.3.2.dylib という名前の場合は、
6 --- メジャーバージョン番号
3 --- マイナーバージョン番号(省略可能)
2 --- バグフィックス バージョン番号(省略可能)
(なお、これらの3つの数字をすべて省略すると、ワイルドカード(何でもOK)扱いとなる)
共有ライブラリは、以上の バージョン番号を管理することで 互換性を保っている。
具体的には、バージョンが変わってファイル名が変わっても大丈夫なように、
ひとつの共有ライブラリは少なくとも3つの名前を使い分ける。
OSX の usr/local/lib/ディレクトリにはやたらとたくさんファイルがあるのは共有ライブラリのせい。
本体名(real name)と、参照用のシンボリックリンクの名前( soname , linker name )が必要である。
3つの名前の詳細は以下の通りである。
libfreetype.6.3.2.dylib ---- real name マイナーバージョン(3)(2)も記述されている、ライブラリ本体
libfreetype.6.dylib ---- soname メジャーバージョン(6)のみ記述される -- シンボリックリンク
libfreetype.dylib ------ linker name ライブラリの名前 -- シンボリックリンク
共有ライブラリの作り方メモ
■共有ライブラリ:
UNIX , Linux では、-shared オプションをつけてコンパイル。次に-fPIC または -fpic オプション を使いコンパイル。
「位置非依存コード - PIC (position independent code)」形式とする らしい。あと -Wl,-soname,xxx.so.
「-Wl,*****」 とあるのは static linker ( ld )に渡すオプションを意味する。
最後に、ln -sf libxxx.so.1.2 libxxx.so のようにシンボリックリンクを作成
OSX Darwin では -dynamiclib オプションをつけてコンパイル。
次に、PIC オプションつけなくてもいい代わりに -fno-common オブションを付けてコンパイル。
soname と linker name に当たるファイルへの シンボリックリンクを作成するらしい。
-compatibility_version 1としてバージョン宣言して、
ln -s libxxx.1.2.dylib libxxx.1.dylib 最後に soname への シンボリックリンク作成
共有ライブラリの ld フラグは、それぞれ
Linux の場合 拡張子 so LDFLAGS = -shared
OSX の場合 拡張子 dylib LDFLAGS = -dynamiclib
MacOSX で共有ライブラリ作るときの注意
ld: common symbols not allowed with MH_DYLIB output format with the -multi_module option
共通シンボルが許されていない(common symbols not allowed)というエラーが出たら
CFLAGS = -fno-common
を追加。
■動的ロードモジュール bundle:
その他メモ:
Framework の場合、位置を指定する インストールパス @executable_path/../Frameworks/ を行う
もしこれが指定されなかったら、自動的に Framework ディレクトリから探すらしい。
-install_name "`echo "@executable_path/〜。
Xcode にも、プリバインディング指定がある。
共有ライブラリは実行時に、メモリアドレス上に置かれるので、
セグメントの開始アドレス -prebind -seg1addr 0x******←アドレス開始位置も必要らしい。
このアドレスは アプリケーションのアドレス 0x000000 と重なっていてはいけない。
gcc の -g オプション: デバッグオプション。
OSX の場合、バンドルする場合は、-single_module を使わない?
gcc の -D オプションは -Dxxx と書くと、 #define xxx と同じ意味。
コンパイル時のパラメータを渡したりすることに利用される。
共有ライブラリ内を構成するファイルやクラス等が、どんなふうになってるのか調べるコマンドがある。
ldd
OSXでは 次のコマンドを使う。
otool -L
使用例:
usr:/usr/local/lib usr$ otool -T -v liballeg-4.2.0.dylib
liballeg-4.2.0.dylib:
Table of contents (1474 entries)
module name symbol name
qwindow.o .objc_class_name_AllegroView
system.o __crt0_argv
vtable8.o __linear_vtable8
ufile.o _a_getdcwd
alegro.o _a_linker_midi
alegro.o _a_linker_mouse