スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

Xcode 4におけるiOS Frameworkの作成方法

Mac OS XではFrameworkを作成することが出来ます。
そもそもMac OS XにおけるFrameworkとは何かというと、簡単にいえば「ヘッダやリソースなどをひとまとめにし、複数のバージョンを保持することが出来るライブラリ」といったところです。

システム内において複数のアプリケーションが共有して利用できる機能をライブラリ化しておくことで、各アプリケーションがその処理を個別に実装することなく、単にそのライブラリをロードして利用するだけでよくなるというのが大きな利点でしょう。

そのため、iOSのようにシステムに自作ライブラリを追加できないOSではあまり意味が無いように思われるのですが、このFrameworkという仕組みを利用すると、ヘッダファイルやリソースを一気にまとめることが出来るので、結果的にライブラリの管理がしやすくなりますし、Xcodeプロジェクトへのインポートもこのフレームワークを1つインポートするだけでヘッダもライブラリも参照できるようになるので非常に便利です。

じゃあiOSの開発でもこれをつくろう!
と思ったのですが、いかんせんこのFrameworkの作成は上記の理由のとおり、Mac OS Xのみで推奨されていることなので、iOS向けに作成する手段をXcodeが用意していません。Xcodeで用意しているのは、Static Library(*.aファイル)の作成のみです。


となれば、自作しかありません。
1つずつポイントを抑えながら作り方を紹介していきます。


01. そもそもFrameworkとはどういうファイルなのか

Frameworkというのは実は特殊なファイル形式で1つにまとまっているわけではなく、Static Libraryやヘッダファイルを決まった形式のディレクトリ内に配置したただのディレクトリです。なので、このディレクトリにiOSで使えるStatic Library(*.aファイル)とヘッダ、リソースを配置してしまえばいいだけの話なのです。

ここまで聞くと、意外に簡単な仕組みであることが判るかと思います。
Frameworkを構成するディレクトリ名を「XXXX.framework」というディレクトリ名にしておき、その中は以下の画像のようなディレクトリ構成を作ります。
これを Framework Bundle と呼びます。
(詳細はApple公式のFramework Programming Guideを参照のこと)

Framework Bundle


02. 実機とシミュレータではアーキテクチャーが異なるためユニバーサル化が必要

iOS向けにFramework作成をXcodeがサポートしていないもう1つの理由がこれです。Mac OS X上でシミュレータでアプリを開発しているときは、i386という32bitインテルCPU上で動作します。一方、iPhone端末上ではARMとよばれるCPU上で動作します。これらは互換性のあるCPUではないため、当然ライブラリの形式も異なります。そうなると、実機向けに作成したライブラリはシミュレータ上では動かせないですし、シミュレータ向けに作成したライブラリは実機上で動かせないのです。

わざわざ切り替えて利用することも出来ないことはないですが、非常に手間のかかる作業になります。これでは、かえって開発効率の低下を招きかねません。

ではどうすればいいのかということですが、Macではこれを解消する「ユニバーサル化」という仕組みを用意しています。ユニバーサル化とは何かというと、異なるアーキテクチャーごとにビルドしたライブラリを1つのライブラリとしてまとめて利用出来るようにする仕組みです。

こうすることで、ファイルは1つだけ用意すればいいことになるので、実機上でもシミュレータ上でも動作するライブラリが完成します。その分、ファイルサイズは上昇してしまいますが、気にするほどではないでしょう。


肝心のユニバーサル化については、「lipo」コマンドで行うことが出来、以下の形式で記述します。

lipo (実機向けライブラリファイル名) (シミュレータ向けライブラリファイル名) -create -output (結合後のライブラリファイル名)


※このコマンドは後述のビルドスクリプト作成時に利用します


03. iOS向けFramework作成のためのXcodeプロジェクトの作り方

前提知識としてはここまでです。
あとは実際に作ってみたいと思います。


03-01. 以下のようにStatic Libraryプロジェクトとして作成します。

Xcode Framework 01


03-02. ターゲットの「Valid Architechtures」に「i386」を追加します

Xcode Framework 02


03-03. Packagingの「Public Headers Folder Path」の項目を「/Headers」に変更します

Xcode Framework 03


03-04. プロジェクトに「Resources」という名前でグループを作成し、その中に「Info.plist」を作成します。内容は以下を参考にしてください

Xcode Framework 04


03-05. TARGETSの下にある「Add Target」ボタンを選択し、「iOS」→「Other」→「Aggregate」を選択して「Next」ボタンを押下する。次の画面で表示されるProduct Nameは「TestFramework-Universal」といったような名前にしておく

Xcode Framework 05


03-06. すると、以下のようにターゲット「TestFramework-Universal」が追加される。ここで、その追加したターゲットの「Build Phases」を選択する

Xcode Framework 06


