背景
iOS向けにSwiftで実装したフレームワークを、Xcodeで普通にコンパイル・インストールすると、出来上がったフレームワークにはiOS Simulator向けのバイナリ(すなわちx86_64バイナリ)が含まれません。
本ドキュメントでは、ARM用とx86用両方のバイナリを含んだ、ユニバーサルバイナリ形式のフレームワークの作成方法を紹介します。
作成日: 2016/09/22
更新日: 2016/12/04
参考文献
- How to build Cocoa Touch Framework for i386 and x86_64 architecture?: StackOverflowの記事です。アイテム17の解決方法を参考にしています
- iOS用Staticライブラリのビルドおよびインストール方法: Qiitaの私の過去記事です。Objective-Cの実装のstatic linkライブラリの作成方法であり、本記事とは対象が異なりますが、問題解決方法のアプローチは同じです。
開発環境
- IDE: Xcode version 8.0
- Target OS: iOS 10
- Language: Swift 3
課題の解決方法
アプローチは以下の通りです:
- ARM向け、およびx86向け各々のフレームワークを準備する
- 両方のファイルをマージする
- 特に、ライブラリ本体については、lipoコマンドで、ユニバーサルバイナリを生成します
以下、手順の詳細について説明します。
XcodeのBuild Setting
iOS向けのフレームワーク実装プロジェクト(言語はSwift)のBuild Settingにて、次を設定します。
カテゴリ | 項目名 | 設定値 | 説明 |
---|---|---|---|
Architectures | Valid architectures | arm64 armv7 armv7s i386 x86_64 |
シミュレータ用のi386, x86_64を追加します |
Deployment | Installation Directory | フレームワークのインストール先フォルダ名 | フレームワークのインストール先を指定します |
Deployment | Skip Install | NO | インストール処理可能にします |
Search Paths | Framework Search Paths | 参照するフレームワークのフォルダ | 別のフレームワークとリンクする場合に設定します |
Install処理の追加
Installターゲットの追加
Xcodeにフレームワークをインストールするためのターゲットを追加します。
- ターゲットの種類は、
Cross Platform
からExternal Build System
とします。 -
Build Phase
のTarget Dependences
には、インストールするフレームワークのビルドフェーズを指定してください。 -
Info
のExternal Build Tool ConfigurationのArgumentsには、-f <以下に示すMakefileのファイル名>
としてください。
install_ios.mk スクリプト
スクリプトの内容を以下に挙げます。同じ内容をgistのinstall_ios.mkに登録しています。
スクリプト中のPROJECT_NAME
とINSTALL_PATH
は拙作のCanary Frameworkの設定です。リポジトリのScript/install_ios.mk
で下記スクリプトファイルを使用しています。
#
# install_ios.mk
#
# Reference URL: http://stackoverflow.com/questions/28652650/how-to-build-cocoa-touch-framework-for-i386-and-x86-64-architecture
#
INSTALL_PATH ?= $(HOME)/local/Frameworks
OS_DIR = $(INSTALL_PATH)/iphoneos
SIM_DIR = $(INSTALL_PATH)/iphonesimulator
install: dummy
# Build framework for device
xcodebuild install -scheme $(PROJECT_NAME) \
-project $(PROJECT_NAME).xcodeproj \
-configuration Release \
-sdk iphoneos \
ONLY_ACTIVE_ARCH=NO DSTROOT=/ \
INSTALL_PATH=$(INSTALL_PATH)/iphoneos
# Build framework for simulator
xcodebuild install -scheme $(PROJECT_NAME) \
-project $(PROJECT_NAME).xcodeproj \
-configuration Release \
-sdk iphonesimulator \
ONLY_ACTIVE_ARCH=NO DSTROOT=/ \
INSTALL_PATH=$(INSTALL_PATH)/iphonesimulator
# Copy framework
(cd $(OS_DIR); tar cf - $(PROJECT_NAME).framework) \
| (cd $(INSTALL_PATH) ; tar xfv -)
(cd $(SIM_DIR)/$(PROJECT_NAME).framework/Modules ; \
tar cf - $(PROJECT_NAME).swiftmodule) \
| (cd $(INSTALL_PATH)/$(PROJECT_NAME).framework/Modules ; tar xfv -)
# Merge frameworks
lipo -create \
-output $(INSTALL_PATH)/$(PROJECT_NAME).framework/$(PROJECT_NAME) \
$(OS_DIR)/$(PROJECT_NAME).framework/$(PROJECT_NAME) \
$(SIM_DIR)/$(PROJECT_NAME).framework/$(PROJECT_NAME)
dummy: