XCFrameworkとは何か?新しいマルチプラットフォーム対応フレームワーク形式の概要と基本を解説

目次
- 1 XCFrameworkとは何か?新しいマルチプラットフォーム対応フレームワーク形式の概要と基本を解説
- 2 XCFramework対応のメリット・利点:マルチプラットフォーム開発における優位性をさらに詳しく解説
- 3 XCFramework対応の理由:なぜ従来フレームワークからXCFrameworkへの移行が必要なのか
- 3.1 新CPUアーキテクチャ(ARM Macなど)への対応が必要になった背景:従来方式ではM1チップへの対応が困難だった
- 3.2 Fatバイナリによる旧方式の限界とApp Storeの制約:非公式なFatフレームワークはApp Store審査で拒否される可能性
- 3.3 シミュレーターコード混入による不具合の排除:デバイス用バイナリに誤ってシミュレータコードを含めない仕組み
- 3.4 複数プラットフォーム開発の一般化と需要増:1つのSDKでiOS・macOSなどを同時サポートするニーズ
- 3.5 Appleの推奨による新標準への移行プレッシャー:公式ドキュメントやWWDCでXCFramework対応が促進
- 4 XCFrameworkの作成方法:Xcodeを用いたマルチプラットフォーム向けビルドとアーカイブ手順を詳しく解説
- 4.1 それぞれのプラットフォーム向けFrameworkをビルドする手順:iOSデバイス用とSimulator用に個別ビルド
- 4.2 XcodeでのArchiveと.xcarchiveの作成:GUIを使ったFrameworkバイナリ書き出し
- 4.3 xcodebuild -create-xcframeworkコマンドの使用方法:複数プラットフォームのビルド成果物を一括パッケージ化
- 4.4 Build設定のポイント:BUILD_LIBRARY_FOR_DISTRIBUTION有効化など将来のSwift互換性を確保する設定
- 4.5 生成されたXCFrameworkの内容確認と検証:Info.plistで含まれるプラットフォームとアーキテクチャを確認
- 5 XCFramework配布の注意点:効率的な配布方法とバージョン管理のポイント
- 5.1 CocoaPodsやCarthageでのXCFramework取り扱い方法と注意点:vendored framework指定や –use-xcframeworksオプションなど
- 5.2 SwiftPMバイナリパッケージとして配布する際のポイント:Package.swiftでのbinaryTarget定義とホスティング方法
- 5.3 バージョン管理と互換性維持のためのベストプラクティス:セマンティックバージョニングと複数バージョン並行提供
- 5.4 コード署名とセキュリティ:XCFramework配布時の開発元署名とApple Notarizationの考慮
- 5.5 配布アーカイブ構成:dSYMシンボルやライセンスファイルの同梱とその扱い
- 6 Swift Package Managerとの連携:XCFrameworkをSwiftPMで配布・統合する方法
- 6.1 XCFrameworkをSwiftPMで利用するメリット:依存管理の統一とCIキャッシュ活用によるビルド時間短縮
- 6.2 Swift PackageのbinaryTarget設定方法:Package.swiftでXCFrameworkのリモートURLとchecksumを指定
- 6.3 XCFrameworkをZIP圧縮しリモート配布する手順:アーティファクトバンドルとしてホスティングする方法
- 6.4 Package.swift内でのchecksum算出と検証プロセス:XCFramework更新時に必要なハッシュの更新方法
- 6.5 SwiftPM利用時の制限事項:binary targetの他パッケージ依存不可などの注意点
- 7 XCFramework生成時によくあるエラー・トラブルへの対応策:原因と解決方法を網羅的に解説【完全ガイド】
- 7.1 バイナリに含めるアーキテクチャ不足/過剰エラーへの対処:missing required architectureエラーの原因究明と解決
- 7.2 Swiftモジュール不適合エラーへの対処:BUILD_LIBRARY_FOR_DISTRIBUTION未設定によるModule Incompatibleエラーを解消
- 7.3 シンボルが見つからない/重複するエラーへの対処:Undefined symbolsやduplicate symbolエラーの原因と対策
- 7.4 シミュレータとデバイスのバイナリ混在によるエラーの回避:XCFramework作成時にSimulatorコードをAppに含めない対策
- 7.5 コード署名や権利設定の不備による実行時エラーの対策:署名エラーやNotarization未実施による問題の回避
- 7.6 Xcode/Swiftバージョン差異による互換性問題への対処:新旧コンパイラ間のABI不一致への対応策
- 8 XCFrameworkと従来Framework(Universal Framework)の違い:互換性・構造・サポート範囲の比較
- 9 Objective-CやC++ライブラリのXCFramework化:既存コードをXCFrameworkに対応させる方法
- 9.1 Objective-C/C++製ライブラリをFramework化する手順と注意点:既存プロジェクトからフレームワークターゲットを作成する方法
- 9.2 Staticライブラリ(.a)+ヘッダをXCFrameworkに含める方法:.aファイルとHeadersフォルダのパッケージング
- 9.3 Modulemapの作成と公開ヘッダ設定:Swiftから利用可能にするためのmodule.modulemap作成方法
- 9.4 Swiftとのブリッジング:Objective-Cヘッダを介したSwiftからの呼び出しと必要な設定
- 9.5 C++コードの互換性とビルド設定:libc++標準ライブラリのリンク設定やextern “C”の考慮
- 10 プラットフォームごとの対応方法(iOS、macOS など):各OS向けXCFramework構築のポイントを解説
- 10.1 iOSデバイスとiOS Simulator向けXCFramework構築時のポイント:アーキテクチャ(arm64/x86_64)別にビルドし同梱
- 10.2 macOS向けXCFramework構築時のポイント(IntelとApple Silicon両対応):ユニバーサル2バイナリの利用とRosettaへの配慮
- 10.3 Mac Catalystプラットフォームのサポート方法と注意点:iOS用FrameworkをCatalyst向けにビルドし変換する手順
- 10.4 tvOSプラットフォーム向けにXCFrameworkを構築する方法と注意点:tvOSデバイス/Simulator両対応のFrameworkを準備
- 10.5 watchOSプラットフォーム向けにXCFrameworkを構築する方法と注意点:ビルド対象にwatchOSを含め複数アーキテクチャを統合
XCFrameworkとは何か?新しいマルチプラットフォーム対応フレームワーク形式の概要と基本を解説
Xcode11以降、Appleは複数プラットフォーム向けのバイナリをまとめて配布できる新しいフレームワーク形式「XCFramework」を導入しました。従来、iOSデバイス用とシミュレーター用、さらにはmacOS用などにプラットフォームごと別々の.frameworkファイルを用意しなければならず、共通のライブラリを複数環境で使い回すには非効率でした。一部の開発者はlipoツールで複数アーキテクチャを人為的に結合した「Fatフレームワーク」を作成して対応していましたが、これは正式な方法ではなく、App Store審査でリジェクトされるケースもありました。XCFrameworkはそうした課題を解決するために登場した公式の配布形式であり、単一のパッケージに複数プラットフォーム(iOS、macOS、tvOS、watchOSなど)向けのフレームワークやライブラリを含めることができます。これにより、開発者はひとつのXCFrameworkバンドルを配布するだけで、ユーザーは自分のターゲットに応じたバイナリを自動的に利用できるようになりました。
XCFrameworkは内部的にはディレクトリ構造を持つ「バンドル」で、各プラットフォーム・アーキテクチャごとのビルド成果物(Frameworkや静的ライブラリなど)を格納し、それらの情報をInfo.plistに記録しています。これにより一つのXCFrameworkが含む複数の変種ライブラリをXcodeが認識し、ビルド時に自動で適切なものを選択してリンクしてくれます。XCFrameworkはソースコードを含まないバイナリ配布フォーマットであり、ヘッダ(API定義)とビルド済みバイナリのみを含むため、ライブラリの機密コードを公開せずに提供できる利点もあります。以上がXCFrameworkの概要と基本的な特徴で、複数環境への対応を公式にサポートし、将来の新しいアーキテクチャにも柔軟に対応できるよう設計された仕組みです。
従来のフレームワーク配布方法が抱えていた課題点:マルチプラットフォーム非対応の問題とFatフレームワークによる非公式対策の限界
XCFramework以前、Appleのプラットフォーム向けライブラリ配布にはいくつかの課題がありました。まず.frameworkは基本的に単一のプラットフォーム(例:iOS用やmacOS用)に限定されており、iOS向けライブラリをMacでも利用したい場合には別途macOS用.frameworkをビルドして配布する必要がありました。またiOSアプリ開発では、実機(arm64など)とシミュレーター(x86_64など)でアーキテクチャが異なるため、それぞれ別々の.frameworkを用意して使い分けなければなりませんでした。この切り替えはプロジェクト設定でFramework検索パスを状況に応じて変更するなど煩雑で、ビルド設定のトリックが必要だったのです。
この不便さに対し、一部の開発者はFatバイナリと呼ばれる手法で非公式に対応していました。Fatバイナリとは、例えばiOS実機用とシミュレーター用の2つのビルド産物をlipoコマンドで無理やり一つに連結したカスタム.frameworkです。これにより単一ファイルでデバイスとシミュレーター双方に対応させることができましたが、この方法はApple非公認のハックでした。特にApp Storeに提出するIPAにシミュレーター向けコード(x86_64アーキテクチャ)が混入したFatフレームワークを含めてしまうと、ストアの審査で拒否される重大なリスクがありました。さらに、Fatフレームワークでは異なるプラットフォーム(例:iOSとmacOS)を一つにまとめることは想定されておらず、あくまで同一OS内での異なるアーキテクチャ統合に留まっていました。つまり従来の方法では、複数OS間で単一のライブラリを共有する明確な手段がなく、開発・保守の面で大きな負担となっていたのです。
XCFramework誕生の背景:新フォーマットが生まれた経緯とAppleの狙いを徹底解説
AppleがXCFrameworkという新たなフォーマットを導入した背景には、上述したような従来方式の限界と、プラットフォーム拡大による状況の変化があります。iPhoneの他にtvOSやwatchOSといった新しいOSが増え、さらにMacでもiOSアプリを動かすMac Catalystの登場など、1つのライブラリを様々な環境で提供したいというニーズが高まっていました。しかし従来の.frameworkではこれに対応する明快な手段がなく、複雑な対処や複数バイナリの配布が必要でした。加えて2020年にはAppleシリコン(M1チップ)搭載Macが登場し、iOSとMacの双方で共通のARM64アーキテクチャが使われるようになりました。この結果、従来のFatフレームワーク手法では「アーキテクチャが同じでもプラットフォームが異なる」というケースに対処できず、従来手法の根本的限界が露呈したのです。
Appleはこれらの背景から、「一つのパッケージで複数プラットフォームに対応できる公式フォーマット」を提供する必要に迫られていました。長年「lipoによる独自対応は推奨されない」としながらも明確な解決策が無かった状況を打破すべく、WWDC 2019においてXCFrameworkが発表されたのです。Appleの狙いは、開発者が安全かつ容易に汎用的なバイナリを配布できる土台を用意し、将来のプラットフォーム追加やアーキテクチャ変更にもスムーズに対応できるようにすることでした。XCFrameworkは結果として、従来の混乱を断ち切る「公式解」として誕生し、Appleが考える理想的なマルチプラットフォーム対応ライブラリ配布形態を具現化したものと言えます。
XCFrameworkの定義と基本的な特徴:複数プラットフォーム対応の仕組みを詳しく紹介
XCFrameworkは一言で言えば「複数プラットフォーム/アーキテクチャ対応のユニバーサルなバイナリ配布パッケージ」です。内部には各プラットフォーム向けのビルド成果物(Frameworkや静的ライブラリなど)がおさめられ、それぞれ別フォルダに整理されています。例えば、iOSデバイス用、iOSシミュレーター用、macOS用、さらにはtvOSやwatchOS用…といった具合に、対応するプラットフォームごとにバイナリとヘッダ類が格納されているのです。そのため一つのXCFrameworkファイルがあれば、iPhoneアプリにもMacアプリにも同じSDKを組み込むことができます。
XCFrameworkがユニークなのは、Xcodeがそれを一つの「アーティファクト」として扱い、自動的に適切なバリエーションを選択して使用してくれる点です。開発者はプロジェクトにXCFrameworkを追加しリンクするだけで、ビルド時にXcodeが現在のビルドターゲット(どのOS向けか・CPUは何か)を判断し、XCFramework内から該当するバイナリを選んでリンクします。その裏では、XCFramework内のInfo.plistに記載されたAvailableLibraries情報を元に、Xcodeがプラットフォームとアーキテクチャの組み合わせを解釈しています。このようにXCFrameworkは一種の「傘(Umbrella)」のように複数バージョンのライブラリをまとめ、プロジェクトには一つだけ追加すれば良い仕組みとなっています。
また、XCFrameworkは将来の拡張性も考慮されています。Appleはこのフォーマットを「future-proof(将来に渡って有効)」と表現しており、新たなプラットフォームやCPUが登場した場合でも、XCFrameworkの仕様内で十分対処可能な柔軟性を持つとしています。例えば今後macOSやiOSで新しいアーキテクチャが採用された場合でも、そのアーキテクチャ向けにビルドしたバイナリをXCFrameworkに追加するだけで、同じパッケージを拡張して対応できます。これは単なるFatフレームワークでは不可能だった芸当であり、XCFrameworkが持つ重要な特徴と言えるでしょう。
XCFrameworkが解決する問題とニーズ:開発者が直面していた課題を解消する仕組みを詳しく解説
XCFrameworkの導入によって、従来開発者を悩ませていた数々の問題が解消されました。まず、複数プラットフォームへの対応が飛躍的に簡単になります。以前はiPhone向けとiPad向け(実際には同じiOSですがアーキテクチャ違いの例として)に同じライブラリを提供するだけでも煩雑さが伴いました。しかしXCFrameworkを使えば単一のパッケージで両方に対応できるため、互換性問題が減りビルドプロセスも簡素化されます。実際、あるチームがiPhoneとiPadの両方に展開するアプリでサードパーティライブラリをXCFrameworkとして取り入れたところ、従来別々に管理していたバイナリを統合でき、ビルド設定の手間も減ったため、開発効率が向上したという例があります。
また、依存ライブラリ管理の面でも恩恵があります。XCFrameworkは1ファイルで複数環境対応できるため、プロジェクトへの組み込み作業がシンプルになります。例えばCocoaPodsやCarthageで複数のバイナリを使い分けていたケースでも、XCFramework版が提供されれば一つの依存指定に置き換えることが可能です。その結果、プロジェクト設定が整理され、CI/CDでのビルドも安定しやすくなります。さらに、サードパーティSDK提供者側にとっても、単一のXCFrameworkを配布すればよいので、プラットフォームごとに個別のパッケージを配る必要がなくなり、バージョン管理やサポートが容易になります。
XCFrameworkはまた、新しいニーズへの対応も実現しました。先述のようにAppleシリコンMacやCatalystの登場で既存の枠組みでは対応困難な状況が生まれましたが、XCFrameworkは公式にそれを解決しました。例えばM1 Mac上でiOSシミュレーターを動かす場合、Fatフレームワークではarm64重複問題が発生しましたが、XCFrameworkにすることでこうした衝突を未然に防ぎ、問題なくライブラリを利用できます。これにより、Appleシリコン環境でもRosettaエミュレーションを使わずネイティブ動作での開発ができ、ビルド時間も短縮されるなどのメリットがあります。
総じて、XCFrameworkは開発者が長年抱えていた「マルチプラットフォーム対応」「依存管理の複雑さ」「将来の変更への不安」といった課題を解消するための的確な解となりました。今やiOS開発の現場ではXCFrameworkが広く普及し、複数プラットフォームをまたぐSDK配布の事実上の標準となりつつあります。これにより開発者は安心してマルチプラットフォーム対応ライブラリを構築・利用できるようになり、ユーザーにも安定した体験を提供できるようになりました。
Appleによる公式サポートと導入時期:Xcode 11で登場しXcode 12でSwiftPM配布に対応
XCFrameworkはいつから使えるようになったのでしょうか?AppleはWWDC 2019(2019年6月)のセッションで初めてXCFrameworkを紹介し、これは同年リリースのXcode 11で正式に利用可能となりました。つまりiOS 13開発のタイミングで登場した新機能です。その翌年のWWDC 2020では、Xcode 12においてSwift Package Manager(SPM)経由でXCFrameworkを配布できる新機能が発表されました。これにより、XCFrameworkとしてビルドしたバイナリをZIP圧縮してリポジトリ上に置き、SPMのbinary targetとして提供する形で、アプリ開発者が簡単にそれを取り込めるようになりました。
Appleは公式ドキュメントや開発者向け資料で、サードパーティSDK提供者に対してXCFrameworkへの移行を強く推奨しています。従来のFatフレームワークは推奨されない手法となり、CocoaPodsやCarthageといったエコシステムでもXCFramework対応が進みました(CocoaPodsは2019年末にはXCFrameworkのサポートを追加しています)。現在では、多くの主要SDK(FirebaseやFacebook SDKなど)がXCFramework形式での提供を開始しており、開発者は公式フォーマットに従った形で安心してそれらを利用できる状況です。Appleによる公式サポート開始から数年で、XCFrameworkはモダンなiOS/Appleプラットフォーム開発において欠かせない存在となったと言えるでしょう。
XCFramework対応のメリット・利点:マルチプラットフォーム開発における優位性をさらに詳しく解説
ここでは、XCFrameworkに対応すること(ライブラリをXCFramework化すること)によって得られる具体的なメリットについて解説します。XCFramework対応の利点は多岐にわたりますが、大きく分けて「マルチプラットフォーム対応が容易になる」こと、「配布と統合が簡素化される」こと、ビルドやCI効率など「開発プロセスの改善」、「将来への適応力向上」、そして「公式ツールとの親和性」の5点が挙げられます。それぞれ順を追って見ていきましょう。
マルチプラットフォーム対応が容易になる利点:単一パッケージで複数OSをサポート可能になり、開発・テストの効率化に貢献
XCFramework対応の最大のメリットは、ひとつのライブラリパッケージで複数のプラットフォームをシームレスにサポートできる点です。これにより、開発者はプラットフォームごとに別々のライブラリを用意・管理する手間から解放されます。例えば以前はiOS向けとmacOS向けに別個の.frameworkを配布していたケースでも、XCFramework化すれば一つの配布物で両OSに対応できます。実際のプロジェクトでも、XCFrameworkを利用することでコードの共通化やテストの簡略化が可能となり、マルチプラットフォーム開発が容易になったという報告があります。Xcodeはビルド時に自動で適切なバリアントを選択するため、開発者は意識せず複数環境への対応を実現できます。この結果、同じコードベースを複数OSでビルド・テストする際の効率が大幅に向上します。特に、iPhone/iPadアプリとMacアプリで共通のSDKを使う場合、XCFrameworkなら一度の導入で済むため、テストケースの重複も減り品質向上にもつながります。
さらに、XCFrameworkは将来的なプラットフォーム追加にも強く、新しいOSが増えてもパッケージを拡張するだけで対応できます。この柔軟性は、開発計画において「他のAppleプラットフォームへの展開を検討したい」といった要求に迅速に応えられるという意味でも大きな利点です。以上のように、XCFramework対応によってマルチプラットフォーム開発は飛躍的に簡素化され、その効果は開発からテスト、保守に至るまで広く波及します。
ライブラリ配布・統合が簡素化されるメリット:依存ライブラリ管理の負担軽減とプロジェクトへの組み込み作業が容易になる
XCFramework対応は、ライブラリの配布方法やプロジェクトへの組み込み手順も簡素化します。従来、サードパーティライブラリを導入する際にはCocoaPodsやCarthage、あるいは手動で.frameworkを追加するなど、煩雑な依存管理が必要でした。しかし、もしライブラリ提供者がXCFramework形式でSDKを配布していれば、開発者はそのXCFrameworkファイルを取得してプロジェクトにドラッグ&ドロップするだけで導入が完了します。ビルド設定もXcodeが自動調整するため、環境ごとにリンク先を変えるような処理も不要です。
CocoaPodsの場合も、podspecでvendored_frameworksとしてXCFrameworkパッケージを指定できるため、ポッド利用者はシンプルにPodfileに依存を1行書くだけで複数アーキテクチャ対応版を導入できます。Carthageも近年では--use-xcframeworks
オプションでXCFrameworkとしてビルド・取得する運用が推奨されており、従来のようにビルド後に不要なアーキテクチャをストリップする手作業は減りました。
依存管理が楽になることは、チーム開発やCI/CDパイプラインの安定化にも寄与します。プロジェクトに含まれるバイナリが減り、構成がシンプルになることで、ビルド時間の短縮や不整合の減少といった効果も期待できます。例えば、複数のターゲット間で共通のライブラリを使う場合でも、一つのXCFrameworkを参照する形に統一できるため、設定ミスによるリンクエラーなどのトラブルが起こりにくくなります。これらの点から、XCFramework対応はライブラリ配布・統合のプロセスそのものを簡略化し、開発者の負担軽減につながる大きなメリットを提供します。
アプリサイズと依存関係管理の改善:ビルド効率向上と不要なコードの排除によるアプリ容量削減
XCFramework対応はアプリのビルド効率や最終的なサイズにも良い影響を与える場合があります。まず、XCFrameworkとして提供されるライブラリは事前にコンパイル済みのバイナリであるため、プロジェクトに組み込んでもソースコードからビルドする必要がありません。その分、アプリをクリーンビルドする際の時間が短縮され、CIでのビルドも高速化する傾向にあります。特に、大規模なOSSライブラリをSPM経由で導入するとき、ソースからビルドする場合は数百MB規模のリポジトリ全体を取得・コンパイルする必要がありましたが、バイナリ配布されたXCFrameworkなら必要最低限の成果物だけをダウンロードすれば済むため、無駄な処理を省けます。これにより、開発マシンやCIの待ち時間が減り、開発サイクルが円滑になります。
また、アプリの最終バイナリサイズにも配慮できます。Fatフレームワーク方式では、不要なアーキテクチャを除去しないまま組み込んでしまうと、その分無駄にサイズが増加する恐れがありました。しかしXCFrameworkでは、各プラットフォーム専用のバイナリのみがリンクされるため、最終的にAppに含まれるコードは必要最低限となります。例えばiOSアプリにおいて、XCFrameworkで提供されたSDKを組み込む場合、App Store提出前のビルドではシミュレータ向けコードは自然と除外されているため、余分な容量を含まずに済みます。これはユーザーのダウンロードサイズ削減にもつながる利点です。
さらに、依存関係管理の改善もアプリ品質に寄与します。XCFrameworkにより依存ライブラリのバージョン衝突や重複リンクが起きにくくなるため(単一パッケージで一元化されるため)、ランタイムでの予期せぬ動作を防ぎやすくなります。以上のように、XCFramework対応はビルド効率とアプリサイズ、依存管理といった開発の裏側にも好影響をもたらし、結果的に開発体験とユーザー体験の双方を向上させることが期待できます。
将来のアーキテクチャ変化への柔軟性と保守性向上:M1など新CPU登場にも対応しやすく長期的な保守が容易
XCFramework対応は、ライブラリの将来の保守性と適応力も高めてくれます。Appleプラットフォームは過去にもCPUアーキテクチャの転換(PowerPC→Intel、Intel→ARM)や新OS追加が度々ありましたが、XCFrameworkはそうした変化に柔軟に対応できるよう設計されています。具体的には、新しいアーキテクチャやOSに対してライブラリをリビルドし、それを既存のXCFrameworkに追加するだけで、新バージョンのパッケージとして提供できます。利用者側は基本的にパッケージをアップデートするだけで新環境への対応版を手に入れられるため、移行もスムーズです。
例えば、近年登場したApple Silicon(M1/M2)への対応では、従来のFatフレームワークは前述のように課題が発生しましたが、XCFrameworkならばIntel向けとARM向けのMac用バイナリを同梱したり、あるいはUniversal 2バイナリを含める形で対応できます。将来、さらに新しいCPUやプラットフォーム(仮にAppleがVRデバイス用OSやその他のフォームファクタを出した場合など)が出現しても、開発者はXCFrameworkパッケージを拡張することで迅速に対応版SDKを提供できるでしょう。
このように、XCFramework対応はライブラリの将来への投資とも言えます。変化に強い構造を持つため、長期の保守においても基盤が安定しやすく、大きな仕様変更なく時代のニーズに追随できます。実際Apple自身が「XCFrameworkは将来の未知のプラットフォームやアーキテクチャにも対応できる」と言及している通り、開発者にとって心強いフォーマットなのです。結果として、XCFrameworkに早めに対応しておくことは、ライブラリ/SDKの寿命を延ばし、利用者からの信頼を高めることにもつながるでしょう。
Swift Package Manager等との親和性・相互運用性の高さ:Apple公式ツールとの統合による開発効率アップ
XCFramework対応の最後のメリットは、Apple公式のエコシステムとの親和性が高まる点です。特にSwift Package Manager(SwiftPM)との連携は大きなトピックで、Xcode 12以降、SwiftPMでXCFrameworkをバイナリ配布することが可能になりました。これにより、サードパーティSDK提供者は自分たちのライブラリをXCFrameworkとしてビルドしGitHub等でホスティングするだけで、開発者はSwiftPMから容易にそれを取り込めるようになりました。CocoaPodsやCarthageと比べても、Xcode統合が進んだSwiftPMは追加ツール不要でセットアップできるため、エンドユーザーである開発者の利便性が高まります。実際、「純正ツールであるSwiftPMでSDK導入が完結することで、環境構築がシンプルになり導入のハードルが下がった」との声もあります。
また、XCFrameworkはAppleのCIサービスであるXcode Cloudとも相性が良い点が指摘されています。Xcode CloudではSwiftPM依存のキャッシュが自動で利用されますが、社内ライブラリをXCFramework+SwiftPM化した事例では「ビルド環境構築の時間短縮」や「依存管理の一元化」に成功しています。Apple公式のソリューションを用いることでサポート面のリスクも低減できるというメリットもあり、社内SDKの配布形態をXCFramework+SwiftPMに移行する企業も増えています。実際、ナビタイムジャパンではC++やObjective-Cで書かれた社内フレームワーク群をXCFramework化しSwiftPM対応することで、CIのキャッシュ活用や環境構築簡略化など運用改善を達成しています。
このように、XCFramework対応は最新のApple純正ツールとの統合を可能にし、開発フロー全体の効率アップにつながります。公式推奨の道具立てを使うことで将来的なサポートも期待でき、安心感も得られるでしょう。以上、5つの観点からXCFramework対応のメリットを述べましたが、総じて言えるのは、XCFrameworkは「より広く・簡単に・効率的に」ライブラリを配布・活用するための強力な仕組みだということです。
XCFramework対応の理由:なぜ従来フレームワークからXCFrameworkへの移行が必要なのか
次に、なぜ現在XCFrameworkへの対応がこれほど重要視されているのか、その背景となる理由を整理します。前章のメリットとも一部重なりますが、ここでは特に「移行せざるを得ない状況」となった要因にフォーカスします。主な理由としては、新しいCPUアーキテクチャ登場への対応、Fatフレームワーク方式の限界とApp Store制約、シミュレータコード混入問題の回避、マルチプラットフォーム開発の一般化、そしてApple自身の推奨による圧力の5点が挙げられます。
新CPUアーキテクチャ(ARM Macなど)への対応が必要になった背景:従来方式ではM1チップへの対応が困難だった
第一の理由は、Apple Silicon(M1)をはじめとする新CPUアーキテクチャへの対応です。2020年に発表されたM1チップ搭載Macは、従来Intel向けにビルドされていたMac用ライブラリに対して大きな変化をもたらしました。従来方式(Intel用.framework)ではM1(Mac用arm64)に対応できず、新たなバイナリの提供が必要となったのです。さらに厄介だったのは、M1 Mac上で動くiOSシミュレータもarm64アーキテクチャを使用するため、iOS実機用(arm64)とシミュレータ用(arm64)でアーキテクチャが重複してしまう点でした。Fatフレームワークではアーキテクチャ名で対象を区別していたため、同じarm64が2つ存在すると正しく扱えずビルドが失敗する事態に陥りました。
Appleはこの問題に対し、開発者にXCFrameworkへの移行を促しています。XCFrameworkであれば、デバイス用とシミュレータ用で同じarm64アーキテクチャを含む場合でも、それらを別プラットフォームのバリアントとして明確に分離して保持できるため、衝突が起こりません。実際Carthageなどでは一時的に「シミュレータarm64を除外してビルドする」ワークアラウンドで凌ぐ手段が取られていましたが、これは根本解決ではなくRosetta 2(Intelエミュレーション)上で開発することを強いる副作用もありました。XCFrameworkならネイティブのarm64環境を活かした開発が可能となり、アーキテクチャ対応とパフォーマンスの両面で有利です。M1に限らず、今後もし新しいCPUやデバイス(例えばARM版の新デバイス)が出現しても、XCFrameworkに対応しておけば柔軟に追随できるため、アーキテクチャ変化への備えとしてXCFramework移行は重要です。
Fatバイナリによる旧方式の限界とApp Storeの制約:非公式なFatフレームワークはApp Store審査で拒否される可能性
第二の理由は、従来のFatフレームワーク方式自体の限界と、Appleの審査ポリシーとの相性の問題です。Fatフレームワーク(Universal Framework)は先述の通り非公式な手法で、開発者コミュニティの工夫から生まれたものですが、Appleは一貫して「推奨されない」としてきました。特にApp Storeに提出する際、Fatフレームワークにシミュレータ向けスライスが含まれているとリジェクトのリスクがあり、実際にストア審査で弾かれた事例も報告されています。
またFatフレームワークは、macOSとiOSのような異なるOS間の統合には対応できないという本質的な制約がありました。Fat化できるのは基本的に同一OS内の異なるCPUアーキテクチャのみで、例えばiOSとmacOSのFrameworkを一つにまとめることは想定されていません。そのため、マルチOSに跨るSDK配布には根本的に不向きでした。このようにFatフレームワーク方式には技術的・運用的な限界があり、Appleとしても開発者に正式な解決策を提示する必要があったのです。
XCFrameworkはその公式解として、Fatフレームワークの問題点をすべて払拭しました。複数OSや複数CPUを1つにまとめられ、App Store審査でも問題ありません(実際、Appleは自社の公開SDKをXCFramework形式で配布しています)。以上の背景から、旧方式の限界に直面していたライブラリ開発者はXCFrameworkへの移行が不可避となったと言えます。
シミュレーターコード混入による不具合の排除:デバイス用バイナリに誤ってシミュレータコードを含めない仕組み
第三の理由は、シミュレーター用コードの混入による不具合を防ぐ必要性です。これは主にiOS向けライブラリの配布で顕在化していた問題です。Fatフレームワークを利用した場合、開発中はシミュレーターとデバイスの両方で1つのライブラリを使える利点がありましたが、リリース時にはシミュレーター向けのx86_64コードを取り除く必要がありました。もし除去し忘れると、App Store提出時に拒否されるだけでなく、仮に通過してしまった場合でも実機には不要なコードが含まれることになり、余計なセキュリティリスクやパフォーマンスへの影響を招きかねません。
XCFrameworkであれば、そもそもデバイス用とシミュレーター用のバイナリが別物として扱われるため、実機向けビルドにはシミュレーターコードがリンクされません。その結果、うっかりシミュレータ用のアーキテクチャを混入させたまま配布してしまうミスを根本から防げます。特にApple Silicon移行期には、シミュレーターがデバイスと同じarm64を使うため一見区別が付きにくく、Carthageビルドで不要なスライスを削るスクリプトを走らせるなど対応が大変でした。XCFrameworkを使えばそうした特殊なスクリプトも不要となり、クリーンなデバイス用バイナリだけをユーザーに届けられます。
加えて、シミュレーターとデバイスのバイナリを厳密に分離することで、デバッグ時の挙動も安定します。以前はFatフレームワーク内にシミュレーターコードが混在していると、Xcodeが警告を出したり、アプリサイズの算定が狂ったりすることもありましたが、XCFrameworkではそのような混乱も起きません。以上のように、XCFrameworkへの移行はシミュレーター関連の不具合リスクを排除する上でも重要な意味を持っています。
複数プラットフォーム開発の一般化と需要増:1つのSDKでiOS・macOSなどを同時サポートするニーズ
第四の理由は、複数プラットフォーム開発が一般化し、それに一つのSDKで対応したいというニーズが高まったことです。Appleはここ数年で、「MacでiPadアプリが動く」「Apple WatchとiPhoneが連携する」といったクロスプラットフォームなユーザー体験を推進してきました。その結果、開発者側もiOSとmacOS、さらにはwatchOSやtvOSといった複数OS向けに単一のSDKを提供・利用したい状況が増えています。
従来、例えばゲームエンジンや広告SDKなどはiOS版とmacOS版が別々に提供されていました。しかし開発効率やバージョン整合性の観点から、できれば同じバージョンのSDKを全プラットフォームで使いたいわけです。XCFrameworkはまさにその需要に応えるための仕組みであり、マルチプラットフォーム開発を前提とした現代のアプリ開発に適合しています。Appleも「プロジェクトがiOSとmacOSをターゲットにするならXCFrameworkで依存関係をまとめると良い」といった趣旨の情報発信を行っており、実際多くのSDKがマルチOS対応を売りにXCFramework化を進めています。
またビジネス的にも、マルチプラットフォーム対応SDKは採用メリットが高まります。たとえば企業が自社サービスのiOSアプリとmacOSアプリの両方を提供している場合、共通SDKが一つで済めば、開発リソースの節約やリリースサイクルの同期が容易になります。XCFrameworkはこうした要望に応え、1パッケージで全デバイスをカバーする手段を提供することで、開発規模の拡大やOS多様化に伴う課題に対処しています。このような背景から、複数プラットフォームを見据えた開発を行うならXCFramework対応が事実上必須となりつつあります。
Appleの推奨による新標準への移行プレッシャー:公式ドキュメントやWWDCでXCFramework対応が促進
最後の理由は、Apple自身がXCFrameworkへの移行を強く推奨していることです。公式ドキュメント、WWDCセッション、開発者へのアナウンスなど、様々な場面でAppleは「XCFrameworkを使うべき」だと示唆しています。例えばWWDC 2019のセッション「Binary Frameworks in Swift」では、従来の問題点(Fatフレームワークの非推奨など)に触れつつXCFrameworkの利点が詳細に説明されました。また、2020年以降Appleは主要なフレームワーク(SwiftUIやRealityKitなど)を通じてバイナリのModule Stability(後述)を確保する方向にシフトしており、XCFrameworkはその流れと軌を一にするものです。
さらに、サードパーティライブラリの世界でも、Appleの方針に追随してXCFrameworkへの対応が進みました。CocoaPodsは2019年9月にXCFrameworkサポートIssueが立ち上がり、1.9.0で正式に対応を果たしています。CarthageもApple Silicon問題への対処として2020年末に–use-xcframeworksを導入し、新フォーマットへの対応を促しました。SwiftPMも上述の通りXcode 12でバイナリ配布を可能にしており、今やApple公式エコシステム全体がXCFrameworkを前提として動いていると言えます。
こうしたApple側からの「新標準への移行圧力」は、開発者にとって無視できないものです。特に法人向けSDKなどでは、クライアントから「XCFramework版はありませんか?」と尋ねられるケースも増えており、対応しなければ選定から外れる可能性も出てきます。つまり、Appleの推奨=業界標準となりつつあり、トレンドに乗り遅れないためにもXCFramework対応が必要という側面があります。以上、5つの観点からXCFramework移行の背景理由を述べました。総合すると、技術的必然性と業界動向双方の理由から、XCFramework対応は現代のAppleプラットフォーム開発で不可避の流れとなっているのです。
XCFrameworkの作成方法:Xcodeを用いたマルチプラットフォーム向けビルドとアーカイブ手順を詳しく解説
ここからは、実際にライブラリ開発者が自作ライブラリをXCFramework化する手順について解説します。Xcodeを使ったGUIでの手順と、xcodebuild
コマンドを使ったCLIでの方法の両方に触れながら、マルチプラットフォーム対応XCFrameworkを作成する流れを説明します。また、作成時に注意すべきビルド設定のポイントや、生成されたXCFrameworkの中身の確認方法についても紹介します。
それぞれのプラットフォーム向けFrameworkをビルドする手順:iOSデバイス用とSimulator用に個別ビルド
XCFrameworkを作成するには、まず対象とする各プラットフォームごとにライブラリ(Frameworkや静的ライブラリ)をビルドする必要があります。例えばiOS向けに開発したライブラリであれば、iOSデバイス用(arm64アーキテクチャ)のビルドと、iOS Simulator用(x86_64およびarm64アーキテクチャ)のビルドをそれぞれ行います。XcodeのGUI上で行う場合、通常はビルドターゲットのDestinationを「Any iOS Device (arm64)」と「Any iOS Simulator (x86_64/arm64)」に切り替えてビルドまたはアーカイブを行えば、それぞれのプラットフォーム向けFrameworkバイナリが得られます。
たとえばXcodeでArchiveを行う場合、Any iOS Device
でArchiveした結果として.arm64デバイス用の.xcarchiveが作成され、Any iOS Simulator
でArchiveすればx86_64/arm64(Apple Silicon)のシミュレータ用.xcarchiveが出力されます。Archiveせず通常のビルドでFrameworkを生成することも可能ですが、Archiveすると署名情報なども含まれ安定した成果物が得られるため推奨です。iOS以外のプラットフォーム、例えばmacOS向けライブラリであれば、Any Mac (Intel)
とAny Mac (Apple Silicon)
とでそれぞれビルドするか、Universal 2(Intel+ARM両対応)バイナリを作成する設定を有効にしてビルドします。
以上のように、対象とする全プラットフォーム分のFrameworkまたはライブラリを事前に用意しておくことがXCFramework作成の第一ステップとなります。なお、XcodeのArchiveコマンドは内部でxcodebuild
を実行しており、自動的にdSYM(デバッグシンボル)なども生成してくれるため便利です。次のステップでは、これら個別プラットフォーム用のビルド成果物をまとめてXCFrameworkバンドルを作成します。
XcodeでのArchiveと.xcarchiveの作成:GUIを使ったFrameworkバイナリ書き出し
XcodeのGUIでXCFrameworkを作成する代表的な方法は、「Archive→Export」を利用する手順です。先ほど述べたように、まず各プラットフォーム別に.xcarchive(アーカイブ)を作成します。例えばiOSデバイス用にArchiveを実行するとMyFramework.xcarchive
という成果物が得られ、内部にProducts/Library/Frameworks/MyFramework.frameworkが格納されています。同様にiOS Simulator用にもArchiveを行い、シミュレータ版の.frameworkを含む.xcarchiveを用意します。
次に、XcodeのメニューからOrganizerを開き、先ほど作成した.xcarchiveを選択します。「Distribute Content(内容を配布)」→「Swift Package(またはXCFramework)」というオプションが表示されますので、そこからエクスポートを進めます。Xcodeは複数の.xcarchiveを選択して同時にエクスポートすることが可能で、デバイス用とシミュレータ用の両アーカイブを選んだ状態で進めると、一つの.xcframeworkファイルが出力されます。エクスポート先を指定すると、そのフォルダ内にMyFramework.xcframework
が作成されるはずです。
この手順により、GUI上だけでXCFrameworkの作成が完了します。Xcodeが内部で必要なxcodebuild -create-xcframework
処理を実行してくれるため、コマンドラインに不慣れな場合でも簡単です。ただし、Xcode GUIでのエクスポートではオプション設定が限定的なので、例えばdSYMを含めるか否かなど細かい制御ができません。デバッグシンボルを含めたい場合や、Archiveではなく通常ビルドのFrameworkからXCFrameworkを作りたい場合は、次に述べるxcodebuildコマンドを使った方法が必要になります。
xcodebuild -create-xcframeworkコマンドの使用方法:複数プラットフォームのビルド成果物を一括パッケージ化
より柔軟な方法として、xcodebuild -create-xcframework
コマンドを直接使ってXCFrameworkを作成することができます。基本的な使い方はシンプルで、xcodebuild -create-xcframework -framework (デバイス用.frameworkのパス) -framework (シミュレータ用.frameworkのパス) -output (出力先XCFrameworkのパス)
という形で実行します。例えば、先ほどArchiveで生成したios.xcarchive
とios-simulator.xcarchive
からフレームワークを取り出して指定する場合:
xcodebuild -create-xcframework \ -framework build/ios.xcarchive/Products/Library/Frameworks/MyFramework.framework \ -framework build/ios-simulator.xcarchive/Products/Library/Frameworks/MyFramework.framework \ -output MyFramework.xcframework
上記コマンドを実行すると、カレントディレクトリにMyFramework.xcframeworkが生成されます。-framework
オプションは複数指定可能なので、iOSデバイス用、iOS Simulator用、さらにmacOS用など、サポートしたい分だけ列挙します。また-library
オプションを使えば静的ライブラリ(.a)とヘッダを組み合わせてXCFrameworkに含めることも可能です(詳細は後述)。コマンド実行前に、それぞれの.frameworkが有効な状態で存在していることを確認してください。なお、デバッグ用のdSYMファイルをXCFrameworkに含めたい場合、-debug-symbols
オプションを使用してdSYMのパスを指定します。このオプションも-frameworkと同様に複数指定可能です。
実行後、特にエラーがなければXCFrameworkが出来上がります。万一Missing required architecture
などのエラーが出た場合、指定したFrameworkに必要なアーキテクチャが含まれていない可能性があります。その際はXcodeのビルド設定を見直し、全ての必要なスライスが含まれるよう再ビルドしてください。xcodebuildコマンドによる方法は、GUIよりも手間ですがスクリプト化してCIで自動生成したり、カスタム設定で自由度高く作成できる利点があります。Appleも公式ヘルプでこのコマンド手順を解説しており、開発者は目的に応じてGUIとCLIを使い分けると良いでしょう。
Build設定のポイント:BUILD_LIBRARY_FOR_DISTRIBUTION有効化など将来のSwift互換性を確保する設定
XCFrameworkを作成・配布する際には、いくつか重要なビルド設定にも注意を払う必要があります。中でも極めて重要なのが、Swiftで書かれたライブラリの場合の「モジュール安定性(Module Stability)」に関する設定です。具体的には、XcodeのBuild設定で対象ターゲットのBuild Libraries for Distribution(通称BUILD_LIBRARY_FOR_DISTRIBUTION)をYES
にすることが推奨されます。
この設定を有効にすると、ライブラリの.swiftinterfaceファイルが生成され、将来のSwiftコンパイラでもバイナリを読み込めるようになります。Swiftは言語仕様のアップデートに伴い、同じモジュールでもコンパイラバージョンが異なると互換性エラーを起こすことがあります(Module compiled with Swift 5.x cannot be imported in Swift 5.y
というエラー)。Module Stabilityに対応していないSDKでは、開発者は使用するXcodeのバージョンに合わせてライブラリの再配布を受ける必要があり、大きな負担でした。しかしSwift 5.1(Xcode 11)でModule Stabilityが導入されたことで、BUILD_LIBRARY_FOR_DISTRIBUTIONを有効にビルドしさえすれば、将来のSwiftバージョンでもそのライブラリを利用できる可能性が高まります。
そのほかの設定としては、Bitcode(現在はAppleのサポートが終了しましたが過去には有効化推奨でした)やCode Signingの扱いがあります。静的ライブラリベースのXCFrameworkであれば署名は不要ですが、動的Frameworkの場合は通常の.framework同様に適切なコード署名(Ad Hoc署名やDeveloper ID署名)をしておくと安全です。特にmacOS向けに配布する場合、Apple Notarization(公証)を済ませておくとエンドユーザー環境で警告が出ずに済みます。
以上のようなビルド設定を整えることで、XCFrameworkはより堅牢で長く使えるものになります。とりわけBUILD_LIBRARY_FOR_DISTRIBUTIONについては忘れずに設定しておきましょう。実際、Yahoo! JAPANの広告SDKチームでもXCFramework化に際してこの設定を有効にし、将来のSwiftバージョンへの備えを行っています。
生成されたXCFrameworkの内容確認と検証:Info.plistで含まれるプラットフォームとアーキテクチャを確認
XCFrameworkの作成が完了したら、その内容を確認しておくことも大切です。XCFrameworkは実体はフォルダなので、FinderやターミナルでMyFramework.xcframework
を開くと中身が見えます。各プラットフォーム向けにios-arm64やios-arm64_x86_64-simulator、macos-x86_64等のディレクトリがあり、その中に実際の.frameworkや.a + Headersが格納されています。例えばiOSデバイス向けのFrameworkとiOSシミュレーター向けのFrameworkを含めたXCFrameworkなら、フォルダが2つ並んでいるはずです。
また、XCFramework直下のInfo.plistファイルを開くと、AvailableLibraries
というキーの下に含まれる各バリエーションの情報が記載されています。そこにはSupportedPlatform
やSupportedArchitectures
として、例えばiOS
(Device)にarm64
、iOS
(Simulator)にarm64
/x86_64
…のように今回パッケージした内容が網羅されています。このInfo.plistをチェックすることで、XCFrameworkに含め忘れたプラットフォームがないか、想定通りのアーキテクチャが入っているかを検証できます。
実際のプロジェクトに組み込んで動作確認することも重要です。Xcodeに生成したXCFrameworkをドラッグ&ドロップし、iPhoneシミュレーターで動作するか、実機で動作するか、さらに別途macOSアプリでリンクして正しく動作するか、といったテストをしましょう。複数のプラットフォームで問題なく読み込まれ動作することが確認できれば、XCFrameworkの作成は成功です。これで晴れて、作成したXCFrameworkをチーム内や外部に配布し、マルチプラットフォーム対応ライブラリとして提供する準備が整いました。
XCFramework配布の注意点:効率的な配布方法とバージョン管理のポイント
XCFrameworkを無事作成できたら、次はそれを配布する段階です。配布にあたっては従来の.framework配布と比べていくつか留意すべき点があります。ここでは、CocoaPodsやCarthageなど既存ツールでの扱い、Swift Package Managerでのバイナリ配布、SDKのバージョン管理、コード署名・セキュリティ上の考慮、そして配布物に含めるべき内容について解説します。適切な手順と注意点を押さえて、安全かつ効率的にXCFrameworkを配布しましょう。
CocoaPodsやCarthageでのXCFramework取り扱い方法と注意点:vendored framework指定や –use-xcframeworksオプションなど
まず、従来から利用されている依存管理ツールでのXCFrameworkの扱いです。CocoaPodsでは、バージョン1.9.0以降でXCFrameworkをサポートしています。Podspecにvendored_frameworks
としてMySDK.xcframework
を指定すれば、Pod利用者がそのPodをインストールした際に、自動的にXCFrameworkがプロジェクトに組み込まれるようになります。CocoaPodsは内部で必要なアーキテクチャの切り分けも処理してくれるため、開発者は特別な対応をせずともXCFramework対応Podを提供できます。
Carthageについては、以前はFatフレームワークを生成する挙動がデフォルトでしたが、Apple Silicon登場時に問題が生じたため、現在では--use-xcframeworks
オプションを付けてビルドすることが推奨されています。Carthage 0.37.0以降ではこのフラグでビルドすると各プラットフォーム向けFrameworkをまとめたXCFrameworkが作成されます。Carthageで自作ライブラリを配布する場合も、このオプションを利用して事前にXCFrameworkをビルドし、その.zipを配布する形が一般的です。
注意点として、Carthageで生成されるXCFrameworkにはデバッグシンボル(dSYM)が含まれないことがあるため、必要なら別途配布するか手動でdSYMを同梱することが望ましいです。また、古いCarthage利用者の中には依然Fatフレームワーク形式に慣れている場合もあるため、リリースノート等で「本SDKはXCFramework形式で提供されます」「Carthage利用時は–use-xcframeworksでビルドしてください」と案内すると親切でしょう。
SwiftPMバイナリパッケージとして配布する際のポイント:Package.swiftでのbinaryTarget定義とホスティング方法
XCFrameworkはSwift Package Manager(SPM)での配布と非常に相性が良いです。SPMでは、Package.swift内で.binaryTarget
を使ってXCFrameworkを指定することで、バイナリパッケージとしてライブラリを提供できます。手順としては以下の通りです。
- XCFramework(
MySDK.xcframework
)をZIP圧縮し、インターネット上(GitHub Releasesや自社サーバ等)にアップロードする。 - Package.swiftを作成し、
targets
配列内に.binaryTarget
エントリを追加する。ここでname
はライブラリ名、url
は先ほどアップロードしたZIPのURL、checksum
はそのZIPファイルのSHA-256ハッシュ値を指定する。 - Package.swiftの
products
配列に.library
エントリを追加し、targetsで定義したbinaryTarget名をリンクする。 - このPackage.swiftをリポジトリにプッシュし、バージョンタグ(セマンティックバージョニングに沿ったタグ名)を付ける。
- 利用者は、Xcodeの「File > Add Packages…」からこのリポジトリを指定し、ライブラリをプロジェクトに追加できる。
上記のステップにより、開発者はSPM経由で簡単にバイナリライブラリを導入できます。binaryTarget
ではGitのリポジトリ上にXCFrameworkを直接置くこともできますが、サイズが大きくなる場合は外部URLを指定した方が無難です(Git LFSなどを使う手もあります)。重要なのは、checksum
フィールドを正確に計算して記述することです。これはセキュリティのためにダウンロードしたファイルのハッシュ検証を行うためで、swift package compute-checksum
コマンドで得られるハッシュ値を使います。
ホスティングするZIPファイルには、.xcframeworkフォルダ自体を含めた状態で圧縮してください(アンアーカイブすると直接MySDK.xcframework
が現れる構造)。また、URLはhttpsで外部からアクセス可能である必要があります。GitHub Releasesを使う場合、リリースごとにXCFrameworkのZIPと対応するハッシュを公開すると良いでしょう。Package.swift側のバージョンアップ(例えば1.0.0から1.1.0への更新)の際には、XCFrameworkを新バージョンでビルドし直しZIPとハッシュを更新することを忘れないようにします。
バージョン管理と互換性維持のためのベストプラクティス:セマンティックバージョニングと複数バージョン並行提供
XCFramework配布におけるバージョン管理は、基本的に他のライブラリ配布と同様にセマンティックバージョニング(Semantic Versioning)に従うのが望ましいです。メジャーバージョンが異なる場合は非互換な変更を含むことを示し、マイナーバージョンアップやパッチでは後方互換性を保つ、というルールです。特にbinary frameworksはソースコードでのコンパイルエラーではなく、リンク時や実行時に問題が表れることがあるため、互換性に影響する変更(関数シグネチャの変更や依存ライブラリの変更など)の際には慎重にメジャー番号を上げるといった対応が求められます。
また、SPMで配布する場合はバージョンタグに従って利用者がバージョン選択を行うため、過去の主要バージョンについてはしばらくリポジトリ上に残しておくのが良いでしょう。例えばv1系とv2系で大きく非互換変更がある場合、2つのリリースブランチや異なるPackage名で並行提供することも検討します。CocoaPodsではpodspec名を変えることで複数バージョン共存(FirebaseのAnalyticsとAnalyticsWithoutAdIdのようなケースなど)が可能です。
互換性維持の観点では、前述したBUILD_LIBRARY_FOR_DISTRIBUTIONの設定やSwift ABIの安定性確保もバージョニング戦略と絡んできます。仮にSwiftのメジャーアップデート(例えばSwift6)でABI互換性が失われる場合には、新しいXCFrameworkバージョンをリリースする必要があります。その際はドキュメント等で「Swift6以降はv2.x系をご使用ください」と案内するなど、利用者への周知も重要です。
さらに細かい点として、XCFramework自体のバージョン番号をどこかで明示しておくことも有用です。Info.plist内に独自キーを設けてバージョンを書き込んでおくか、READMEやドキュメントに対応表を載せておくと、利用者が誤って古いXCFrameworkを使っているといったトラブルに気づきやすくなります。総じて、セマンティックバージョニングに沿った丁寧なリリースと情報提供が、XCFramework配布の円滑なバージョン管理につながります。
コード署名とセキュリティ:XCFramework配布時の開発元署名とApple Notarizationの考慮
XCFramework自体は単なるコンテナ形式ですが、その中身に動的ライブラリ(.framework)が含まれている場合、コード署名の扱いに注意が必要です。iOS向けの.frameworkは通常Appビルド時に再署名されるため、配布段階でAd Hoc署名(-
コード署名なし)でも問題ないことが多いです。しかしmacOS向けのFrameworkの場合、Gatekeeperなどの観点でDeveloper ID署名を行っておくことが望ましいです。特に、開発元が配布するSDKをユーザーが直接アプリ内に組み込むケースでは、あらかじめ署名されたバイナリである方が信頼性が高まります。
さらにmacOS用のライブラリを含むXCFrameworkをインターネットで配布する場合、AppleへのNotarization(公証)を受けておくと安心です。NotarizationされたDeveloper ID署名付きバイナリであれば、エンドユーザーのMacで読み込まれる際にセキュリティ警告が出にくくなります。もっとも、XCFramework自体は開発者がアプリに組み込む目的で配布されるため、最終的にはアプリ開発者側でApp全体をNotarization/署名する流れになります。そのため必須ではありませんが、提供者としてセキュリティに配慮する場合は検討してもよいでしょう。
iOS向けについては、App Storeに含められないシミュレータコードや不要なリソースを入れないこと自体がセキュリティ対策となります。前述のようにXCFrameworkならそれらが避けられるので、余計な心配は減ります。また、XCFramework配布時にはハッシュ値(SPMの場合はchecksum)を利用して改竄検知を行う仕組みが標準で備わっています。提供者は正しいハッシュをPackage.swiftに記載し、利用者のXcodeが自動検証するため、これもセキュリティ面での安心材料です。
最後に、人間的なセキュリティとしてライセンスの表示があります。XCFrameworkにはREADME等を同梱する明確な場所がないため、必要に応じてドキュメントURLを提供したり、ライセンスファイルを含めたzipで配布したりすると良いでしょう。これらの対応を総合して、XCFramework配布時には技術的セキュリティと情報提供の両面で信頼性を確保するよう心掛けます。
配布アーカイブ構成:dSYMシンボルやライセンスファイルの同梱とその扱い
XCFrameworkを配布する際のアーカイブ(zipなど)の構成にも気を配りましょう。基本的には「XCFramework本体のみをZIP圧縮したもの」を提供すれば問題ありません。例えばMySDK.xcframework
というフォルダをzipに固めて配布し、利用者はそれを展開して出てきた.xcframeworkをプロジェクトに追加する形です。複数のXCFrameworkを一度に配布する場合でも、各.xcframeworkファイルをまとめてzipに含めるだけで構いません。
dSYMファイル(デバッグシンボル)は、可能であれば配布しておくことが望ましいです。クラッシュ解析などでシンボル情報が役立つためですが、配布サイズとのトレードオフもあります。SPMの場合、binaryTargetでdSYMを同梱する手段は現在ありませんが、CocoaPodsではresources指定でdSYMを落とすことも可能です。手動配布の場合は、必要に応じてMySDK.framework.dSYM
を別途提供するか、ドキュメントで希望者に提供する旨を記載すると良いでしょう。GitHubなどで配布する場合、リリースページにdSYM付きアーカイブとdSYMなしアーカイブの2種類を用意するケースもあります。
また、ライセンスファイル(LICENSEやNOTICE)がある場合、XCFramework内に含めてしまう方法もあります。例えばMySDK.xcframework/LICENSE.txt
のようにファイルを置いておけば、配布物にライセンスが付随することになります。ただしXcode上からは見えないため、結局利用者には届きにくい可能性があります。代替として、GitHubリポジトリにライセンスを明記しておく、ドキュメントに記載しておくなどが考えられます。
最後に、XCFramework配布用zipのチェックリストとしては、「正しい構造で解凍できるか」「想定通りのアーキテクチャが入っているか(Info.plistで確認)」「余計なファイルが混入していないか(.DS_Storeなど)」「必要ならdSYM等別途提供されているか」などが挙げられます。これらを確認した上で配布を開始すれば、利用者にとって使いやすいXCFramework提供が実現できるでしょう。
Swift Package Managerとの連携:XCFrameworkをSwiftPMで配布・統合する方法
最後に、Swift Package Manager(SPM)との連携について詳しく見ていきます。近年、Apple公式のパッケージ管理ツールであるSwiftPMの利用が一般化しつつあり、XCFrameworkはそのSwiftPMを通じて配布できる点で非常に重要です。SwiftPMでXCFrameworkを扱う方法やメリット、注意点を解説します。すでに「配布の注意点」で概要を触れましたが、ここでは具体的なPackage.swiftでの定義方法や制約事項について、より踏み込んで説明します。
XCFrameworkをSwiftPMで利用するメリット:依存管理の統一とCIキャッシュ活用によるビルド時間短縮
XCFrameworkとSwiftPMの組み合わせには多くのメリットがあります。まず、プロジェクトの依存管理を全てSwiftPMに一元化できるため、CocoaPodsや手動導入を併用する必要がなくなります。これは環境構築をシンプルにし、チーム開発での「このSDKはPodで、このSDKはSwiftPMで…」といった混乱を解消します。特にXcode CloudなどCI環境ではSwiftPM依存はキャッシュが効くため、全依存をSwiftPMにまとめることでCIビルド時間の短縮にも寄与します。
また、SwiftPMはXcodeに統合されているため、ライブラリ導入のユーザーエクスペリエンスが良好です。開発者はXcodeのUIから必要なパッケージを選ぶだけで、依存解決からダウンロード、プロジェクト設定反映まで自動で行われます。XCFrameworkで提供されるバイナリも、このUIフローの中でシームレスに取得・組み込みが可能です。従来のサードパーティツールでは時に起動スクリプトの調整や設定ファイル競合などがありましたが、SwiftPMならそういった問題が起きにくいです。
さらに、SPM経由のバイナリ提供はCI/CDパイプラインにも有利です。前述した通り、大容量のリポジトリをcloneすることなく済むため、CIでの依存取得が高速になり、かつApple公式の継続的インテグレーションサービス(Xcode Cloud)でも効率的にキャッシュされます。Yahoo!広告SDKの事例では、社内フレームワークをXCFramework化しSwiftPM対応したことで、CI上のビルド時間短縮やビルド環境の安定化といった運用改善が得られています。
このように、XCFrameworkをSwiftPMで利用することは、依存管理の統一による利便性向上と、開発効率・CI効率の向上という二面で大きなメリットがあります。AppleもWWDCセッション「Distributing Binary Frameworks as Swift Packages」において、XCFrameworkをSwiftPMで配布する手順とメリットを強調しており、今後ますますこの組み合わせが主流になっていくと考えられます。
Swift PackageのbinaryTarget設定方法:Package.swiftでXCFrameworkのリモートURLとchecksumを指定
それでは具体的に、SwiftPMでXCFrameworkを配布するためのPackage.swift設定方法を説明します。まず前提として、XCFrameworkをZIP圧縮して公開URLを用意しておく必要があります。GitHub Releasesや自社サーバー上にMySDK.xcframework.zip
をアップロードしてください。
次にPackage.swiftファイルで、binaryTargetを利用してそのZIPを指します。具体例を示します:
let package = Package( name: "MySDK", platforms: [ .iOS(.v12), .macOS(.v10_15) ], products: [ .library(name: "MySDK", targets: ["MySDK"]) ], targets: [ .binaryTarget( name: "MySDK", url: "https://example.com/MySDK.xcframework.zip", checksum: "0123456789abcdef...(SHA256ハッシュ)" ) ] )
上記のように.binaryTarget
エントリを追加し、url
に先ほどのZIPの公開URL、checksum
にそのSHA-256ハッシュ値を指定します。ハッシュ値はswift package compute-checksum MySDK.xcframework.zip
コマンドで計算可能です。platforms
セクションは省略も可能ですが、サポートOSを明記すると親切です。また、この例ではtargets名とbinaryTarget名を同じにしていますが、別名でも構いません。その場合はproductsの.library定義でtargetsにbinaryTarget名を指定してください。
Package.swiftを作成したら、そのファイルを含むリポジトリでタグを打ち、GitHubなどに公開します。あとはユーザーがそのリポジトリをSwiftPMから追加すれば、自動的に指定したURLからXCFrameworkがダウンロードされ、プロジェクトに組み込まれる流れになります。重要なのは、URL先のZIPとchecksumが正しく対応していることです。万一ZIPを差し替えた場合は必ずchecksumも更新し、タグも更新(または新規バージョン発行)してください。
このbinaryTargetの設定は、一度正しく行えば以降はソースコード公開の必要もなくSDK配布が可能になるため、大変有用です。なお、Package.swiftでpath
を使ってローカルXCFrameworkを指定することもできますが、それは主に社内利用やローカル開発用であり、一般配布にはURL指定が用いられます。
XCFrameworkをZIP圧縮しリモート配布する手順:アーティファクトバンドルとしてホスティングする方法
前項でも触れましたが、XCFrameworkをSwiftPMで配布する場合、そのホスティング方法もポイントです。一般的な方法としてはGitHub Releasesがよく利用されます。GitHubのリポジトリでReleaseを作成し、ビルドしたMySDK.xcframework.zip
をアセットとして添付します。こうするとhttps://github.com/ユーザー/リポジトリ/releases/download/1.0.0/MySDK.xcframework.zip
のようなURLが得られるので、それをPackage.swiftに記載します。
GitHub以外では、自社で用意したHTTPSサーバーやCDNに置く方法もあります。AWS S3やCloudFront、あるいはFirebase Storageなど、静的ファイルを配布できる場所ならどこでも構いません。重要なのは、安定したURLであることと、ダウンロード帯域が十分にあることです。バイナリはサイズが大きくなりがちなため、可能であればCDN経由でキャッシュされるようにしておくとユーザーに優しいです。
ZIPに含める内容は基本的に.xcframeworkフォルダのみですが、READMEやライセンスを同梱したい場合は別途パッケージングを検討します。ただしSPMはZIP内のファイルに対して厳格なので、変にフォルダ構成を変えない方が安全です。前述のGitHub例のようにReleaseページに説明を書くなどで対応すると良いでしょう。
また、一度公開したZIPは不容易に差し替えないことが肝要です。SwiftPMは同じバージョンタグでは一度取得したバイナリをキャッシュするため、差し替えると利用者側で不整合が起きる可能性があります。もしどうしても差し替える場合は、新しいバージョン番号を振り直すことを強く推奨します。
総じて、XCFrameworkのリモート配布は、適切なホスティングとバージョン管理のもとで行えば難しくありません。SPMによる自動導入がユーザー体験を向上させるため、提供者としては少し手間をかけてでもこの仕組みを整える価値があります。
Package.swift内でのchecksum算出と検証プロセス:XCFramework更新時に必要なハッシュの更新方法
SwiftPMのbinaryTargetで重要な役割を果たすchecksum
フィールドについて補足します。checksum
は前述の通り、XCFramework ZIPのSHA-256ハッシュ値です。SwiftPMはパッケージ取得時に、この値とダウンロードしたファイルのハッシュを比較し、一致しない場合はエラーを出します。これによって、配布者が意図しない改竄を検知したり、ダウンロードエラーを検出したりできます。
開発者がXCFrameworkを更新する際には、新しくビルドした.xcframeworkをZIP化し、swift package compute-checksum
コマンドを使って新しいハッシュ値を算出します。そしてPackage.swift内の該当binaryTargetのchecksum
を書き換えます。さらに、その変更を含めて新たにGitタグを打ちます。例えばバージョン1.0.1でチェックサムが変わったら、1.0.2としてタグ付けし、Package.swiftには1.0.2のZIP URLとそのハッシュを載せます。
実は、ハッシュが変わらない更新というのは基本的にあり得ません。なぜならバイナリ内容が1ビットでも変わればSHA-256値は大きく変動するからです。そのため、配布者はバージョンアップ時には必ずこのchecksum更新が必要と認識しておくことが大事です。もしチェックサムを間違えると、ユーザー側ではfailed to verify checksum
エラーが出ますので、適宜正しい値に修正して再タグ付けする必要があります。
ちなみに、複数のbinaryTargetを一つのPackage.swiftで提供する場合、それぞれに個別のURLとchecksumを指定できます。その場合も同様に各ZIPのハッシュを計算して記入します。更新時には該当するものだけ変更する形です。なお、このchecksum機能はSPM独自のものであり、CocoaPodsなどでは存在しません。ですので、SPMでの配布においてのみ留意すれば良いポイントとなります。
SwiftPM利用時の制限事項:binary targetの他パッケージ依存不可などの注意点
SwiftPMでXCFrameworkを利用する際には、いくつか制限事項があることも覚えておきましょう。まず、binary targetはSwiftPM上で他のパッケージへの依存を宣言できないという制約があります。つまり、XCFramework化されたSDKが内部で別のSwiftパッケージ(例えばAlamofireなど)に依存している場合、それをPackage.swift上で表現することはできません。これを解決するには、依存部分も含めてXCFrameworkにパッケージングするか、あるいはダミーのターゲットを用意してそこから依存させるというワークアラウンドが必要になります。後者の方法については、空のターゲットを作りbinary targetと他パッケージの両方をdependenciesに指定するというテクニックが知られています。
次に、iOSアプリではネストしたFrameworkがサポートされないという点にも注意です。XCFramework内に別のFrameworkを内包する形は基本的にできないため、依存ライブラリを持つSDKの場合、前述のように全て一つのXCFrameworkにまとめるか、Package.swift上で複数binaryTargetとして分ける必要があります。Firebaseのように多数のモジュールがあるSDKでは、複数のXCFrameworkを別々のbinaryTargetとして提供し、それらを統合するパッケージを用意する手法が取られています。
さらに、SwiftPMはパッケージ解決時にGitのタグ単位で見るため、リポジトリ構成にも気を配る必要があります。例えば、タグに対してPackage.swiftをしっかり整備しておかないと、ユーザーは依存追加できません。また、一度公開したタグの内容(特にbinaryTargetのURLやchecksum)を変えると先述の通り問題になりますので、immutableな運用が求められます。
最後に、開発中にSPMでbinary targetを更新したい場合、一旦パッケージキャッシュをクリアする必要がある点も覚えておきましょう。Xcodeのメニュー(File > Packages > Reset Package Caches)でキャッシュをリセットすれば、再度新しいバイナリをダウンロードし直してくれます。
以上がSwiftPM利用時の主な制限事項と注意点です。これらを理解した上で適切に対処すれば、SwiftPMによるXCFramework配布は非常に強力な手段となります。
XCFramework生成時によくあるエラー・トラブルへの対応策:原因と解決方法を網羅的に解説【完全ガイド】
XCFrameworkを扱う際に開発者が遭遇しがちなエラーやトラブルと、その対処法についてまとめます。新しい仕組みであるXCFrameworkですが、適切に作成・利用すれば基本的にトラブルは多くありません。しかし環境設定の不備や互換性の問題などでいくつか典型的なエラーが発生することがあります。ここでは、そうしたよくある問題の原因と解決策を網羅的に解説し、XCFramework導入時のトラブルシューティングに役立てていただきます。
バイナリに含めるアーキテクチャ不足/過剰エラーへの対処:missing required architectureエラーの原因究明と解決
Missing required architecture XXX
というエラーメッセージは、XCFramework利用時に比較的目にすることがあります。これは、アプリをビルドしようとした際に必要なCPUアーキテクチャ向けのコードがXCFramework内に含まれていない場合や、逆に不要なアーキテクチャを含んでいる場合に発生します。
例えば、Mac用アプリでIntel + Apple Silicon両対応(Universal)でビルドしているのに、組み込んだXCFrameworkがIntel(x86_64)版しか提供していなければ、ARM64が足りないと怒られます。逆にiOSアプリでビルド中、XCFramework内にi386(古い32bitシミュレータ)スライスがあると、サポート外アーキテクチャとして警告が出ることもあります。
解決策としては、XCFramework作成者側で不足のないよう全アーキテクチャを含めることが第一です。ターゲットとするプラットフォームに応じて、armv7(古い32bitデバイス)やarm64eなど特殊なものが必要か検討し、必要ならビルドしてXCFrameworkに含めましょう。利用者側でこのエラーに遭遇した場合、最新版のXCFrameworkが出ていないか確認してください。多くの場合、後日ARM64対応版などが公開されて解決するケースがあります。
それでも解決しない場合、自分でXCFrameworkを再構築することも一案です。もしソースが公開されているなら、不足しているアーキテクチャを対象にビルドしてローカルでXCFrameworkを作り直すこともできます。あるいは、どうしてもという場合は、Fatフレームワークを一時的に使う(Arm64重複問題がなければ)か、アプリのビルド設定を制限する(例:Intel Macサポートを切る)という妥協も考えられます。
基本的には、エラーメッセージに書かれているアーキテクチャ名を手掛かりに、何が足りない/余計なのかを判断するのが第一歩です。それに対応する形で、ビルドをやり直すか、設定を変更すればこのエラーは解消するでしょう。
Swiftモジュール不適合エラーへの対処:BUILD_LIBRARY_FOR_DISTRIBUTION未設定によるModule Incompatibleエラーを解消
Swiftで書かれたライブラリのXCFrameworkを利用する際に発生しがちなエラーとして、Module compiled with Swift X.X cannot be imported by the Swift X.Y compiler
というものがあります。これは、XCFramework内のSwiftモジュールが現在使用中のSwiftコンパイラと互換性がない場合に表示されるエラーです。
原因の多くは、ライブラリ提供側がBUILD_LIBRARY_FOR_DISTRIBUTIONを有効にせずビルドしていることにあります。前述した通り、これが無効だとモジュールの互換性は同一コンパイラバージョン内に限定されてしまいます。そのため、例えばライブラリがXcode 12環境でビルドされたものだと、Xcode 13や14では上記エラーが出て使えない、といった事態が起こります。
この問題への根本的な対処は、ライブラリ提供者がBUILD_LIBRARY_FOR_DISTRIBUTIONを有効化してビルドし直すことです。Module Stabilityに対応したXCFrameworkであれば、異なるSwiftバージョン間でも読み込みが可能になります。ライブラリ利用者の立場では、提供元が対応版を出してくれるのを待つか、もしくはソースが公開されていれば自前で上記設定を有効にしてビルドし直すという手もあります。
もしソース非公開で対応版も望めない場合の苦肉の策としては、古いXcodeでビルドする、Swiftのバージョンをライブラリに合わせて下げる、といったことになります。ただし現実的ではないため、可能な限り提供者側に報告し対応してもらうのが良いでしょう。幸い、現在では多くの主要ライブラリがModule Stabilityに対応済みであり、新規に遭遇する頻度は下がっています。いずれにせよ、エラーメッセージに記載のバージョンを確認し、Swift何.xでビルドされたものなのかを判断することがポイントです。
シンボルが見つからない/重複するエラーへの対処:Undefined symbolsやduplicate symbolエラーの原因と対策
リンク時に発生する代表的なエラーとして、Undefined symbols for architecture XXX:
やduplicate symbol
があります。前者は「シンボルが見つからない」、後者は「シンボルが重複して定義されている」ことを示します。
Undefined symbolsエラーの原因は、XCFramework内のライブラリが依存する他のライブラリをリンクしていなかったり、正しいフラグでビルドされていなかったりすることです。例えばC++ライブラリの場合、libc++
とのリンクが必要なのにそれが抜けていると未定義シンボルになります。また、Objective-Cライブラリでカテゴリのシンボルが正しくロードされていない場合なども該当します。対策としては、ライブラリ提供側が必要な依存を明示的にリンクする、利用者側でOther Linker Flagsに-lc++
を追加する、といったことが考えられます。
duplicate symbolエラーは、同じシンボルが二重に定義されている場合に起こります。XCFrameworkに含まれる静的ライブラリを複数個リンクしている場合や、XCFramework内と別に同じオブジェクトファイルをリンクしてしまった場合などが原因です。例えば、あるXCFrameworkにAとB二つのライブラリが含まれ、それぞれ同じ関数foo()を持っているとするとduplicate symbolエラーになります。対策はシンボル名が衝突しないよう変更するか、リンクする対象を整理することです。通常は提供者側でシンボルのユニーク性を保証すべきですが、もし利用側で複数リンクしているなら不要な方を外す対応となります。
これらのエラーは、XCFramework固有というよりは従来から存在するリンクエラーです。ただ、XCFrameworkは一つのパッケージに多くの内容を含むため、原因の切り分けが難しく感じることがあります。エラーメッセージに具体的なシンボル名や重複元ファイルパスが出ますので、それを手掛かりに、どの部分が問題かを探りましょう。場合によっては、問題のあるシンボル名でプロジェクト全体を検索し、どこで定義・参照されているかを突き止めることも有効です。
最終的な対処としては、提供元への問い合わせ・修正依頼も視野に入ります。特に商用SDKであればサポートに連絡し、バグとして修正してもらうのが確実です。
シミュレータとデバイスのバイナリ混在によるエラーの回避:XCFramework作成時にSimulatorコードをAppに含めない対策
こちらは前述の「シミュレーターコード混入問題」と重なる内容ですが、XCFramework関連のトラブルとして再度強調します。Fatフレームワーク時代には、アプリにシミュレータ用コードが混入しているとApp Storeで拒否される、という事態が起きました。XCFrameworkを使っていれば基本的に発生しない問題ですが、例えばビルド設定ミスでXCFrameworkではなく古い.frameworkを参照してしまっていた等の場合に注意が必要です。
アプリ開発者側でできる対策としては、Releaseビルド時に不要アーキテクチャを除去するスクリプトを入れておくことがあります。実際、現在でもCocoaPodsのPodfileにEXCLUDED_ARCHS
設定やlipoによるスライス除去スクリプトを書く例が見られます。ただ、XCFrameworkを正しく使っていればそれらは基本不要です。
そのため、もしシミュレータ関連のエラー(building for iOS, but linking in . dylib built for iOS Simulator
のようなメッセージ)が出た場合は、プロジェクト設定でリンクしているファイルが正しいか確認してください。Xcodeの「Linked Frameworks and Libraries」に誤って.framework
を直接追加していないか、Embed設定が重複していないか等を点検します。根本的には、XCFramework導入時にXcodeが自動設定する内容を変更しないのがベストです。
まとめると、XCFramework導入後のアプリでは本来シミュレータコード混入の心配はないはずなので、この種のエラーが出たら設定漏れ・設定ミスを疑い、対策としては正しいXCFramework参照に統一することが解決策となります。
コード署名や権利設定の不備による実行時エラーの対策:署名エラーやNotarization未実施による問題の回避
XCFramework利用における実行時のトラブルとして、コード署名まわりの問題も考えられます。iOSアプリでは、アプリビルド時に含まれるすべてのFrameworkが自動的にアプリ開発者の証明書で再署名されるため、あまり意識する必要はありません。ただしmacOSアプリの場合、組み込んだXCFramework内のFrameworkが正しく署名されていないと、Gatekeeperがブロックしたり、アプリ起動時にクラッシュしたりする可能性があります。
これを避けるために、前述したように提供者側でDeveloper ID署名をしておくことが望ましいですが、利用者側でも対策できます。Macアプリの場合、ビルド後にcodesign --verify --deep
でアプリバンドル内の署名を検証し、不備がないか確認しましょう。CIでこのチェックを入れておくと安心です。もし署名が必要なFrameworkが署名なしで入っていた場合、エラーが表示されます。その際は手動で再署名する(XcodeでEmbed状態にしておけば自動署名されます)か、提供元に署名付きのものを要求してください。
また、アプリのEntitlements設定も確認が必要です。たとえば対象SDKがキーチェーンやネットワーク拡張など特別な権利を要求する場合、アプリ側で適切なEntitlementを付与しておかないと、実行時にSDKが機能せずエラーが発生します。XCFramework自体は単なる容器ですが、中のライブラリ機能によっては追加設定が必要なケースがあることを認識しましょう。
Notarizationに関しては、MacアプリをDeveloper IDで配布する場合は最終的にアプリバンドル全体をNotarizeすればOKです。XCFramework内のコンポーネント個別には不要です。ただ、提供元がNotarize済みバイナリを提供している場合、エンドユーザーとしてはGatekeeper警告に遭遇しにくくなるため、そうした品質のものを選ぶのも一つの手です。
以上のように、コード署名や権利設定の不備に起因する問題は、主にMac向けで注意が必要です。iOSではビルドプロセス任せで概ね大丈夫ですが、Macでは開発者自身が積極的に検証・対処して、安全にSDKを組み込むようにしましょう。
Xcode/Swiftバージョン差異による互換性問題への対処:新旧コンパイラ間のABI不一致への対応策
最後に、XcodeやSwiftのバージョン差による互換性問題とその対処について触れます。基本的には前述したModule Stabilityの話と重なるのですが、SwiftのABI(Application Binary Interface)が完全に安定したのはSwift 5以降です。それ以前のSwiftでビルドされたライブラリは、新しいSwiftコンパイラでは読み込めません。またSwift 5.3で導入されたコンカレントモジュールなど、細かな言語仕様変更もあり、Swift製ライブラリはXcodeのアップデート時に問題が表面化することがあります。
対処法としては、常に最新のツールでXCFrameworkをリビルド・再配布することが重要です。ライブラリ提供者は、Xcodeのメジャーアップデート(例えば14→15)時には念のため再ビルドして動作確認し、必要なら新バージョンをリリースすると良いでしょう。幸いSwiftのABIは5以降安定していますので、BUILD_LIBRARY_FOR_DISTRIBUTIONが有効であれば緊急性は低いですが、それでもSwiftUIなど新しいフレームワークとの組み合わせで予期せぬ問題が起こる可能性もゼロではありません。
利用者側としては、もしライブラリが古いXcodeでビルドされたまま更新されていない場合、Xcode側でモジュールを無視するオプション(DYLD_LIBRARY_PATH
をいじるなど非推奨手段)もありますが、現実的ではありません。できる限り提供元にアップデートを促しましょう。オープンソースであれば自らPRを出すのも手です。
まとめると、XcodeやSwiftのバージョン違いによる問題は、提供者がModule Stabilityに対応し、適宜ビルド更新することで大半が防げます。利用者も、新旧バージョン移行期にはドキュメントやサポート情報を確認し、不具合が報告されていないかチェックすると良いでしょう。互換性問題は事前の情報共有と準備で乗り越えられるケースがほとんどです。
XCFrameworkと従来Framework(Universal Framework)の違い:互換性・構造・サポート範囲の比較
最後に、XCFrameworkと従来のFramework(いわゆるUniversal/Fat Framework)の違いを整理します。これまでの内容で多くの差異に触れてきましたが、ここで改めて両者を比較し、XCFrameworkの優位性を明確にしましょう。
Universal(Fat)Frameworkとは何か:複数アーキテクチャを一つにまとめた旧来のフレームワーク形式
まず、従来のUniversal Framework(Fat Framework)とは何だったのかをおさらいします。Universal Frameworkとは、複数のCPUアーキテクチャに対応するバイナリを一つに纏めた.frameworkのことを指します。典型的には、arm64(デバイス用)とx86_64(シミュレータ用)の2つのアーキテクチャを含むiOS向けFrameworkがそれに当たります。開発者はlipo
コマンドを使用してそれぞれの.frameworkからバイナリ(MyLib
など)を取り出し、一方に結合してFatバイナリを作成し、それをFrameworkに埋め込むことでFat Frameworkを作っていました。
Fat Frameworkの利点は、開発中にデバイスでもシミュレータでも一つのFrameworkファイルを使い回せる点でした。一方デメリットとしては、アプリリリース時に余計なスライス(例えばシミュレータ用x86_64)を削除しなければならないこと、そもそもApple非公式の手段であることなどが挙げられます。Fat Frameworkは言わば「Universal Binary」(ユニバーサルバイナリ)のFramework版でしたが、macOSでのUniversal 2バイナリとは異なり、プラットフォームを跨ぐものではなく一つのOS内の複数CPUを対象としたものでした。
XCFrameworkのディレクトリ構造と従来.framework構造の比較:各プラットフォームごとにフォルダ分割された仕組み
続いて、XCFrameworkと従来Frameworkの構造の違いです。従来の.frameworkは単一の「.framework」ディレクトリであり、その中に単一の実行ファイル(バイナリ)とResources、Headers、Info.plistなどが入っていました。一方XCFrameworkは、.xcframeworkディレクトリの中に複数の.frameworkフォルダやライブラリフォルダを抱える構造になっています。各フォルダにはそれぞれ別プラットフォーム向けのバイナリが格納され、ルートのInfo.plistでそれらを索引する形です。
例えば、MySDK.xcframework
内にios-arm64
とios-arm64_x86_64-simulator
という二つのフォルダがあれば、前者にはデバイス用MySDK.framework、後者にはシミュレータ用MySDK.frameworkが入っています。さらにmacOS用にmacos-arm64_x86_64
フォルダがあれば、Universal2なMySDK.frameworkが入っている、といった具合です。対して従来のFat Frameworkでは、これらを全て一つのMySDK.framework内の単一バイナリにアーキテクチャ連結していました。
この構造上の違いから、XCFrameworkは新しいアーキテクチャやプラットフォームを後から追加しやすい利点があります。単にフォルダを増やして別の.frameworkを入れればよいのです。一方Fat Frameworkは一つのバイナリに全て混ぜ込む必要があるため、組み合わせや再結合が柔軟ではありませんでした。構造の違いは概念的にはそれだけですが、シンプルな違いが運用面の大きな差につながっています。
複数プラットフォーム・アーキテクチャ対応の違い:公式フォーマットのXCFramework vs 非公式Fatフレームワーク
XCFrameworkとFat Frameworkの目的上の違いとして、対応範囲があります。XCFrameworkはAppleが公式に「複数プラットフォーム・複数アーキテクチャ対応の配布フォーマット」と位置づけており、iOSだけでなくmacOS、tvOS、watchOSといったすべてのAppleプラットフォームを単一パッケージで扱えます。これに対しFat Frameworkは原理的に一つのOSに限定されていました。つまり、XCFrameworkはクロスプラットフォーム対応、Fat Frameworkは単一プラットフォーム内のUniversal対応という棲み分けです。
また、Fat Frameworkは冒頭から述べている通りApple非公式でしたが、XCFrameworkはXcode 11以降で完全に統合された正式機能です。そのためサポート状況も大きく異なります。XcodeはXCFrameworkに関してはUI上でもうまく扱えるようになっており、アーカイブ時に不要スライスを自動除去する必要もありません。Appleのプラットフォームサポートも、Catalystのような特殊ケースまで含めてXCFrameworkで対処する前提になっています。
総じて、XCFrameworkは21世紀のApple開発標準と言えるフォーマットであり、Fat Frameworkは過渡期の互換手段であったと言えるでしょう。いまやFat Frameworkが必要とされる場面はほぼ無く、XCFrameworkでその上位互換の役割を果たせる状況です。
利用方法や統合手順の違い:Xcodeへの追加とリンク設定、SwiftPM対応可否の比較
開発者目線での利用方法の違いにも触れておきます。Fat Frameworkを使う場合、開発者はしばしばXcodeプロジェクトにその.frameworkをドラッグ&ドロップし、Embedded Binaries
やLinked Frameworks
に追加していました。XCFrameworkも基本的には同様にドラッグ&ドロップで追加できますが、リンク時にXcodeが自動選択するためFatと違って追加先は「Frameworks, Libraries, and Embedded Content」に一つだけ置けばOKです。Fat Framework時代はシミュレータビルド時のみ別Frameworkに切り替えるスクリプトを組むこともありましたが、XCFrameworkではそうした手間は不要です。
また、CocoaPodsやCarthageでの挙動も異なります。CocoaPodsはFat Framework利用時、各アーキテクチャ別のビルド→Fat結合→導入というプロセスをPodspecのscript
で記述したりしていました。しかしXCFrameworkではPodspecにそのまま指定できるため、エレガントに統合できます。Carthageは前述の通り–use-xcframeworks対応が入り、現在ではほぼXCFramework前提です。
最も大きな違いは、Swift Package Managerに対応できるか否かでしょう。Fat Frameworkはソースコードがない状態ではSPMで配布できませんでした(現状、SPMのbinaryTargetは.xcframeworkのみサポート)。つまり、Fat Frameworkを主軸とした配布ではSwiftPMを使えず、CocoaPods/Carthageに頼るほかありませんでした。一方XCFrameworkならSPMによる配布が可能なため、前述した様々なメリットを享受できます。
このように、統合手順の簡易さやモダンなツール対応においても、XCFrameworkは従来方式より勝っています。Apple自身が提供するライブラリ(例えばSwift Chartsなど)はXCFrameworkを前提としているものもあり、今後さらにこの差は広がっていくでしょう。
互換性と将来性の違い:XCFrameworkのほうが新アーキテクチャ追加に柔軟で将来的な変更に強い
最後に、互換性と将来性の観点で比較します。Fat Frameworkは前提として「将来のアーキテクチャ増加」や「新OS登場」を考慮しておらず、あくまで当時存在する範囲での便宜的ソリューションでした。そのためCatalystやARM Macが登場した時に問題が発生し、もはや立ち行かなくなりました。一方XCFrameworkはAppleが「将来を見越したフォーマット」として設計しただけあり、今後何が出てきても対応しやすい柔軟さがあります。
たとえば、もし将来Appleが仮にx86_64以外のIntel CPU(極端な例ですが)やARMの新拡張(ARMv10など)を導入しても、XCFrameworkならそのsliceを追加すれば対応できます。また、新規デバイス向けOSが出ても同様です。Fat Frameworkでは到底追いつけない速度で、XCFrameworkなら変化に対応可能です。
また、互換性という意味では、前述したSwiftのModule Stability問題も含め、XCFramework+BUILD_LIBRARY_FOR_DISTRIBUTIONによってバイナリの長期利用が視野に入ります。Fat Framework時代はSwift製Frameworkを配布するのが非現実的でしたが(Swift5以前モジュール不安定のため)、XCFramework時代の今はSwift SDKも普通に配布されています。このように、言語仕様の進化にもキャッチアップしやすい点も将来性の高さと言えるでしょう。
総合的に見て、XCFrameworkは互換性維持と将来拡張への対応力で従来方式を大きく凌駕しています。Appleも強力に推進している以上、今後Fat Frameworkに戻る理由はほぼありません。古いプロジェクトで互換性維持のためFat Frameworkを使い続けるケースはあるかもしれませんが、新規開発やライブラリ刷新のタイミングでは積極的にXCFrameworkを採用するのが賢明です。
Objective-CやC++ライブラリのXCFramework化:既存コードをXCFrameworkに対応させる方法
ここでは、特にObjective-CやC++で実装されたライブラリをXCFramework化する際のポイントについて説明します。Swiftで書かれたライブラリの場合と基本手順は同じですが、言語特有の注意点があります。また、既存のプロジェクトからFrameworkターゲットを作成する方法や、モジュールマップの設定、Bridging Headerの扱いなども取り上げます。Navitimeの事例では、C++やObjective-C製の社内フレームワーク群をXCFramework化してSwiftPM配布する取り組みが行われています。その知見も踏まえ、以下に解説します。
Objective-C/C++製ライブラリをFramework化する手順と注意点:既存プロジェクトからフレームワークターゲットを作成する方法
まず、既存のObjective-CやC++で書かれたコードをXCFramework化するには、前提としてそのコードをビルドしてFramework(または静的ライブラリ)を生成できる状態にする必要があります。Xcodeプロジェクト内で作っているライブラリであれば、新たにFrameworkターゲットを追加し、そこに既存のソースファイルを組み込む方法が考えられます。ターゲットの種類は、Objective-CならCocoa Touch Framework(iOS向け)やCocoa Framework(macOS向け)、C++ならStatic LibraryやFramework(C++もFramework化可能です)を選択します。
注意点として、C言語やC++で実装されたライブラリの場合、Frameworkターゲットを作った段階ではまだモジュール(module)情報がないため、後述のmodulemap設定をする必要があります。Objective-Cの場合は自動でモジュールヘッダが生成される(Umbrella Headerを用意する)ので比較的楽です。ただしカテゴリの扱いなど、公開ヘッダと非公開ヘッダをしっかり分けて、モジュールインターフェースを正しく構築することが大切です。
Frameworkターゲットを作成したら、通常のアプリと同様に各プラットフォーム向けにビルドできるか確認します。ここから先のXCFramework化の流れは既に述べた手順(Archive→xcodebuild -create-xcframework)と同じです。Navitimeの例でも、まず社内C++ライブラリをFramework化し、XCFrameworkで包む対応が取られています。
最後に、既存プロジェクトのビルド設定も確認しましょう。特にC++ではC++ Standard Library(libc++ vs libstdc++)の選択や、Exceptionsの有無といった設定が揃っていないとリンクエラーになることがあります。FrameworkターゲットのBuild Settingsで、他のプロジェクトと同じ設定になるよう合わせておくと安全です。
Staticライブラリ(.a)+ヘッダをXCFrameworkに含める方法:.aファイルとHeadersフォルダのパッケージング
XCFrameworkはFrameworkだけでなく、静的ライブラリ(.a)とヘッダ群の組み合わせも格納できます。もしライブラリが「.aファイル+ヘッダ一式」という形式の場合、わざわざFrameworkターゲットにしなくても、それをXCFrameworkに含めることが可能です。
手順としては、xcodebuildコマンド利用時に-library
オプションで静的ライブラリファイル(例:libMyLib.a
)を指定し、併せて-headers
オプションでヘッダファイルを集めたディレクトリへのパスを指定します。例えば:
xcodebuild -create-xcframework \ -library path/to/libMyLib.a \ -headers path/to/Headers \ -output MyLib.xcframework
こうすると、MyLib.xcframework
内にHeaders
フォルダが作られ、その中に提供したヘッダ群が配置されます。利用者がこのXCFrameworkをXcodeに追加すると、Xcodeはヘッダ検索パスを自動設定し、ヘッダが参照できるようになります。
注意点として、Headers内にmodule.modulemapが存在するかどうかです。Objective-CのみのライブラリならUmbrella Header(例えばMyLib.h)を用意し#include
する形でも良いですが、C++を含む場合はmodulemapを用意して、ヘッダをモジュール化することが推奨されます。modulemapがないとSwiftからインポートしづらくなるケースがあります。
なお、静的ライブラリ版XCFrameworkを作る場合でもBUILD_LIBRARY_FOR_DISTRIBUTIONを有効にしたビルドが望ましいです。これはSwiftのモジュール安定性には関わりませんが(静的ライブラリは純粋なバイナリのみ)、特にSwiftと組み合わせて使う場合にヘッダの内容が変化した際の互換性などに配慮が必要だからです。
Modulemapの作成と公開ヘッダ設定:Swiftから利用可能にするためのmodule.modulemap作成方法
Objective-CやC/C++ライブラリをXCFramework化する際、modulemapの設定は重要なポイントです。modulemapとは、Clang/Swiftコンパイラに対してモジュール(module)のエクスポート情報を伝えるファイルです。
Framework形式であればXcodeが自動生成することも多いですが、静的ライブラリ+ヘッダの場合は手動でmodulemapを作る必要があります。またFrameworkでも、公開ヘッダを適切に設定しておかないと、意図したAPIがエクスポートされないことがあります。
modulemapの基本形は:
module MyLib [system] { header "MyHeader1.h" header "MyHeader2.h" export * }
のようになります。[system]
はヘッダ内の警告を無視する場合などに付けます。header
で公開したいヘッダファイルを列挙し、export *
でそれら全てをモジュールに含める指定です。このmodulemapをHeadersフォルダ内に置いておけば、XCFrameworkに組み込まれ利用時に認識されます。
Frameworkの場合、XcodeのBuild SettingsでPrivate Header / Public Headerを切り分け、Public指定されたヘッダがモジュールに含まれます。Umbrella Headerも用意しておくと良いでしょう。XcodeはUmbrella Header(通常フレームワーク名と同じ.h)を自動生成することもありますが、内容をカスタマイズしたい場合は自分で作成し、modulemapからumbrella header "MyLib.h"
と指定できます。
modulemapが適切に機能すると、Swiftからimport MyLib
とするだけでObjective-C/C++ライブラリの公開APIが使えるようになります。特にC++の場合、modulemap無しだとブリッジングが困難なので、この設定は肝心です。Navitimeの事例でも、この対応によりC++中心の社内ライブラリをSwiftPMから利用可能にしています。
Swiftとのブリッジング:Objective-Cヘッダを介したSwiftからの呼び出しと必要な設定
Objective-CやCのライブラリをSwiftから使う際には、Bridging Headerまたはmodulemapによるブリッジが必要です。XCFrameworkとして配布されるObjective-Cライブラリの場合、基本的にはmodulemap/Public Headerが整備されていれば、利用者側でBridging Headerを用意する必要はありません。import MyLib
だけでSwiftコードから呼び出せます。
しかし、もしXCFramework化されたライブラリがモジュール未対応(modulemap無し)で提供された場合、利用者はプロジェクトにBridging Headerを作成し、その中で#import
のようにヘッダをインポートする必要があります。これによりSwiftコンパイル時にそのヘッダがブリッジされ、Objective-C APIがSwiftに露出します。
ライブラリ提供者の立場としては、可能な限りmodulemapとPublic Headerを適切に設定し、ユーザーがBridging Header不要で利用できるように配慮すべきです。特に商用SDKでは、その方が導入手順が簡潔になり評価が高まります。
C++については、Swiftから直接呼び出すことはできないため、Objective-C++経由のラッパーを提供するのが一般的です。例えばC++クラスをObjective-Cクラスでラップし、そのヘッダを公開する形です。XCFrameworkにそうしたラッパーを含めておけば、Swift→ObjC++→C++という呼び出し経路ができあがります。Bridging Headerやmodulemapの仕組み自体はObjective-C向けと同じなので、ラッパーヘッダをPublicにするだけで問題ありません。
最後に、Swiftから利用する上で問題になりがちな命名の衝突やNS_SWIFT_NAMEマクロなども確認しておくと良いでしょう。Objective-Cのクラス名がSwiftの名前空間で衝突しないようPrefixを付ける、Enumを使う場合はNS_ENUM
マクロを使う等、通常のSDK開発と同様のベストプラクティスが適用されます。
C++コードの互換性とビルド設定:libc++標準ライブラリのリンク設定やextern “C”の考慮
C++ライブラリをXCFramework化する場合の留意点も補足します。まず、C++の場合AppleのClangでは標準ライブラリとしてlibc++
が使われますが、古いプロジェクトではlibstdc++
(GCC由来の古い標準ライブラリ)が指定されていることもあります。XCFramework化にあたっては、libc++に統一することをお勧めします。Xcode 10以降ではlibstdc++は非推奨となっているためです。
また、C++には名前改名(Name Mangling)の問題があります。C++関数をCから利用したりSwiftから利用する場合、extern "C"
指定で関数をエクスポートしないと名前が変換されリンカで見つからなくなります。Objective-C++のラッパーを提供する際には、その内部でC++コードを呼ぶ形にし、SwiftからはObjective-C API経由で使うようにするとこの問題は回避できます。
C++特有のもう一つの点は、Exceptionの扱いです。SwiftからはC++の例外を直接受け取れないため、例外を投げるようなC++コードを内部に持つライブラリでは、例外ハンドリングの仕組みも考慮する必要があります。場合によっては例外をcatchしてNSErrorに変換するラッパーを用意するなどの対策が求められます。
ビルド設定では、他にもObjective-C++の場合にARCを有効にするか、ビットコード(iOS向けでは現在非推奨だがlegacyサポート)を含めるか否か、といった項目もあります。プロジェクトに合わせて適切に設定してください。
総じて、Objective-C/C++ライブラリのXCFramework化は、Swiftライブラリに比べると少し準備が多いですが、きちんと対応すれば問題なく提供できます。Navitime社内でもC++100%のフレームワークをXCFramework+SwiftPMで配布し、Swiftから利用する体制を構築しています。これは、従来では考えにくかったC++ライブラリの容易な社外提供を可能にした例と言えます。
プラットフォームごとの対応方法(iOS、macOS など):各OS向けXCFramework構築のポイントを解説
最後に、各プラットフォーム(iOS、macOS、Catalyst、tvOS、watchOSなど)ごとにXCFrameworkを構築・提供する際のポイントを解説します。基本的な流れは全て似ていますが、それぞれのプラットフォーム特有の注意点があります。
iOSデバイスとiOS Simulator向けXCFramework構築時のポイント:アーキテクチャ(arm64/x86_64)別にビルドし同梱
iOS向けXCFrameworkは最も一般的なケースです。iOSには実機(arm64、以前はarmv7も)とSimulator(x86_64およびApple Siliconではarm64)という2種類のビルドターゲットが存在します。XCFrameworkにはこの両方を含めることが必須と言えます。手順はすでに述べた通り、device向けとsimulator向けにそれぞれArchiveまたはビルドを行い、その2つをxcodebuild -create-xcframework
で統合するだけです。
注意点は、Simulator向けビルドでApple Silicon(macOS ARM)用も含めるかどうかです。Xcode 12以降ではデフォルトでarm64シミュレータもビルドされますので、特別な理由がなければそのままで構いません。XCFrameworkにios-arm64_x86_64-simulator
という形で一括して入ります。ただ、もし古いXcode環境(Intel MacでXcode 11など)で作業している場合、arm64シミュレータはビルドできません。その際はx86_64シミュレータ版だけでもXCFramework化できますが、Apple Silicon Macでシミュレータ動作させるユーザーには不足となるので、可能な限り新しいXcode環境でarm64シミュレータ込みでビルドするようにしましょう。
出来上がったiOS用XCFrameworkは、iPhone/iPadアプリ開発者がXcodeに組み込んで使う想定です。Embed設定はEmbed & Sign
(動的ライブラリの場合)にしておけば、App内に含まれ実機で動作します。なお、BitcodeはXcode 14で廃止されましたが、それ以前はBitcode対応も考慮する必要がありました。最新環境では気にしなくてOKです。
macOS向けXCFramework構築時のポイント(IntelとApple Silicon両対応):ユニバーサル2バイナリの利用とRosettaへの配慮
macOS向けのXCFrameworkは、Intel(x86_64)とApple Silicon(arm64)の両アーキテクチャ対応を行う点がポイントです。基本的な方針として、Universal 2(x86_64 + arm64)のバイナリを含むFrameworkを1つ用意し、それをXCFramework内に格納する形がおすすめです。XcodeでAny Mac
向けにArchiveすれば、デフォルトでUniversalバイナリが生成されます。別々にIntel用とARM用をビルドして後でlipo結合しても良いですが、Xcode任せで構いません。
Catalystと区別するため、macOS用FrameworkのSupported Platform
はmacos
となります。XCFramework内では例えばmacos-arm64_x86_64
というLibraryIdentifierで識別されます。
Rosettaへの配慮という点では、Intel Mac用バイナリを提供しない選択も将来的には考えられます。しかし現状多くのMacがIntelで動いており、AppleもUniversalアプリの提供を推奨しています。そのため当面はIntel+ARM両対応が標準でしょう。XCFrameworkでIntel非対応とする場合、platforms
指定で.arm64のみにするなど出来なくはないですが、あまり現実的ではありません。
なお、macOS用FrameworkはiOS用と違い署名やNotarizationの問題があるため、配布時にはDeveloper IDで署名しておくと親切です(前述)。XCFramework自体にはどちらでも入れられますが、エンドユーザー環境での読み込みを円滑にするためには署名済みが好ましいです。
Mac Catalystプラットフォームのサポート方法と注意点:iOS用FrameworkをCatalyst向けにビルドし変換する手順
Mac Catalyst(UIKit for Mac)はiPadアプリをMac向けに動作させる仕組みですが、ライブラリ観点ではios
プラットフォームの派生(ios-macabi
とも呼ばれる)として扱われます。Catalyst向けにXCFrameworkを用意する場合、Xcodeでビルドターゲットを「Any Mac (Catalyst)」に切り替えてFrameworkをビルドし、それを他と同様にXCFrameworkに含めます。
XCFrameworkのInfo.plist上は、Catalyst用バイナリはSupportedPlatform
がios
、SupportedPlatformVariant
がmaccatalyst
として記録されます。LibraryIdentifierもios-arm64_x86_64-maccatalyst
のようになります。つまりCatalystはiOSの特殊ケース扱いなのです。
実際の手順としては、iOS用FrameworkターゲットでMac Catalystを有効にする設定(ターゲットのBuild SettingsでSupports Mac Catalyst
をYesに)をオンにし、ArchiveするとCatalyst用.xcarchiveが得られます。それを-framework
に指定してXCFramework化します。Catalyst専用に別ターゲットを作る方法もありますが、多くの場合iOSターゲットを流用できます。
注意点として、CatalystではサポートするOSバージョン(macOS 10.15以上など)に気を付けること、またiOS特有の機能(例えばHealthKitなど一部はCatalyst未対応)が含まれているとリンクエラーになる可能性があります。Catalyst向けビルドが通るかどうかをまず確認し、問題なければXCFrameworkに加えましょう。
Catalyst用バイナリを提供するかどうかはSDK提供者の判断になります。iOS版をMacに持ってくるニーズがある場合は対応すべきですが、不要なら省くこともできます。その場合Catalyst環境ではiOS版をRosetta経由で動かすことになりますが、それでも動くケースもあります。
tvOSプラットフォーム向けにXCFrameworkを構築する方法と注意点:tvOSデバイス/Simulator両対応のFrameworkを準備
tvOS向けXCFrameworkも基本はiOSの場合と似ています。tvOSにはarm64のApple TVデバイスとx86_64(およびARM64 Mac上のARM64? 実際Mac上ではRosetta? Apple TV SimulatorはIntel? ※Apple TV SimulatorはIntelで動作。Apple Silicon MacだとRosetta? この辺厳密にはARM64 Simulatorもあるかもしれませんがドキュメント不足)のSimulatorがあります。原理上はiOSと同様です。
XcodeでtvOS用Frameworkターゲットを作成し、Archiveをデバイス向けとSimulator向けで行います。それらをxcodebuild -create-xcframework
で統合するとtvos-arm64
とtvos-x86_64
(あるいはtvos-arm64_x86_64-simulator
)を含むXCFrameworkが出来上がります。Info.plistでもSupportedPlatform = tvos
として区別されます。
注意点は、tvOSでは利用できないAPI(例えばUIWebViewや一部のフレームワーク)がiOSに比べて多いので、コードがtvOSでコンパイル通るか確認することです。また、tvOS Simulatorは64bit IntelのみなのでApple Silicon Mac上でもRosettaで動く場合があり、パフォーマンスに影響があります。もっとも、これは利用者側の問題であり、提供者としては対応しようがありません。
tvOS向けの需要がどれほどあるかにもよりますが、Apple TVアプリ向けSDKを提供するならXCFrameworkにtvOSバイナリを含めると喜ばれます。逆に不要なら省いても構いません。その判断はSDKの利用シナリオによるでしょう。
watchOSプラットフォーム向けにXCFrameworkを構築する方法と注意点:ビルド対象にwatchOSを含め複数アーキテクチャを統合
最後にwatchOSです。Apple Watch向けのライブラリはかなり限定的な用途ですが、ヘルスケア系SDKなどで提供されることがあります。watchOSも基本は同じで、armv7k(32-bit Apple Watch)やarm64_32(64-bit Apple Watch用縮小アドレッシング)と、i386(Simulator)といったアーキテクチャがあります。
XcodeではwatchOS用Frameworkターゲットを作り、Archiveするとwatchos-armv7k_arm64_32
(デバイス)とwatchos-i386_arm64
(Simulator? Apple SiliconではARM64かな?)のような成果物が得られます。これらをXCFrameworkにまとめるだけです。
注意点は、watchOSのSimulatorは実行速度が遅く、あくまで開発用であること、またFrameworkのサイズに厳しい制限があることなどです。Watch向けはシビアなリソース制限があるため、不必要なコードを入れないようにしたり、デバイス上で効率よく動くことを確認するなど品質面にも気を遣いましょう。
もしSDKの対象プラットフォームとしてwatchOSをサポートするなら、XCFrameworkに含めること自体は難しくありません。ただ、利用者が限られることも多いので、要望がある場合にのみ対応する方針でも良いかもしれません。
以上、各プラットフォーム別のXCFramework構築ポイントを述べました。総じて言えるのは、XCFrameworkフォーマット自体がプラットフォーム差異を吸収してくれるため、我々開発者は各プラットフォームごとに適切にビルドして入れ込むだけで良いということです。これまで煩雑だった複数OS対応SDK配布が、XCFrameworkによって飛躍的にシンプルになったことを改めて感じるでしょう。