XCFrameworkとは?作成手順とSwiftPM配布・署名の要点

XCFrameworkとは?作成手順とSwiftPM配布・署名の要点

XCFrameworkは、iOS実機・iOS Simulator・macOSなど複数のプラットフォーム向けにビルドしたフレームワークやライブラリを、1つの.xcframeworkバンドルにまとめるAppleの配布形式です。この記事では、実機用とSimulator用のarm64をFat Frameworkに混在させられない理由から、xcodebuild -create-xcframeworkでの作成、Swift Package Managerでのバイナリ配布、Xcode 15以降の署名検証までを、Appleのドキュメントとリリースノートを根拠に整理します。

まとめ:XCFrameworkの要点と作成・配布の判断

  • XCFrameworkはXcode 11で導入された、プラットフォームごとのバイナリを別フォルダに分けて同梱する形式です。lipoで1つのバイナリに合成するFat Frameworkとは違い、同じarm64を持つ実機版とSimulator版を共存させられます。
  • 作成はプラットフォームごとにxcodebuild archiveを実行し、xcodebuild -create-xcframeworkでまとめます。ビルド設定はBUILD_LIBRARY_FOR_DISTRIBUTION=YESとSKIP_INSTALL=NOが前提です。
  • Swift Package ManagerではbinaryTargetで配布します(Swift 5.3/Xcode 12以降)。リモート配布はzipとswift package compute-checksumで出したSHA-256が必要で、Appleプラットフォーム専用です。
  • Xcode 15以降はXCFrameworkの署名が検証され、署名者が変わるとビルドが止まります。配布側はcodesign --timestampで署名しておくべきです。
  • CocoaPods trunkは2026年12月2日に新規Podspecの受け付けを止める予定です。これからXCFrameworkを配布するなら、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つ入れられないという制約の上に成り立っていました。

Apple SiliconのMacでSimulatorがarm64で動くようになり、前提が崩れました。Carthage 0.37.0(2021年2月1日)のリリースノートは、Xcode 12でSimulatorにApple Siliconのサポートが入った結果、実機版とSimulator版の両方がarm64でビルドされるためXCFrameworkが必要になった、と説明しています。同じリリースで、Xcode 12でのフレームワークビルドがxcrun lipoのエラーで失敗する既知の問題も記載されています。

Appleのドキュメントも、iOS用とiOS Simulator用のスライスをlipoで1つのバイナリにまとめないよう明記しています。iOS対応のXCFrameworkには、arm64の実機用と、x86_64とarm64を含むSimulator用の、少なくとも2つのバイナリが要ります。

Xcode 11からXcode 27までのXCFramework関連の変更

Xcode XCFrameworkに関する変更
11 XCFramework導入、-create-xcframework追加
12 -debug-symbolsでdSYM同梱、SwiftPMのバイナリ配布
15 署名の検証、mergeable librariesから作成可能
16 XCFrameworkを使うターゲットのプレビュー不具合を修正
27 ld64削除、macOS 27以上の対象でx86_64既定外

いずれも各版のXcodeリリースノートの記載です。実務で影響が大きいのはXcode 12と15の変更で、12でSwiftPMからの配布が、15で署名の検証が入りました。現行のXcodeの版はXcodeの最新バージョンとアップデート手順で確認できます。

xcodebuild -create-xcframeworkによる作成手順

ビルド設定: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製のバイナリでこれを生成しない場合、異なるSwiftコンパイラ間でのモジュール互換性を保証できず、importに失敗することがあります。

プラットフォームごとのアーカイブ作成

対応したいプラットフォームの数だけxcodebuild archiveを実行します。

xcodebuild archive \
  -project MyFramework.xcodeproj \
  -scheme MyFramework \
  -destination "generic/platform=iOS" \
  -archivePath "archives/MyFramework-iOS"

xcodebuild archive \
  -project MyFramework.xcodeproj \
  -scheme MyFramework \
  -destination "generic/platform=iOS Simulator" \
  -archivePath "archives/MyFramework-iOS_Simulator"

アーキテクチャとSDKは-destinationから決まります。Appleは-archや-sdkを直接指定するより-destinationを使うよう勧めています。Mac Catalyst版は"generic/platform=macOS,variant=Mac Catalyst"を指定します。

