Xcode

プログラミングで出逢った出来事

自作ライブラリを使った iOS アプリビルド時にリンクエラーが発生しました。

適切なバイナリがライブラリに含まれていなかったことが原因でした。

自作ライブラリのリンク時に Undefined symbols for architecture エラーが発生する。

Xcode 6 で Cocoa touch Framework が登場する前に作った自作の iOS フレームワークを使ってアプリをビルドしたときに、次のようなエラーメッセージが表示され、ビルドに失敗することがありました。

Undefined symbols for architecture arm64:

"_OBJC_CLASS_$_EzPhoneNumberSupport", referenced from:

objc-class-ref in EzRDARPhoneNumberCollectionView.o

objc-class-ref in EzRDARConfiguration.o

こういったエラーは実装がライブラリに含まれていない場合にありがちで、今回の場合ではEzRDARPhoneNumberCollectionViewクラス で参照しているEzPhoneNumberSupportクラス がライブラリに含まれていない、ということになりそうです。

ただ、ライブラリにはこのクラスが確かに含められていて不思議に思えたのですけど、その直前に次の警告が出力されていました。

Ignoring file /Users/tomohiro/Library/MyFrameworks/Debug/EzVoIP.framework/EzVoIP, missing required architecture arm64 in file /Users/tomohiro/Library/MyFrameworks/Debug/EzVoIP.framework/EzVoIP (2 slices)

これを見ると、なにやらライブラリの組み込みが無視されたということが伺えます。

具体的にはmissing required architecture arm64 のところで、おそらくarm64 用のバイナリが見つからなかったためにライブラリが無視されたということのようでした。

原因

原因は警告メッセージのとおりで、今回の場合はビルドされたライブラリに適切なバイナリが存在しなかったために発生したエラーでした。

ライブラリの場合は複数のバイナリをビルドしてまとめられたりするようですけど、デバッグビルドの時には効率優先で、現在のアーキテクチャーだけのバイナリを作るようにBuild Settings で設定されているようです。

Xcode 6 ではこれが推奨設定のため、プロジェクト設定を自動で調整してもらうと、この設定が有効になってビルドに失敗する場合もあります。

対処方法

対処方法は簡単で、Build SettingsArchitectures カテゴリにあるBuild Active Architecture Only で、Debug に設定されているYes をNo に変更します。

こうすることで、デバッグビルドのときにも全てのアーキテクチャーに対応したビルドを生成してくれるようになります。

特にiOS アプリの場合、シミュレーターと実機とではCPU のアーキテクチャーが異なるため、今回のようなバイナリの不一致が発生しやすいのかもしれませんね。