Help us understand the problem. What is going on with this article?

xcframeworkを作成する(第1回)

GMOアドマーケティングのT.Oです。

Xcode11でフレームワークの新しい配布形態としてxcframeworkが導入されました。
xcframeworkを使用すると、iOS実機、iOSシミュレーターなどの複数のプラットフォーム用のフレームワークを1つにまとめることができます。またアプリに組み込む際には、それぞれのプラットフォームを意識することなく利用できるようになりました1
ここではSwiftでxcframerworkを作成、利用する手順についてご紹介します。

●前提
作成するxcframeworkは、iOS10以降で利用可能なEmbedded Frameworkをまとめたものとします。
(iOS13, iPadOSにも対応しています)
開発環境としてXcode 11.0を利用しSwift5を使用します。

●xcframeworkの作成手順
1. プロジェクト作成
2. xcframework生成のためのビルド設定
3. Objective-C対応
4. テスト用のアプリ作成

今回は上記の手順のうちの
「1. プロジェクト作成」
「2. xcframework生成のためのビルド設定」
についてまとめます。

1.プロジェクト作成

まずフレームワーク用のテンプレートを選択してプロジェクトを作成します。
Xcodeで「File→New→Project..」メニューを選び、テンプレートの選択画面で「Cocoa Touch Framework」を選択します。
xcframework_p1.png

新規プロジェクトのオプション選択画面が表示されるので、Product Nameなどの設定を行います。
xcframework_p2.png
iOS10以降で利用可能としたいので、PROJECTのDeployment→iOS Deployment Targetで"iOS10.0"を選択します。
xcframework_p2-2.png
xcframeworkを作成するため、Build Options→Build Libraries for DistributionでYesを選択します。
xcframework_p3.png
次に「New File」を選択し、テンプレート選択画面で「Cocoa Touch Class」を選び
フレームワークの処理をSwiftで記述します。

ここでは以下のように文字をコンソール出力することにします。

Ore.swift
import UIKit

public class Ore: NSObject {
    public func oreMethod(){
        print("Hello Ore XCFramework");
    }
}

ビルドターゲットをフレームワーク(この例だとOreXCFramework)に変更します。Product→Buildを選択しビルドします。ビルドエラーがないことを確認します。

2.xcframeworkのためのビルド設定

iOS実機、iOSシミュレータ用のフレームワークをビルドして1つのxcframeworkにまとめるためのビルド設定を行います。

「File→New→Target」で新規ターゲットのテンプレート選択画面で「Cross-platform→Aggregate」を選びます。
xcframework_p4.png
Product Nameを指定します。ここでは例として"Aggregate"と指定します。
xcframework_p5.png
次にTARGETSから作成した"Aggregate"を選択した状態で「Build Phases」を選び、「+」を選択して「New Run Script」を選びます。
xcframework_p6.png
Run Scriptが作成されます。
xcframework_p7.png

Run Scriptの"#Type a script or drag file from your workspace to insert its path"と記述されている部分に以下のxcframework出力用スクリプトを貼り付けます。
このスクリプトを実行するとフレームワークのプロジェクト以下にOutputディレクトリを作成します。そしてOutputディレクトリ以下にxcframework作成のための中間ファイル、archiveファイル、xcframeworkを出力します。

# 出力先ディレクトリ(プロジェクトの直下)
OUTPUT_DIR=${PROJECT_DIR}/Output

# 中間ファイルの出力先ディレクトリ
DERIVED_DIR=${OUTPUT_DIR}/${CONFIGURATION}-derived

# archiveの出力先ディレクトリ
ARCHIVE_DIR=${OUTPUT_DIR}/${CONFIGURATION}-archive

# xcframeworkの出力先ディレクトリ
XCFRAMEWORK_DIR=${OUTPUT_DIR}/${CONFIGURATION}-xcframework

# 出力先ディレクトリ削除
rm -rf ${OUTPUT_DIR}

# 中間ファイルの出力先ディレクトリ作成
mkdir -p ${DERIVED_DIR}

# アーカイブファイルの出力先ディレクトリ作成
mkdir -p ${ARCHIVE_DIR}

# xcframeworkの出力先ディレクトリ作成
mkdir -p ${XCFRAMEWORK_DIR}

# iOS実機用のarchiveファイル
ARCHIVE_FILE_IOS=${ARCHIVE_DIR}/ios.xcarchive
echo "ARCHIVE_FILE_IOS:${ARCHIVE_FILE_IOS}"

