OSXのFrameworkを作ってみる

以前dylibを作ってみましたが、同じノリでFrameworkを作ってみます。AppleのMach-O Programming Topicsを参考にしました。Xcodeは可能な限り使いたくないのでコマンドラインでやります。

まずライブラリにするhello関数を用意します。文字列出力しているだけですがObjective-Cで書いています。

// hello.h
#import <Foundation/Foundation.h>

void hello(NSString* text);

// hello.m
#import "hello.h"

void hello(NSString* text) {
	NSLog(@"hello %@ world!!", text);
}

早速フレームワークを作ってみます。ドキュメントによるとフレームワーク名と同じ名前のバイナリをHello.framework/Versions/A/Helloに置けば良さそうです。あとはシンボリックリンクを適宜張っていきます。

$ gcc -c hello.m
$ ls
hello.h hello.m hello.o
$ mkdir -p Hello.framework/Versions/A/Headers
$ gcc -dynamiclib -framework Foundation -o Hello.framework/Versions/A/Hello hello.o
$ cp hello.h Hello.framework/Versions/A/Headers/.
$ cd Hello.framework/Versions
$ ln -s A Current
$ cd ..
$ ln -s Versions/Current/Hello Hello
$ ln -s Versions/Current/Headers Headers

最終的な構成は以下です。シンボリックリンクでやや複雑に見えますが、dynamiclibが中に入っているただのディレクトリです。Xcodeとかでフレームワークへの参照を追加したりしているとブラックボックスな香りがして難しそうですが、何でもないですね。

$ tree Hello.framework
Hello.framework
├── Headers -> Versions/Current/Headers
├── Hello -> Versions/Current/Hello
└── Versions
    ├── A
    │   ├── Headers
    │   │   └── hello.h
    │   └── Hello
    └── Current -> A

次に作ったHello.frameworkを~/Library/Frameworksに置いて、実際に使ってみます。システムライブラリ扱いになるので、importに注意しましょう。

// main.m
#import <Hello/hello.h>

int main() {
	hello(@"framework");
	return 0;
}

ビルドは-frameworkオプションに続けてHelloとすると、先ほどのHello.frameworkとリンクできます。この際に.frameworkは省略します。-Fオプションでフレームワークのサーチパスを追加します。

$ gcc main.m -framework Foundation -framework Hello -F/Users/taichino/Library/Frameworks
$ ./a.out
2012-09-22 06:02:59.293 a.out[27553:60b] hello framework world!!

無事に動きました。思ったより簡単で良かったです。

ひとつ分からない事が残っています。環境変数にDYLD_FRAMEWORK_PATHを追加しておくと、ビルド時に-Fオプションを指定しなくても良いので嬉しいはずなのですが、そうするとフレームワーク内のHello /hello.hが見つからないよとコンパイルエラーになります。/Library/Frameworks辺りに入れておけば問題ないので、実害はないですが釈然としないです。

何か知っている方が居られましたら教えてください。

Leave a Reply

Your email address will not be published. Required fields are marked *