XCFrameworkは、iOS実機・iOS Simulator・macOSなど複数のプラットフォーム向けにビルドしたフレームワークやライブラリを、1つの.xcframeworkバンドルにまとめるAppleの配布形式です。この記事では、Fat Frameworkでは実機とSimulatorのarm64を共存させられない理由から、静的・動的の選び方、xcodebuild -create-xcframeworkの通しスクリプト、Swift Package Managerでの配布、Xcode 15以降の署名検証までを、Appleのドキュメントとリリースノートを根拠に整理します。2020年前後の解説記事にある「Bitcode対応は必須」などの前提が、Xcode 14以降でどう変わったかも扱います。
まとめ:XCFrameworkの要点と作成・配布の判断
- XCFrameworkはXcode 11で導入された、プラットフォームごとのバイナリを別フォルダに分けて同梱する形式です。lipoで1つのバイナリに合成するFat Frameworkと違い、同じarm64を持つ実機版とSimulator版を共存させられます。
- 作成はプラットフォームごとに
xcodebuild archiveを実行し、xcodebuild -create-xcframeworkでまとめます。ビルド設定はBUILD_LIBRARY_FOR_DISTRIBUTION=YESとSKIP_INSTALL=NOが前提です。 - Bitcodeは不要です。Xcode 14でApp StoreがBitcode付きの提出を受け付けなくなり、Xcode 15でサポート自体が削除されました。Xcode 27はApple silicon専用になり、macOS 27以上を対象にするとx86_64が既定のアーキテクチャから外れます。
- Swift Package Managerでは
binaryTargetで配布します(Swift 5.3/Xcode 12以降)。リモート配布はzipとswift package compute-checksumで出したSHA-256が要ります。 - Xcode 15以降は署名が検証され、署名者が変わるとビルドが止まります。CocoaPods trunkは2026年12月2日に新規Podspecの受け付けを止める予定なので、これから配布するならSwiftPMを主経路にしてください。
XCFrameworkの仕組みとFat Frameworkとの違い
プラットフォーム別フォルダとInfo.plistによる構造
.xcframeworkの中身は、プラットフォームとアーキテクチャの組み合わせごとのフォルダ(例:ios-arm64、ios-arm64_x86_64-simulator)と、それらを列挙したInfo.plistです。Xcodeはビルド時にこのInfo.plistを読み、ビルド先に合うフォルダのバイナリだけをリンクします。
次は静的ライブラリを1枚だけ含むXCFrameworkのInfo.plistの抜粋です(外側のplist・dict要素は省略)。AvailableLibrariesの各要素が1フォルダに対応します。
<key>AvailableLibraries</key>
<array>
<dict>
<key>HeadersPath</key> <string>Headers</string>
<key>LibraryIdentifier</key> <string>macos-x86_64</string>
<key>LibraryPath</key> <string>libGreet.a</string>
<key>SupportedArchitectures</key>
<array><string>x86_64</string></array>
<key>SupportedPlatform</key> <string>macos</string>
</dict>
</array>
<key>CFBundlePackageType</key> <string>XFWK</string>
<key>XCFrameworkFormatVersion</key> <string>1.0</string>
Simulator向けのフォルダにはSupportedPlatformVariantにsimulatorが入り、Mac Catalyst向けはmaccatalystになります。SupportedArchitecturesに書かれたアーキテクチャがビルド先と合わないと、そのフォルダは選ばれません(症状は後述)。
Fat Frameworkの制約:実機とSimulatorのarm64衝突
以前は、実機用(arm64)とSimulator用(x86_64)のバイナリをlipoで1つに合成したFat Framework(Universal Framework)が非公式に広く使われていました。1つのバイナリには同じアーキテクチャのスライスを2つ入れられません。Simulatorがx86_64だけで動いていた間は、これで困りませんでした。
Apple SiliconのMacでSimulatorがarm64で動くようになり、前提が崩れました。Carthage 0.37.0(2021年2月1日)のリリースノートは、Xcode 12でSimulatorにApple Siliconのサポートが入り、実機版とSimulator版の両方がarm64でビルドされるためXCFrameworkが必要になった、と説明しています。AppleのCreating a multiplatform binary framework bundleも、iOS用とiOS Simulator用のスライスをlipoで1つにまとめないよう明記しています。以下の作成手順も、このドキュメントの記述に沿っています。
2020年前後の解説から変わった前提:Bitcode・x86_64・Xcode 27
検索上位には2020〜2023年に書かれたXCFrameworkの解説が多く、当時の前提がそのまま残っています。2026年11月時点で書き換えが必要なのは次の4点です。
| 当時の前提 | 現在 | 変わった版 |
|---|---|---|
| Bitcode対応は必須 | サポート削除・設定は無効 | Xcode 15(14で非推奨化) |
| Simulatorはx86_64でも動く | 既定のランタイムはApple silicon用 | Xcode 26 |
| Intel MacでもXcodeが動く | Apple silicon専用 | Xcode 27 |
| macOS版は常にUniversal | macOS 27以上の対象はarm64のみが既定 | Xcode 27 |
Xcode 14のリリースノートには、App StoreがXcode 14からBitcode付きの提出を受け付けなくなったこと、Bitcodeを明示的に有効にすると「Building with bitcode is deprecated」という警告が出ることが書かれています。さらにXcode 15のリリースノートでBitcodeのサポート自体が削除され、ENABLE_BITCODEは効果を持たなくなりました。ENABLE_BITCODE=YESや-debug-symbolsでの.bcsymbolmap同梱を手順に含めている古いスクリプトは、その部分を削って構いません。
Xcode 26からは、ダウンロードするSimulatorランタイムが既定でIntel Mac対応を含まない小さい版になりました。Downloading and installing additional Xcode componentsによると、Intel MacやRosettaの実行先を使う場合は従来どおりuniversal版が入り、コマンドでは-architectureVariantにuniversalかarm64を指定して選べます。
xcodebuild -downloadPlatform iOS -architectureVariant universal
Xcode 27のリリースノートによると、Xcode 27はApple siliconのMacにしかインストールできません(Appleの動作要件表ではmacOS Tahoe 26.6以降)。またMACOSX_DEPLOYMENT_TARGETを27.0以上にするとARCHS_STANDARDからx86_64が外れます。必要ならARCHSへ明示的に追加できます。同じリリースノートで従来のリンカld64が削除され、-ld_classicも使えなくなりました。
一方で、Simulator版のx86_64を今すぐ外すべきではありません。利用者の中にはIntel MacでXcode 26.6以前を使い続けている開発者がいます。ARCHSを未設定のままにすれば、Simulator版にはarm64とx86_64の両方が入ります。x86_64を外すのは、利用者全員がApple siliconに移ったと確認できてからにしてください。Intel MacでのXcodeの扱いはXcodeの最新バージョンは27|確認・アップデート手順とIntel Macは26.6まで、Xcode 27の動作要件はXcode 27はいつリリースされた?正式版27A266aの動作要件とXcode 26からの移行点にまとめています。
xcodebuild -create-xcframeworkによるXCFrameworkの作成
静的か動的か:MACH_O_TYPEの選択
最初に決めるのは、フレームワークを静的にするか動的にするかです。ビルド設定のMACH_O_TYPEで、Appleのビルド設定リファレンスどおりstaticlibが静的、mh_dylibが動的です。どちらでもXCFrameworkにできますが、利用側の設定と配布物の中身が変わります。
| 項目 | 静的 | 動的 |
|---|---|---|
| MACH_O_TYPE | staticlib | mh_dylib |
| .frameworkの埋め込み | Embed & Sign | Embed & Sign |
| アプリに入るもの | リソースのみ | バイナリとリソース |
| dSYM | アプリのdSYMに含まれる | フレームワークごとに同梱 |
AppleのCreating a static frameworkは、Xcode 15以降の静的フレームワークも利用側で「Embed & Sign」を選ぶよう指示しています。Xcode 15のリリースノートのとおり、埋め込み時にフレームワーク内の静的アーカイブは取り除かれ、コードはアプリ本体にリンクされます。「Do Not Embed」を選ぶのは.aの静的ライブラリをそのまま入れる場合です。
商用SDKを1つ配るだけなら、起動時のロードが増えない静的を選んでください。アプリ本体とApp Extensionの両方から同じコードを使わせたい場合は、コードを1か所に置ける動的が向きます。両方の利点が欲しいなら、Xcode 15以降で使えるmergeable libraries(後述)も候補になります。
ビルド設定:BUILD_LIBRARY_FOR_DISTRIBUTIONとSKIP_INSTALL
Appleのドキュメントは、フレームワークのターゲットに次の3つを設定し、フレームワークのターゲットとその依存だけをビルドするスキームを用意するよう求めています。
| 設定 | 値 | 理由 |
|---|---|---|
| BUILD_LIBRARY_FOR_DISTRIBUTION | YES | .swiftinterfaceを生成 |
| SKIP_INSTALL | NO | YESだとアーカイブに入らない |
| ARCHS | 未設定 | 全アーキテクチャのユニバーサルに |
BUILD_LIBRARY_FOR_DISTRIBUTIONを有効にすると、Swiftのlibrary evolutionとモジュール安定性が有効になり、テキスト形式のモジュールインターフェース(.swiftinterface)が生成されます。Swift公式ブログのLibrary Evolution解説のとおり、これにより別の版のSwiftコンパイラでビルドしたアプリからもimportできます。Swift製のバイナリでこれを有効にしない場合、異なるSwiftコンパイラ間でのモジュール互換性を保証できず、importに失敗することがあります。
アーカイブからXCFramework生成までの通しスクリプト
対応したいプラットフォームの数だけxcodebuild archiveを実行し、最後に-create-xcframeworkでまとめます。次のスクリプトは動的フレームワークを、iOS実機・iOS Simulator・Mac Catalystの3種類でまとめる例です。
#!/bin/bash
set -euo pipefail
SCHEME=MyFramework
OUT="$(pwd)/build"
rm -rf "$OUT"
archive() {
xcodebuild archive \
-project MyFramework.xcodeproj \
-scheme "$SCHEME" \
-destination "$1" \
-archivePath "$OUT/$2" \
BUILD_LIBRARY_FOR_DISTRIBUTION=YES \
SKIP_INSTALL=NO
}
archive "generic/platform=iOS" ios
archive "generic/platform=iOS Simulator" ios-sim
archive "generic/platform=macOS,variant=Mac Catalyst" catalyst
ARGS=()
for p in ios ios-sim catalyst; do
ARGS+=(-archive "$OUT/$p.xcarchive" -framework "$SCHEME.framework")
ARGS+=(-debug-symbols "$OUT/$p.xcarchive/dSYMs/$SCHEME.framework.dSYM")
done
xcodebuild -create-xcframework "${ARGS[@]}" -output "$OUT/$SCHEME.xcframework"
アーキテクチャとSDKは-destinationから決まります。Appleは-archや-sdkを直接指定するより-destinationを使うよう勧めています。Mac Catalystが不要なら、archiveの行とforの対象からcatalystを外します。
-debug-symbolsはXcode 12で追加されたオプションで、直前に指定したフレームワークにdSYMを対応づけて同梱します。動的フレームワークのdSYMはアーカイブ内のdSYMsフォルダに出力されます。Apple Developer ForumsのスレッドではAppleのDTSがiOS.xcarchive/dSYMs/StructKit.framework.dSYMを指定する例を示しており、同じスレッドに相対パスで失敗し絶対パスで解決したという報告もあるため、スクリプトでは$(pwd)から組んだ絶対パスで渡しています。静的フレームワークはdSYMを持たず、利用側のアプリをビルドしたときにアプリのdSYMへ含まれるので、-debug-symbolsの行は不要です。クラッシュ解析でdSYMが要る理由はFirebase Crashlyticsのシンボル運用で扱っています。
C/C++静的ライブラリの指定:-libraryと-headers
CMakeなどXcode以外でビルドするC/C++ライブラリは、プラットフォームごとに静的ライブラリ(.a)を作り、-frameworkの代わりに-libraryで渡します。ヘッダは-headersで指定します。
xcodebuild -create-xcframework \
-library products/iOS/libMyLibrary.a -headers products/iOS/include \
-library products/iOS_Simulator/libMyLibrary.a -headers products/iOS_Simulator/include \
-output xcframeworks/MyLibrary.xcframework
Appleは、静的ライブラリを.frameworkの形に包んで拡張子.aを外すやり方を避けるよう書いています。iOS・tvOS・watchOS・visionOSで動的リンクするには.frameworkが必要で、.dylibを動的リンクに使えるのはmacOSだけです。Simulator版の.aは、x86_64とarm64をlipoで1つにまとめておきます(実機版とは混ぜません)。
fileコマンドによるアーキテクチャの確認
作成したXCFrameworkに必要なアーキテクチャが入っているかは、フォルダ内のバイナリにfileを実行して確かめます。
file build/MyFramework.xcframework/ios-arm64_x86_64-simulator/MyFramework.framework/MyFramework
Simulator向けのバイナリにarm64とx86_64の両方が出れば、Apple SiliconとIntelの両方のMacでSimulatorを動かせます。片方しか無い場合はARCHSやEXCLUDED_ARCHSが設定されていないかを確認し、Simulatorのアーカイブを作り直します。
Swift Package ManagerでXCFrameworkを配布するbinaryTarget
zipとcompute-checksumによるリモート配布
バイナリ依存はSE-0272で提案され、Swift 5.3(Xcode 12同梱)で実装されました。サーバーでホストする場合は、XCFrameworkをzipのルートに置いて公開し、Package.swiftにURLとチェックサムを書きます。次のURLとチェックサムは記述例です。
// swift-tools-version:5.9
import PackageDescription
let package = Package(
name: "MySDK",
platforms: [.iOS(.v15)],
products: [
.library(name: "MySDK", targets: ["MySDK"])
],
targets: [
.binaryTarget(
name: "MySDK",
url: "https://example.com/MySDK-1.2.0.xcframework.zip",
checksum: "26236bf295aaf5cb2793c66e0bff8bb080fdfa85ddab25ebf73bf0f667023fb2"
)
]
)
チェックサムはパッケージのルートでswift package compute-checksum MySDK-1.2.0.xcframework.zipを実行して出します。Swift 6.3.3で出力をshasum -a 256と比べると同じ64桁の値で、中身はzipファイルのSHA-256でした。zipは格納ファイルの更新日時なども含むため、内容やメタデータが変われば、作り直したzipのチェックサムも変わります。アップロードするzipそのものから計算してください。
binaryTargetの名前は、XCFramework内のモジュール名と一致させる必要があります。パッケージの基本的な書き方はSwift Package Manager入門を参照してください。
ローカルパスでの配布と公式サンプルの注意点
XCFrameworkをパッケージのGitリポジトリに直接含める場合は、zipもチェックサムも不要で、.binaryTarget(name:path:)を使います。
AppleのDistributing binary frameworks as Swift packagesにあるサンプルマニフェストは、ローカルのバイナリターゲットを.package(name:path:)と書いています。これは依存パッケージの宣言で、ターゲットの配列には書けません。本文の説明どおり.binaryTarget(name:path:)と書いてください。
Swift 6.3.3(Command Line Tools、macOS 26.5 SDK、Xcode本体なし)で、macOS向け静的ライブラリ1枚を含むXCFrameworkを手で組み、.binaryTarget(name: "Greet", path: "Greet.xcframework")をexecutableTargetから参照すると、import GreetでCの関数を呼べました。xcodebuildが無い環境でも、SwiftPMはInfo.plistを読んでXCFrameworkを解決します。
SupportedArchitecturesが合わないときの症状
同じ構成で、Info.plistのSupportedArchitecturesだけをx86_64からarm64に書き換え、x86_64のMacでswift buildすると、error: no such module 'Greet'で失敗しました。
エラーはアーキテクチャ不一致ではなく「モジュールが無い」と表示されます。ビルド先と合うフォルダが無いと、XCFramework自体が見つからない扱いになるためです。利用者からno such moduleの報告が来たら、まず相手のビルド先(実機、Simulator、Mac Catalyst)とInfo.plistの組み合わせを突き合わせてください。
Linux向けはSE-0482のartifactbundle
XCFrameworkはAppleプラットフォーム専用で、Linux向けのパッケージからは使えません。代わりにSE-0482(Swift 6.2で実装)で、artifactbundleにstaticLibraryという種類が加わりました。info.jsonにターゲットトリプルごとの.aとヘッダの場所を書き、同じbinaryTargetで参照します。対象は標準Cライブラリにだけ依存し、C言語のインターフェースを持つ静的ライブラリです。
{
"schemaVersion": "1.0",
"artifacts": {
"CGreet": {
"type": "staticLibrary",
"version": "1.0.0",
"variants": [{
"path": "greet/libgreet.a",
"supportedTriples": ["aarch64-unknown-linux-gnu"],
"staticLibraryMetadata": {
"headerPaths": ["greet/include"],
"moduleMapPath": "greet/include/module.modulemap"
}
}]
}
}
}
Swift 6.3.3では、supportedTriplesをx86_64-apple-macosxにした同じ構成をmacOSでビルドし、import CGreetからCの関数を呼べました。対象がCのインターフェースに限られるので、Swiftのモジュールを配るApple向けはXCFramework、Linux向けのCライブラリはartifactbundleと分けてください。
CocoaPods・CarthageでのXCFramework配布と移行
Podspecのvendored_frameworksとtrunkの読み取り専用化
CocoaPodsでは、Podspecのvendored_frameworksに.xcframeworkを指定して配布できます。最小の例は次のとおりです。
Pod::Spec.new do |s|
s.name = 'MySDK'
s.version = '1.2.0'
s.summary = 'Example SDK'
s.homepage = 'https://example.com/MySDK'
s.license = { :type => 'Commercial', :file => 'LICENSE' }
s.author = { 'Example Inc.' => '[email protected]' }
s.source = { :http => 'https://example.com/MySDK-1.2.0.xcframework.zip' }
s.ios.deployment_target = '15.0'
s.vendored_frameworks = 'MySDK.xcframework'
end
ただしCocoaPods公式ブログは、2026年11月2〜6日に新しいPodspecを受け付けない試験運用を行い、12月2日にtrunkを恒久的に新規Podspecの受け付け停止へ切り替える計画を公表しています(日付は確定ではないとも書かれています)。既存のビルドは壊れませんが、trunk経由では新しい版を届けられなくなります。CocoaPods本体は2026年7月6日に1.17.0が出ています。これからXCFrameworkを配布するなら、SwiftPMのbinaryTargetを主経路にし、trunkには既存利用者向けの最終版だけを置いてください。CocoaPods側の詳細はCocoaPodsとは?1.17.0の使い方とpod install、2026年12月の読み取り専用化への備えで解説しています。
Carthageの–use-xcframeworksとビルド済みバイナリ
Carthageでは、0.37.0で追加された--use-xcframeworksを付けるとUniversal FrameworkではなくXCFrameworkが生成されます。リリースノートは、生成物をcarthage copy-frameworksのスクリプトフェーズを使わずにターゲットのEmbedded binariesへドラッグするよう指示しています。0.38.0以降は、GitHub Releasesのアセット名に.xcframeworkを含むビルド済みXCFrameworkも取り込めます。
ビルド済みバイナリの添付は止まることがあります。RxSwiftのReleasesは、6.10.0(2026年1月22日)までRxSwift.xcframework.zipを添付していましたが、6.10.1以降のリリースにはアセットがありません。ビルド済みに頼る構成は、更新のたびにアセットの有無を確かめてください。RxSwiftのSPM導入はRxSwiftとは?Observable・Subject・DisposeBagの基本と6.10.2のSPM導入で扱っています。
Xcode 15以降のXCFramework署名とプライバシーマニフェスト
codesignによる署名と署名が変わったときのビルドエラー
Xcode 15から、プロジェクトで使うXCFrameworkの署名が検証されます。Verifying the origin of your XCFrameworksによると、File inspectorに署名情報が表示され、最後に確認した署名者がプロジェクトファイルに保存されます。以降のビルドで署名者が変わったり署名が消えたりすると、is not signed with the expected identity and may have been compromisedというエラーでビルドが止まります。
SDKの譲渡や自前ビルドへの切り替えなど変更に心当たりがあれば、Issue navigatorでエラーを選び、Accept Changeで受け入れます。心当たりが無い場合、Appleは信頼できる入手元からXCFrameworkを入れ直し、開発環境自体も監査するよう求めています。
配布側は次のコマンドで署名します。
codesign --timestamp -s "Apple Distribution: Example Inc." build/MyFramework.xcframework
Apple Developer Programの会員はApple DistributionかApple Developmentの証明書を使います。署名に使った証明書を失効させると、そのXCFrameworkを使う側のビルドがエラーになるため、失効前に別の証明書で署名し直した版を配布してください。証明書の入手はApple Developer Programの登録手順、証明書とプロファイルの関係はプロビジョニングプロファイルとはを参照してください。
プライバシーマニフェストと署名が必須になるSDK
AppleのThird-party SDK requirementsは、Alamofire、FirebaseCore、Flutter、RxSwiftなど、App Storeのアプリでよく使われるSDKを一覧で示しています。これらを含む新規アプリや、これらを追加するアップデートを提出するときはプライバシーマニフェストが必須で、バイナリ依存として使う場合は署名も必須です。一覧のSDKを再パッケージしたものも対象です。
フレームワークでの配置場所はプラットフォームで異なります。iOS・iPadOS・tvOS・visionOS・watchOSは.frameworkのルートにPrivacyInfo.xcprivacyを置き、macOSとMac CatalystはVersions/A/Resources/に置きます。XCFrameworkを作ってから中身を手で差し替えると署名が壊れるので、マニフェストはビルド前にターゲットのリソースへ入れておいてください。
XCFrameworkのビルドエラーと原因の切り分け
| 症状 | 主な原因 | 対処 |
|---|---|---|
| no such module | ビルド先に合うフォルダが無い | Info.plistと対象を照合 |
| Swiftの版違いでimport不可 | .swiftinterface未生成 | BUILD_LIBRARY_FOR_DISTRIBUTION |
| is not a member type of struct | モジュールと同名の型 | 型名を変える |
| Simulatorだけリンク失敗 | Simulator版にarm64が無い | -destinationで再アーカイブ |
| xcrun lipoのエラー | 実機とSimulatorのarm64衝突 | XCFrameworkへ移行 |
| expected identity | 署名者の変更・署名の削除 | 入手元を確認しAccept Change |
| アーカイブが空 | SKIP_INSTALL=YES | SKIP_INSTALL=NO |
モジュール名と型名の衝突による.swiftinterface検証エラー
SDKでよくあるのが、モジュール名と同じ名前の型(例:モジュールGreetの中のpublic struct Greet)を公開する設計です。BUILD_LIBRARY_FOR_DISTRIBUTIONを有効にした場合、生成される公開APIの型参照によっては、モジュール名と型名の衝突がビルドエラーを引き起こします。Swift 6.3.3で、public struct Greetと、それを返すpublic func make() -> Greetを持つモジュールを-enable-library-evolutionと-emit-module-interface-path付きでビルドすると、まず次の警告が出ました。
warning: public struct 'Greet.Greet' shadows module 'Greet', which may cause failures when importing 'Greet' or its clients in some configurations
続いて生成直後のインターフェース検証でerror: 'Greet' is not a member type of struct 'Greet.Greet'となり、終了コード1で止まりました。.swiftinterfaceにはmake()の戻り値がGreet.Greetと書かれますが、読み込むときに先頭のGreetがモジュールでなく構造体として解決されるためです。
型名をGreeterに変えると警告もエラーも消えました。公開済みで型名を変えられない場合、警告が案内するswiftlang/swift Issue #56573は、OTHER_SWIFT_FLAGSに-Xfrontend -module-interface-preserve-types-as-writtenを加える回避策を挙げています。Swift 6.3.3ではこのフラグで戻り値がGreetと書かれ、検証が通りました。ただしIssueは確実な方法ではないと断っており、Hashableなどの準拠を手で実装する必要が出る場合もあります。新規のSDKでは、モジュール名と型名を最初から分けておくのが確実です。
mergeable librariesで作るXCFramework
複数のXCFrameworkを1つのアプリに入れて起動時間やサイズが気になる場合、Xcode 15以降はmergeable librariesから作ったXCFrameworkも扱えます。利用時にアプリへマージされるか、マージ用のメタデータが取り除かれます。配布側ではライブラリターゲットの「Build Mergeable Library」を有効にし、そのアーカイブからXCFrameworkを作成します。この形で作ったXCFrameworkはInfo.plistにMergeableMetadataキーが入り、Xcode 15以降でしか使えません。
XCFrameworkを採用しないほうがよい場面
ソースコードを公開でき、利用側のビルド時間も許容できるライブラリなら、SwiftPMのソース配布を第一候補にしてください。Appleのドキュメント自体が、バイナリ配布は含めたバイナリが対応するプラットフォームしかサポートできず移植性が下がる、と欠点を明記しています。
次の条件のどれかに当てはまるなら、バイナリ化の手間に見合いません。
- 社内の同じリポジトリか、同じチームだけで使うモジュール
- Linuxなど、Apple以外のプラットフォームでもSwiftのコードとしてビルドしたいパッケージ
- 新しいXcodeで互換性を確認し、必要な場合に再ビルド・署名・zip・チェックサム更新を行う体制が無い
XCFrameworkが本領を発揮するのは、ソースを渡せない商用SDKや、ビルドに時間がかかるC/C++ライブラリを事前ビルドして配る場合です。SDKの設計から配布・アプリへの組み込みまでを外部に任せる場合は、iOSアプリ開発の支援内容も参考にしてください。Kotlin MultiplatformのようにiOS向けの成果物をXCFrameworkで出す技術もあり、採用判断はCompose Multiplatformとは?KMPとの違いとiOS対応の現在地・採用判断を解説で扱っています。
よくある質問
XCFrameworkと.frameworkは何が違いますか?
.frameworkは1つのプラットフォーム向けのバイナリとヘッダ、リソースをまとめたバンドルです。XCFrameworkは、その.frameworkや静的ライブラリをプラットフォームごとに複数収め、Info.plistで選べるようにした入れ物です。実機版とSimulator版をlipoで合成しないので、両方がarm64でも共存できます。
XCFrameworkとSwift Packageはどちらを使うべきですか?
対立するものではありません。Swift Packageは配布と依存解決の仕組みで、XCFrameworkはその中に入れられるバイナリの形式です。ソースを公開できるならソースのSwift Packageを、ソースを渡せないならbinaryTargetでXCFrameworkを包んだSwift Packageを配ります。
XCFrameworkはどのXcodeから使えますか?
Xcode 11のリリースノートで導入され、xcodebuild -create-xcframeworkもこのとき追加されました。Swift Package ManagerのbinaryTargetから配布できるのはSwift 5.3/Xcode 12以降で、署名の検証はXcode 15以降です。
XCFrameworkをXcodeのプロジェクトに追加する方法は?
SwiftPMで配布されていればパッケージとして追加します。.xcframeworkを直接渡された場合は、ターゲットのGeneralにある「Frameworks, Libraries, and Embedded Content」へ追加し、.frameworkが入っていれば、Xcode 15以降では静的・動的とも「Embed & Sign」、.aの静的ライブラリなら「Do Not Embed」を選びます。追加後、File inspectorで署名状態を確認してください。
XCFrameworkにdylibを入れられますか?
入れられますが、.dylibを動的リンクに使えるのはmacOSだけです。iOS・iPadOS・tvOS・visionOS・watchOSで動的リンクさせるなら、.frameworkとして作ってXCFrameworkに収めます。