03-07. 「Build Phases」を選択すると、以下のように「Target Dependencies」以外何もない画面が出てくる。ここで、右下にある「Add Build Phase」→「Add Run Script」を選択する

Xcode Framework 07


03-08. すると、以下のように「Run Script」という項目が追加される

Xcode Framework 08


03-09. あとは「Shell」の部分にビルド用のスクリプトを記述する。スクリプトは以下の内容を記述する。(TestFrameworkの部分は最初から作成されているStatic Libraryのターゲットの名前を指定する)


# Environment Variables
FRAMEWORK_NAME=${PROJECT_NAME}
FRAMEWORK_VERSION=A
FRAMEWORK_VERSION_NUMBER=1.0
FRAMEWORK_BUILD_PATH="${SRCROOT}/build/${CONFIGURATION}-framework"
FRAMEWORK_DIR="${FRAMEWORK_BUILD_PATH}/${FRAMEWORK_NAME}.framework"
FRAMEWORK_PACKAGE_NAME="${FRAMEWORK_NAME}.${FRAMEWORK_VERSION_NUMBER}.zip"

# Clean directories
rm -rf "${FRAMEWORK_BUILD_PATH}"

# Build simulator and device binaries.
xcodebuild -project ${PROJECT_NAME}.xcodeproj -sdk iphonesimulator${IPHONEOS_DEPLOYMENT_TARGET} -target "TestFramework" -configuration ${CONFIGURATION} clean build
xcodebuild -project ${PROJECT_NAME}.xcodeproj -sdk iphoneos${IPHONEOS_DEPLOYMENT_TARGET} -target "TestFramework" -configuration ${CONFIGURATION} clean build

# create framework directories.
mkdir -p ${FRAMEWORK_DIR}
mkdir -p ${FRAMEWORK_DIR}/Versions
mkdir -p ${FRAMEWORK_DIR}/Versions/${FRAMEWORK_VERSION}
mkdir -p ${FRAMEWORK_DIR}/Versions/${FRAMEWORK_VERSION}/Resources
mkdir -p ${FRAMEWORK_DIR}/Versions/${FRAMEWORK_VERSION}/Headers

# create symlinks
ln -s ${FRAMEWORK_DIR}/Versions/${FRAMEWORK_VERSION} ${FRAMEWORK_DIR}/Versions/Current
ln -s ${FRAMEWORK_DIR}/Versions/Current/Headers ${FRAMEWORK_DIR}/Headers
ln -s ${FRAMEWORK_DIR}/Versions/Current/Resources ${FRAMEWORK_DIR}/Resources
ln -s ${FRAMEWORK_DIR}/Versions/Current/${FRAMEWORK_NAME} ${FRAMEWORK_DIR}/${FRAMEWORK_NAME}

# create the universal library
lipo ${SRCROOT}/build/${CONFIGURATION}-iphoneos/lib${FRAMEWORK_NAME}.a ${SRCROOT}/build/${CONFIGURATION}-iphonesimulator/lib${FRAMEWORK_NAME}.a -create -output "${FRAMEWORK_DIR}/Versions/Current/${FRAMEWORK_NAME}"

# copy files
cp ${SRCROOT}/build/${CONFIGURATION}-iphoneos/Headers/*.h ${FRAMEWORK_DIR}/Headers/
cp Info.plist ${FRAMEWORK_DIR}/Resources

# zip (配布用に TestFramework.framework ディレクトリをZIP圧縮するだけなので、配布しないなら以下はコメントアウトしてもよい)
cd ${FRAMEWORK_BUILD_PATH}
zip -ry ${FRAMEWORK_PACKAGE_NAME} $(basename $FRAMEWORK_DIR)



03-10. これでビルドできるようになったので、スキーマから「TestFramework-Universal」を選択し、ビルドを行えばFramework Bundleが作成される。ビルドを行うと、Xcodeのプロジェクトファイル(*.xcodeproj)の置いているディレクトリに「build」という名前のディレクトリが作成され、このディレクトリ内の「Debug-framework」ディレクトリ内に、「TestFramework.framework」というディレクトリが作成されている。これがFrameworkである。試しに、他のプロジェクトでこの「TestFramework.framework」ディレクトリをFrameworkとして追加できるかどうか試してみるとよい。上手くいけば、以下のようにFrameworkとして追加することが出来る

Xcode Framework 09




以上が、Xcode4におけるiOS向けFrameworkの作成方法になります。Frameworkはライブラリとして利用する場合も然ることなが、管理面や配布面でも非常に便利な形式ですので是非とも活用していきましょう。
スポンサーサイト

コメントの投稿

非公開コメント

プロフィール

Author:Kou
モバイル関連の開発ばかりやってる人のブログです。たまにWebもやります。

最新記事
最新コメント
最新トラックバック
月別アーカイブ
カテゴリ
検索フォーム
RSSリンクの表示
リンク
ブロとも申請フォーム

この人とブロともになる

QRコード
QR
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。