読者です 読者をやめる 読者になる 読者になる

やらなイカ?

たぶん、iOS/Androidアプリの開発・テスト関係。

複数のTarget/Configurationを持つiOSプロジェクトの構成Tips

以前"iOS勉強会議"で少しお話した内容ですが、新しいプロジェクトを整備するタイミングがあったので、ようやくまとめてみました。

例えば、

  • クイズアプリでコンテンツの異なるものを別アプリとしてビルド、リリースしたい
  • サーバと通信するアプリで、テスト用に接続先を切り替えたい

といった要件の実現方法です。

TargetとConfiguration

Xcodeのビルド設定には、Target, Configuration, そしてXcode4から加わったSchemeがあります。それぞれ、以下の用途で使い分けるものとします。

  • Target: 例えばクイズアプリでコンテンツの異なるもの、Lite版など。別アプリとしてリリースするもの。
  • Configuration: 接続先サーバの違い(開発サーバ/ステージング/本番)、デバッグ版/リリース版など。
  • Scheme: TargetをXcodeで実行するときの設定で、Build, Run, Test, Profile, Analyze, Archiveの5つに固定されています。それぞれにConfigurationを1つだけ関連付けします。

つまり、ビルド設定は Target x Configurationの数だけ存在します。SchemaはXcode上でビルド等実行する場合の"つなぎ役"です。

xcconfigファイル

ビルド設定はxcodeprojのエディタで変更できますが、TargetとConfigrationの数が増えてくると管理しきれなくなります。
xcconfigファイルは、ビルド設定のうち必要なものだけをテキストファイルで記述できる仕組みで、"New File..."からひな形を作成できます。
f:id:nowsprinting:20121118022524p:plain

作成したxcconfgは、プロジェクトの"Info"タグ下にある"Configuration"で、各Configurationに関連付けます。
f:id:nowsprinting:20121118022912p:plain

この状態でプロジェクト設定のエディタを開くと、xcconfigに設定した内容が(Boldでないフォントで)設定されているのがわかります。
f:id:nowsprinting:20121118023921p:plain
この例ではDebug.xcconfigに、

INFOPLIST_FILE = byXcconfigFile-Info.plist

と記述しています。

xcconfigの内容はデフォルト値として使用され、xcodeprojのエディタで値を個別に上書きすることもできます。上書きしたものはBoldフォントで表示されます。
尚、xcconfigに記述するキーと値は、xcodeprojのエディタで[cmd]+[c] → xcconfigファイルで[cmd]+[p]でコピペできます。

いくつか例を挙げます。

//GCC4.2 Preprocess
GCC_PREPROCESSOR_DEFINITIONS = ${TARGET_NAME} DEBUG

//GCC4.2 Language
GCC_PREFIX_HEADER = ${TARGET_NAME}/${TARGET_NAME}-${CONFIGURATION}-Prefix.pch

//Use Frameworks
FRAMEWORK_SEARCH_PATHS = $(inherited) $(SYSTEM_APPS_DIR)/Xcode.app/Contents/Developer/Library/Frameworks/ $(SRCROOT)/oss_frameworks/

//Use C++ Libraries
LIBRARY_SEARCH_PATHS = $(inherited) $(SRCROOT)/oss/cURL $(SRCROOT)/oss/OpenSSL $(SRCROOT)/oss/OCMock_iOS
OTHER_CPLUSPLUSFLAGS = $(OTHER_CFLAGS) -I$(SRCROOT)/oss/cURL/Headers -I$(SRCROOT)/oss/OpenSSL/Headers

ポイントをいくつか。

INFOPLIST_FILE

Info.plistファイルは、Targetごとにバージョンを分けたければ使い分け、統一でよければ一本化してもいいはずです。その場合、アプリの表示名(CFBundleDisplayName)はInfoPlist.stringsに定義し、これをTargetごとに作成します。

GCC_PREFIX_HEADER

上例ではTarget x Configurationごとにpch(pre-compiled header)ファイルを定義しています。これでTargetごとに振る舞いが違う部分の制御や、接続先サーバのURIを定義をpchファイルに定義することができます。

その他のオススメ

デバッグ用に"DEBUG"、リリース用にassertを無効化する"NDEBUG"は入れておいたほうがよいでしょう。
また上にも載せていますが、スタティックライブラリ関係は設定漏れを防ぐためにも記述を一箇所に固めておくことをおすすめします。

ビルドスクリプト

複数のビルドをひとつづつGUIで作るのは大変ですしオペミスもでますので、コマンドラインツールの"xcodebuild"を呼び出すスクリプトを組んでおくと便利です。
ビルドしてipa/zipファイルに固めたりするついでにビルドバージョンをインクリメントしたりcopyrightの年表示(に使えるplist)を更新したりもするスクリプトをgithubに置いておきましたので参考にしてください。