# iOSシミュレータ用のarchiveファイル
ARCHIVE_FILE_IOS_SIMULATOR=${ARCHIVE_DIR}/iossimulator.xcarchive
echo "ARCHIVE_FILE_IOS_SIMULATOR:${ARCHIVE_FILE_IOS_SIMULATOR}"

# iOS実機用のarchiveファイル作成
xcodebuild archive -scheme ${PROJECT_NAME} -destination="iOS" -archivePath $ARCHIVE_FILE_IOS -derivedDataPath $DERIVED_DIR -sdk iphoneos SKIP_INSTALL=NO BUILD_LIBRARY_FOR_DISTRIBUTION=YES

# iOSシミュレータ用のarchiveファイル作成
xcodebuild archive -scheme ${PROJECT_NAME} -destination="iOS Simulator" -archivePath $ARCHIVE_FILE_IOS_SIMULATOR -derivedDataPath $DERIVED_DIR -sdk iphonesimulator SKIP_INSTALL=NO BUILD_LIBRARY_FOR_DISTRIBUTION=YES

# xcframework作成
xcodebuild -create-xcframework -framework $ARCHIVE_FILE_IOS/Products/Library/Frameworks/${PROJECT_NAME}.framework -framework $ARCHIVE_FILE_IOS_SIMULATOR/Products/Library/Frameworks/${PROJECT_NAME}.framework -output $XCFRAMEWORK_DIR/${PROJECT_NAME}.xcframework

# xcframeworkの出力ディレクトリをFinderで開く
open ${XCFRAMEWORK_DIR}

ビルドターゲットをAggregateに変更します。そしてProductメニュから→Buildを選択して
ビルドします。
xcframework_p8.png
ビルドが成功したら生成されたxcframeworkをFinderやtreeコマンドなどで確認します。
実機用フレームワーク(ios-armv7_arm64以下)とシミュレータ用フレームワーク(ios-i386_x86_64-simulator以下)が両方とも含まれている状態になっていればここまでの手順は完了です。

%tree OreXCFramework.xcframework
OreXCFramework.xcframework
├── Info.plist
├── ios-armv7_arm64
│   └── OreXCFramework.framework
│       ├── Headers
│       │   ├── OreXCFramework-Swift.h
│       │   └── OreXCFramework.h
│       ├── Info.plist
│       ├── Modules
│       │   ├── OreXCFramework.swiftmodule
│       │   │   ├── arm.swiftdoc
│       │   │   ├── arm.swiftinterface
│       │   │   ├── arm64-apple-ios.swiftdoc
│       │   │   ├── arm64-apple-ios.swiftinterface
│       │   │   ├── arm64.swiftdoc
│       │   │   ├── arm64.swiftinterface
│       │   │   ├── armv7-apple-ios.swiftdoc
│       │   │   ├── armv7-apple-ios.swiftinterface
│       │   │   ├── armv7.swiftdoc
│       │   │   └── armv7.swiftinterface
│       │   └── module.modulemap
│       ├── OreXCFramework
│       └── _CodeSignature
│           └── CodeResources
└── ios-i386_x86_64-simulator
    └── OreXCFramework.framework
        ├── Headers
        │   ├── OreXCFramework-Swift.h
        │   └── OreXCFramework.h
        ├── Info.plist
        ├── Modules
        │   ├── OreXCFramework.swiftmodule
        │   │   ├── i386-apple-ios-simulator.swiftdoc
        │   │   ├── i386-apple-ios-simulator.swiftinterface
        │   │   ├── i386.swiftdoc
        │   │   ├── i386.swiftinterface
        │   │   ├── x86_64-apple-ios-simulator.swiftdoc
        │   │   ├── x86_64-apple-ios-simulator.swiftinterface
        │   │   ├── x86_64.swiftdoc
        │   │   └── x86_64.swiftinterface
        │   └── module.modulemap
        ├── OreXCFramework
        └── _CodeSignature
            └── CodeResources

参考

執筆にあたり以下を参考にさせていただきました。
Binary Frameworks in Swift - WWDC 2019 - Videos - Apple Developer
いけだや技術ノート Xcode 11で導入されるxcframeworkのディレクトリ構造

明日は、xcframeworkを作成する(第2回)です。
引き続き、GMOアドマーケティング Advent Calendar 2019をお楽しみください!


  1. Xcode10までは、各プラットフォーム用のフレームワークを1つのファイルにまとめることはできていたのですが、それをアプリで利用する際に必要なプラットフォームに適合したフレームワークのみを切り出すためのスクリプトを実行する必要があり、手順がやや煩雑になっていました。 

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした