西海岸より

つらつらざつざつと

staticライブラリにカテゴリを含む際に気をつけること

Xcodeのプロジェクトでstaticライブラリを作る場合で、さらにライブラリにカテゴリの実装が含まれる場合には注意が必要です。

リンカフラグに、「-ObjC」を設定

staticライブラリを利用する側のコードで、カテゴリを利用する場合、そのままでは実行のexeファイルにカテゴリのコードが含まれないようで、リンカフラグに「-ObjC」を設定しておく必要があります。
手順としては、staticライブラリを利用するターゲットの設定を開き、「他のリンカフラグ」に「-ObjC」を追加すればOKです。


カテゴリの実装ファイルに関係ないinterfaceとimplementationを追加

上記の対策をしてもうまくいかなかったため、ググってみたところ、どうやらcategoryを読み込まないバグがあるらしく、カテゴリの実装も、実装クラスとして見せかけることで回避できるそうです。


IMPORTANT: For 64-bit and iPhone OS applications, there is a linker
bug that prevents -ObjC from loading objects files from static
libraries that contain only categories and no classes. The workaround
is to use the -all_load or -force_load flags.
- 引用:http://groups.google.com/group/three20/msg/8d2044681ad58f13?pli=1

具体的には、以下のように関係ないクラスの宣言を.mの先頭の方に付加すればOK。「FIXCATEGORYBUG_NSSTRING_SAMPLE」は他と名前の衝突が無ければ何でもよいです。

  • NSString+Sample.m
@interface FIXCATEGORYBUG_NSSTRING_SAMPLE @end
@implementation FIXCATEGORYBUG_NSSTRING_SAMPLE @end

@implementation NSString (Sample)
 .
 .
 .
@end

staticライブラリを使う場合には、ここは結構なはまりどころかと思います。

ちなみに、staticライブラリを利用する側で、リンカフラグに「-all_load」を使うことで解決されているケースもありましたが、http://groups.google.com/group/three20/msg/8d2044681ad58f13?pli=1 でもあるように、libttoolのバグのためにduplicate symbolのエラーが発生するケースがあります。

このため、今のところは上記2つの対策が有効かと。