XCFramework は、iOS、macOS、tvOS、watchOS 向けのライブラリを1つのパッケージにまとめる Apple のバイナリ形式です。.framework を置き換え、シミュレータとデバイスの異なるアーキテクチャ向けにビルドする際の fat binary の問題を解消するために設計されました。Apple WWDC 2019 によると、XCFramework は複数のプラットフォームをサポートする SDK の配布における必須形式となり、ユニバーサルバイナリの旧来のアプローチを完全に置き換えました。
要点
XCFramework は、Apple が WWDC 2019 で発表したバイナリライブラリとフレームワークのパッケージ形式です。主な目的は、すべてのターゲットプラットフォームとアーキテクチャ向けのライブラリのコンパイル済みバージョンを含む単一のバンドルを作成することです。
XCFramework 以前は、開発者は lipo ユーティリティを介して複数のアーキテクチャを結合する fat binary を備えた .framework を使用していました。このアプローチには問題がありました。シミュレータ用にプロジェクトをビルドする際、fat binary にはシミュレータとデバイスの両方のアーキテクチャが含まれており、App Store にビルドを提出する際にエラーが発生していました。開発者は、不要なアーキテクチャを削除するために Run Script フェーズを記述する必要がありました。
Apple デベロッパードキュメント(2024)によると、XCFramework は Apple エコシステムのすべてのプラットフォーム(iOS、iPadOS、macOS、tvOS、watchOS、visionOS、Catalyst アプリケーション)をサポートしています。各プラットフォームはパッケージ内で個別のスライスを取得し、アーキテクチャの競合を排除して SDK 配布を簡素化します。
XCFramework は主に3つのシナリオで使用されます:サードパーティ開発者へのクローズド SDK の配布、Flutter および React Native 用のネイティブモジュールの配布、および事前コンパイルが必要なライブラリの公開。この形式は、Apple エコシステムで公開されるすべての新しい SDK に必須です。
開発者は、ソースコードを開示できない場合、ライブラリがプロプライエタリアルゴリズムを使用している場合、またはライセンス保護が必要な場合に XCFramework を選択します。ソースコードで動作する Swift Package Manager とは異なり、XCFramework は既にコンパイルされたバイナリファイルを配布します。
Fat binary の問題は、ユニバーサルバイナリが1つの Mach-O ファイルに複数のアーキテクチャを含んでいたことです。シミュレータ用にアプリをビルドする際、Xcode はデバイスの arm64 アーキテクチャとシミュレータの x86_64 アーキテクチャの両方を含めていました — App Store はデバイスアーキテクチャのみを受け付けていました。
従来の解決策は、最終ビルドからシミュレータアーキテクチャを削除するために lipo を呼び出す Run Script フェーズを追加することでした。このアプローチは脆弱で、Xcode のアップデートや新しいアーキテクチャ(Apple Silicon 上のシミュレータ向け arm64 など)の登場で壊れていました。
Swift.org(2023)によると、Swift Package Manager チームは当初、バイナリ依存関係をサポートしようとした際にこの問題に直面しました。XCFramework は形式レベルでこれを解決しました。各スライスは、ターゲットプラットフォームとアーキテクチャを記述する Info.plist を持つ個別のフォルダです。Xcode はビルド時に自動的に必要なスライスを選択し、後処理を必要としません。
XCFramework の各スライスには、プラットフォームとアーキテクチャの1つの組み合わせのみが含まれます。例えば、ios-arm64 には iOS デバイス用のバイナリのみが含まれ、ios-x86_64-simulator には Intel Mac シミュレータ用のみが含まれます。Xcode は自動的に正しいスライスを選択し、アーキテクチャ削除スクリプトの必要性を排除し、ビルドエラーのリスクを低減します。
ios-arm64-x86_64-simulator スライスは Apple Silicon Mac をサポートするために導入されました。以前は、シミュレータには arm64(Apple Silicon)と x86_64(Intel)の個別のバイナリが必要でした。XCFramework は単一のシミュレータスライス内で fat binary を許可しています — これが fat binary が正当化される唯一の例外です。
XCFramework パッケージは .xcframework 拡張子を持つディレクトリで、最上位に Info.plist とバイナリスライスを含むフォルダがあります。各スライスには特定のプラットフォーム向けの .framework または .a ライブラリが含まれます。
MyLibrary.xcframework/
Info.plist
ios-arm64/
MyLibrary.framework/
Info.plist
MyLibrary
ios-x86_64-simulator/
MyLibrary.framework/
Info.plist
MyLibrary
macos-arm64-x86_64/
MyLibrary.framework/
Info.plist
MyLibrary
パッケージの Info.plist には AvailableLibraries キーが含まれており、各スライスの LibraryIdentifier、LibraryPath、SupportedPlatform を列挙します。Xcode はプロジェクトに XCFramework を追加する際にこのファイルを読み取り、検索パスと Embed Frameworks フェーズを自動的に構成します。
各スライスは、独自の Info.plist を持つ完全な .framework または静的ライブラリです。これにより、XCFramework は混合タイプ(一部のプラットフォームでは静的ライブラリ、他のプラットフォームでは動的フレームワーク)をサポートできますが、実際にはすべてのスライスに1つのタイプが使用されます。
XCFramework の作成は xcodebuild -create-xcframework を介して行われます。このコマンドは、各プラットフォーム用に既にビルドされた .framework または .a ライブラリを入力として受け取り、それらを1つのパッケージに結合します。
プロセスは2つのステップで構成されます:最初に各ターゲットプラットフォーム用のバイナリがビルドされ、次にそれらが XCFramework にパッケージ化されます。ビルドには標準の Xcode destination フラグが使用されます。
# Step 1: build frameworks for each platform
xcodebuild archive -scheme MyLibrary -destination "generic/platform=iOS Simulator"
xcodebuild archive -scheme MyLibrary -destination "generic/platform=iOS"
xcodebuild archive -scheme MyLibrary -destination "generic/platform=macOS"
# Step 2: create XCFramework
xcodebuild -create-xcframework -framework ./iOS/MyLibrary.framework -framework ./iOSSim/MyLibrary.framework -framework ./macOS/MyLibrary.framework -output ./MyLibrary.xcframework
-create-xcframework フラグは Xcode 11 で導入されました。このコマンドは自動的に正しいディレクトリ構造を作成し、すべてのプラットフォームの説明を含む Info.plist を生成します。.framework のいずれかが破損しているか、誤ったアーキテクチャでビルドされている場合、xcodebuild は検証段階でエラーを出力します。
CI/CD では、すべてのプラットフォームのビルドと XCFramework の作成を自動化する シェルスクリプト が使用されます。一般的なアプローチは、パラメータ化された scheme と出力パスを持つ Makefile または Fastlane lane の形のラッパーです。
# build_xcframework.sh - automation script
set -e
SCHEME="MyLibrary"
OUTPUT="./build"
xcodebuild archive -scheme "$SCHEME" -sdk iphonesimulator -archivePath "$OUTPUT/sim.xcarchive"
xcodebuild archive -scheme "$SCHEME" -sdk iphoneos -archivePath "$OUTPUT/dev.xcarchive"
xcodebuild -create-xcframework -framework "$OUTPUT/dev.xcarchive/Products/Library/Frameworks/MyLibrary.framework" -framework "$OUTPUT/sim.xcarchive/Products/Library/Frameworks/MyLibrary.framework" -output "$OUTPUT/MyLibrary.xcframework"
このようなスクリプトは、テスト通過後に CI パイプライン(GitHub Actions、Bitrise、Jenkins)で実行されます。生成された XCFramework はアーカイブされ、リリースアーティファクトとしてアップロードされるか、pod spec を介して CocoaPods などの依存関係マネージャを通じて公開されます。
XCFramework を Xcode プロジェクトに統合するには、検索パスの手動設定は必要ありません。ターゲットの General 設定で .xcframework を Frameworks, Libraries, and Embedded Content セクションにドラッグするだけです。
.framework とは異なり、XCFramework はシミュレータアーキテクチャを削除するための Run Script フェーズを追加する必要がありません。Xcode は自動的に利用可能なスライスを判別し、現在のビルドスキームに必要なものだけを含めます。物理デバイスには ios-arm64 スライスが使用され、シミュレータには ios-arm64-x86_64-simulator または ios-x86_64-simulator が使用されます。
import MyLibrary
func processData() {
// XCFramework resolves the correct slice at build time
let processor = DataProcessor()
let result = processor.analyze(input: "sample")
print(result)
}
CocoaPods の場合、統合は vendored_frameworks とサポートされるプラットフォームのリストを指定した podspec を介して行われます。依存関係マネージャは、プロジェクトに必要なスライスを自動的に判別します。Firebase、Adjust、AppsFlyer などの多くの商用 SDK は、インストールを簡素化するために XCFramework に移行しています。
Swift Package Manager と XCFramework は競合するものではなく、互いに補完し合います。SPM はソースコードで動作し、プロジェクトのビルドごとに依存関係をコンパイルします。XCFramework は、消費者側でのコンパイルを必要とせずに、既製のバイナリを提供します。
Swift Package Manager 5.3 のリリースにより、Apple は バイナリ依存関係 のサポートを追加しました — これで SPM はリモート依存関係として XCFramework をダウンロードできます。Package.swift はバイナリアーティファクトの URL と検証用のチェックサムを指定します。
Swift Package Manager のドキュメント(2024)によると、バイナリ依存関係はソースコードを開示しない SDK や、ビルド時間が不釣り合いに長いライブラリに推奨されます。オープンソースプロジェクトの場合は、SPM を介したソースコード配布が推奨されます。
| 基準 | XCFramework | Swift Package Manager |
|---|---|---|
| 形式 | バイナリ(.xcframework) | ソースコード |
| コード保護 | 完全 | なし |
| ビルド時間 | 最小(コピー) | コード量に依存 |
| プラットフォーム柔軟性 | すべての Apple プラットフォーム | Package.swift に依存 |
| 統合 | ドラッグ&ドロップまたは SPM | Package.swift |
よくある質問
.framework は、デバイスとシミュレータのアーキテクチャを含む fat binary を備えたレガシー形式です。XCFramework は各スライスを個別に保存し、ビルド中のアーキテクチャ競合を排除します。Apple はすべての新しいプロジェクトと既存プロジェクトの移行に XCFramework を推奨しています。
CocoaPods はバージョン 1.9 以降 XCFramework をサポートしています。podspec で spec.vendored_frameworks と spec.static_framework を指定するだけで十分です。マネージャは、プロジェクトのプラットフォームで利用可能なスライスを考慮して、自動的に依存関係を解決します。
Apple は .framework のサポートを削除していませんが、新しい SDK には専ら XCFramework を推奨しています。古い形式の fat binary でアプリを App Store に提出すると、シミュレータアーキテクチャが原因で Invalid Bundle エラーが発生する可能性があり、XCFramework が実用的な necessity となっています。
Swift 5.3 以降、SPM のバイナリ依存関係は XCFramework を使用します。Package.swift はバイナリパッケージの url と checksum を指定します。SPM はダウンロードし、整合性を検証し、ソースコードをコンパイルせずに XCFramework をシステム依存関係として接続します。
visionOS は Xcode 15 以降 XCFramework でサポートされています。WWDC 2023 で Apple は、この形式が Apple Vision Pro 向けに拡張されたことを確認しました。visionOS のスライスは SupportedPlatform = xros で、arm64 アーキテクチャを含みます。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。