はじめに
本記事は どすこい塾 Advent Calendar 2025 の10日目の記事です。
昨日は @dosukoi_android さんで サーバーサイドDartのフレームワークを作ってる でした。
XCFrameworkをSPM経由で導入する方法を紹介します。
環境
- OS:macOS Sequoia 15.6(24G84)
- Swift:6.2.1
XCFrameworkをSPM経由で導入する方法
XCFrameworkをSPM経由で導入するには、 提供側と利用側で Package.swift を2つ用意します。
フォルダ構成に決まりはありませんが、本記事では以下とします。
$ tree
.
└── loki-ios
└── Packages
├── LokiPackage
│ └── Package.swift # 利用側の `Package.swift`
└── unity-framework
├── Package.swift # 提供側の `Package.swift`
└── UnityFramework.xcframework
提供側に Package.swift を作成
以下のような Package.swift を作成します。XCFrameworkと同じ階層に配置するのが無難です。
XCFrameworkを binaryTarget() で読み込み、Swift Packageとして公開しているだけです。
本記事では UnityFramework を例に挙げています。
UnityFramework.xcframework や UnityFramework の部分は適宜変更してください。
.iOS(.v18) も必要に応じて変更してください。
// swift-tools-version: 6.2
import PackageDescription
let package = Package(
name: "UnityFramework",
platforms: [
.iOS(.v18),
],
products: [
.library(
name: "UnityFramework",
targets: ["UnityFramework"],
),
],
dependencies: [
],
targets: [
.binaryTarget(
name: "UnityFramework",
path: "./UnityFramework.xcframework",
),
],
)
この Package.swift は誰でも作れますが、提供側で用意すると親切です。
利用側の Package.swift に追加
利用側の Package.swift は、 dependencies に提供側の Package.swift があるフォルダを相対パスで指定し、 product() でプロダクトとパッケージを指定するだけです。
// swift-tools-version: 6.2
import PackageDescription
let package = Package(
name: "LokiPackage",
platforms: [
.iOS(.v18),
],
dependencies: [
+ .package(path: "./../unity-framework"),
],
targets: [
.target(
name: "UnityCore",
dependencies: [
+ "UnityFramework",
],
),
],
)
おまけ: Package.swift を作成しなくても直接XCFrameworkを追加できる
Xで質問があったので説明します。
ご指摘の通り、 UnityFramework を別のSwift Packageに分離しなくても直接 binaryTarget() を使うことでXCFrameworkを導入できます。
// swift-tools-version: 6.2
import PackageDescription
let package = Package(
name: "LokiPackage",
platforms: [
.iOS(.v18),
],
targets: [
.target(
name: "UnityCore",
dependencies: [
+ "UnityFramework",
],
),
+ .binaryTarget(
+ name: "UnityFramework",
+ path: "./../unity-framework/UnityFramework.xcframework",
+ ),
],
)
もちろんこれでも問題ありませんが、個人的には以下2つのデメリットを感じます。
- XCFrameworkであることを意識しないといけなく、他のSwift Packageと同じように扱えない
- ターゲット全体をループして処理している場合、バイナリターゲットを明示的に弾かないといけないことがある
後者について、例えば以下のように全ターゲットに対して swiftSettings を指定してるとします。
for target in package.targets {
target.swiftSettings = ○○
}
targets に binaryTarget が含まれている場合、以下のエラーが発生してResolve Packagesに失敗します。
target 'UnityFramework' is assigned a property 'settings' which is not accepted for the binary target type. The current property value has the following representation: [ ... ].
guard 節などを使って明示的に弾かなければなりません。
for target in package.targets {
+ guard target.name == "unity-framework" else {
+ return
+ }
target.swiftSettings = ○○
}
おわりに
簡単にXCFrameworkをSPM経由で導入できました。
以上 どすこい塾 Advent Calendar 2025 の10日目の記事でした。
明日は未定です。