2026年9月14日に正式版が出たXcode 27(27A266a)のリリースノートでは、MACOSX_DEPLOYMENT_TARGETを27.0以上にするとARCHS_STANDARDからx86_64が外れます。必要ならARCHSへ明示的に追加できますが、macOS版を配布していてIntel Macの利用者が残る場合は、最低対応OSを上げる前に確認してください。詳細はXcode 27の現在地と動作要件にまとめています。

-frameworkと-libraryでのバンドル生成

アーカイブがそろったら、-create-xcframeworkで1つにまとめます。

xcodebuild -create-xcframework \
  -archive archives/MyFramework-iOS.xcarchive -framework MyFramework.framework \
  -archive archives/MyFramework-iOS_Simulator.xcarchive -framework MyFramework.framework \
  -output xcframeworks/MyFramework.xcframework

静的ライブラリ(.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

クラッシュログのシンボル化にdSYMを使うなら、Xcode 12で追加された-debug-symbolsで.dSYMを同梱できます。利用側のクラッシュ解析でdSYMが要る理由はFirebase Crashlyticsのシンボル運用で扱っています。

CMakeなどXcode以外でビルドするライブラリは、静的ライブラリを.frameworkの形に包んで拡張子.aを外すやり方を避け、-libraryで渡します。iOS・tvOS・watchOS・visionOSで動的リンクするには.frameworkが必要で、.dylibを動的リンクに使えるのはmacOSだけです。

fileコマンドによるアーキテクチャの確認

作成したXCFrameworkに必要なアーキテクチャが入っているかは、フォルダ内のバイナリにfileを実行して確かめます。

file MyFramework.xcframework/ios-arm64_x86_64-simulator/MyFramework.framework/MyFramework

Simulator向けのバイナリにarm64とx86_64の両方が出れば、Apple SiliconとIntelの両方のMacでSimulatorを動かせます。片方しか無い場合は、Simulatorのアーカイブを作り直します。

Swift Package ManagerでXCFrameworkを配布するbinaryTarget

zipとcompute-checksumによるリモート配布

バイナリ依存はSE-0272で提案され、Swift 5.3で実装されました。Xcode 12のリリースノートにも、SwiftパッケージがXCFrameworkとして配布されるビルド済みライブラリを提供できるようになったとあります。

以下のURLとチェックサムは記述例です。実際の配布では自分の公開URLと配布zipから計算した値に置き換えます。サーバーでホストする場合は、XCFrameworkをzipのルートに置いて公開し、Package.swiftに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そのものから計算してください。

binaryTargetの名前は、XCFramework内のモジュール名と一致させる必要があります。また、AppleのドキュメントのとおりバイナリターゲットはAppleプラットフォーム専用で、Linux向けのパッケージからは使えません。

ローカルパスでの配布と公式サンプルの注意点

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'で失敗しました。

エラーはアーキテクチャ不一致ではなく「モジュールが無い」と表示されます。Info.plistにビルド先と合うフォルダが無いと、XCFramework自体が見つからない扱いになるためです。配布したXCFrameworkで利用者からno such moduleの報告が来たら、まず相手のビルド先(実機、Simulator、Mac Catalyst)とInfo.plistの組み合わせを突き合わせてください。

パッケージの基本的な書き方はSwift Package Manager入門を参照してください。

CocoaPods・CarthageでのXCFramework取り込みと移行判断

CocoaPodsでは、1.9.0(2020年2月)で対応したvendored_frameworksに.xcframeworkを指定して配布できます。ただし、CocoaPods公式ブログ(2024年11月30日)は、2026年11月1〜7日に試験運用を行い、12月2日にtrunkが新しいPodspecを恒久的に受け付けなくなる計画を公表しています。既存のビルドは壊れませんが、trunk経由では新しい版を届けられなくなります。

Carthageでは、0.37.0で追加された--use-xcframeworksを付けるとUniversal FrameworkではなくXCFrameworkが生成されます。リリースノートは、生成物をcarthage copy-frameworksのスクリプトフェーズを使わずにターゲットのEmbedded binariesへドラッグするよう指示しています。0.37.0では、バイナリをダウンロードするgithub依存にこのオプションが効かず、--no-use-binariesでソースから再ビルドさせる必要がありました。0.38.0(2021年5月)以降は、GitHub Releasesのアセット名に.xcframeworkを含むビルド済みXCFrameworkも取り込めます。

2026年9月時点でSDKを新たに配布するなら、SwiftPMのbinaryTargetを主経路にし、公開trunk経由のCocoaPods配布は既存利用者向けの最終版の提供にとどめ、独自のSpecsリポジトリで継続する場合は別途運用してください。CocoaPods自体の構造はCocoaPodsの基本構造と役割で解説しています。

Xcode 15以降のXCFramework署名とプライバシーマニフェスト

codesignによる署名と署名が変わったときのビルドエラー

Xcode 15から、プロジェクトで使うXCFrameworkの署名が検証されます。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." xcframeworks/MyLibrary.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
Simulatorだけリンク失敗 Simulator版にarm64が無い -destinationで再アーカイブ
xcrun lipoのエラー 実機とSimulatorのarm64衝突 XCFrameworkへ移行
expected identity 署名者の変更・署名の削除 入手元を確認しAccept Change
アーカイブが空 SKIP_INSTALL=YES SKIP_INSTALL=NO

表は原因の例であり、症状だけでは配布物の不備と断定できません。利用側の依存設定やツールチェーンも確認し、必要なバイナリやモジュールインターフェースの不足が判明した場合に、配布側へ再生成を依頼してください。

複数のXCFrameworkを1つのアプリに入れて起動時間やサイズが気になる場合、Xcode 15以降はmergeable librariesから作ったXCFrameworkも扱えます。リリースノートによれば、利用時にマージされるか、マージ用のメタデータが取り除かれます。この形で作ったXCFrameworkはInfo.plistにMergeableMetadataキーが入り、Xcode 15以降でしか使えません。

XCFrameworkを採用しないほうがよい場面

ソースコードを公開でき、利用側のビルド時間も許容できるライブラリなら、SwiftPMのソース配布を第一候補にしてください。Appleのドキュメント自体が、バイナリ配布は含めたバイナリが対応するプラットフォームしかサポートできず移植性が下がる、と欠点を明記しています。

具体的には次の条件のどれかに当てはまるなら、バイナリ化の手間に見合いません。

  • 社内の同じリポジトリか、同じチームだけで使うモジュール
  • Linuxなど、Apple以外のプラットフォームでもビルドしたいパッケージ
  • 新しいXcodeで互換性を確認し、対応アーキテクチャの追加などが必要な場合に再ビルド・署名・zip・チェックサム更新を行う体制が無い

XCFrameworkが本領を発揮するのは、ソースを渡せない商用SDKや、ビルドに時間がかかるC/C++ライブラリを事前ビルドして配る場合です。

よくある質問

XCFrameworkと.frameworkは何が違いますか?

.frameworkは1つのプラットフォーム向けのバイナリとヘッダ、リソースをまとめたバンドルです。XCFrameworkは、その.frameworkや静的ライブラリをプラットフォームごとに複数収め、Info.plistで選択できるようにした入れ物です。実機版とSimulator版をlipoで合成する必要が無いため、両方がarm64でも共存できます。

XCFrameworkはどのXcodeから使えますか?

Xcode 11のリリースノートで導入され、xcodebuild -create-xcframeworkもこのとき追加されました。Swift Package ManagerのbinaryTargetから配布できるのはSwift 5.3/Xcode 12以降で、署名の検証はXcode 15以降です。

XCFrameworkは実機とSimulatorで別々に作る必要がありますか?

作るアーカイブは別々ですが、配布物は1つにまとめます。-destination "generic/platform=iOS"と"generic/platform=iOS Simulator"でそれぞれアーカイブを作り、-create-xcframeworkに両方を渡します。Appleは両者をlipoで1つのバイナリにしないよう明記しています。

XCFrameworkをXcodeのプロジェクトに追加する方法は?

SwiftPMで配布されていればパッケージとして追加します。.xcframeworkファイルを直接渡された場合は、ターゲットのGeneralにある「Frameworks, Libraries, and Embedded Content」へ追加します。動的フレームワークなら「Embed & Sign」、単体の静的ライブラリ(.a)なら「Do Not Embed」を選びます。プライバシーマニフェストなどのリソースを持つ静的フレームワーク(Xcode 15以降)は埋め込む設定にします。Xcodeは静的リンク済みのメインバイナリを除いてバンドルを同梱します。追加後、File inspectorで署名状態を確認してください。

CocoaPodsで配布しているXCFrameworkはどうすべきですか?

CocoaPods trunkは2026年12月2日に新規Podspecの受け付けを止める予定なので、それ以降の版はtrunkでは届けられません。binaryTargetを使ったSwiftPMパッケージを用意し、Podspec側の説明やREADMEで移行先を案内するのが確実です。

関連記事

お気に入りに入れた記事の一覧

資料請求

RELATED POSTS 関連記事

目次