Swift Package Manager(以下、SPM)の登場から数年が経ち、実務でも導入事例が増えてきました。
しかし、有名なFrameworkであっても、依然としてSPM非対応のものは少なくありません。
本記事では、SPM非対応FrameworkをXCFramework化してSPMで管理する方法、およびPrivate RepositoryのRelease Assetを利用する方法について整理します。
SPMとXCFramework
SPMは、binaryTarget
を使って XCFramework形式のバイナリ を依存関係として登録できます。
これにより、SPM非対応のFrameworkでもXCFramework形式にビルドして登録すれば、SPMで擬似的に管理可能です。
XCFrameworkの参照方法は以下の2通りです。
- ローカル参照
- サーバーからバイナリをホスティング
サーバー配布の場合は、XCFrameworkを含むZIPファイルを作成し、公開します。
Package.swift
の例は以下の通りです。
// Package.swift
import PackageDescription
let package = Package(
name: "AppPackage",
products: [
.library(name: "HogeUtil", targets: ["HogeUtil"]),
],
targets: [
.binaryTarget(
name: "HogeUtil",
url: "https://example.com/HogeUtil.xcframework.zip",
checksum: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
),
]
)
非公開Frameworkの場合は、Git LFS や AWS S3 など、限定アクセス可能な場所にバイナリを置く必要があります。
Private RepositoryのRelease Assetは以前使えなかった
GitHubで管理している非公開FrameworkをRelease Assetとして配布できれば、
自前でホスティングする必要もなく便利です。
しかし、以前はGitHub認証周りの問題で Private RepositoryのRelease AssetをSPMから直接参照できませんでした。
実際、以下フォーラムにも同様の報告があります。
先行事例:リポジトリ同梱方式
リポジトリ本体にXCFrameworkを同梱して配布する方法です。
ただし、GitHubは100MB以上のファイルを置けないため、バイナリが小さい場合に限られます。
なぜRelease Assetを使えなかったのか
原因は大きく2つありました。
1. ダウンロードURLが直接利用できない
Release AssetのURLは直接ZIPを返さず、302リダイレクトを返します。
SPMのURLSession
はリダイレクト先を取得せず、.zip
拡張子必須という制約もあるため利用できませんでした。
2. Accept: application/octet-stream
ヘッダーがなかった
GitHub API仕様に沿ったヘッダーが付与されておらず、ダウンロードに失敗していました。
現在は以下PRにより解決しています。
Xcode 13.3以降で解決済み
これらの問題はXcode 13.3以降で解消され、Private RepositoryのRelease Assetも利用可能になりました。
Private RepositoryのRelease Assetを使う手順
SPM対応Frameworkを使うよりは手間がかかりますが、ビルド高速化などのメリットもあります。
前提条件
- FrameworkがGitHubリポジトリで管理されている
- Tag / Releaseが発行されている
- Release AssetにXCFrameworkのZIPがアップされている
1. 最新Releaseの取得
GitHub APIで最新Release情報を取得します。
curl -H "Accept: application/vnd.github+json" -H "Authorization: Bearer <YOUR-TOKEN>" https://api.github.com/repos/OWNER/REPO/releases/latest
レスポンスのassets.url
を控えておきます。
2. Checksumの取得
ZIPをダウンロードし、Checksumを計算します。
swift package compute-checksum HogeUtil.xcframework.zip
3. Package.swiftにbinaryTargetを追加
import PackageDescription
let package = Package(
name: "AppPackage",
products: [
.library(name: "HogeUtil", targets: ["HogeUtil"]),
],
targets: [
.binaryTarget(
name: "HogeUtil",
url: "https://api.github.com/repos/OWNER/REPO/releases/assets/ASSET_ID.zip", // .zip必須
checksum: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
),
]
)
4. .netrc
の作成
SPMは .netrc
での認証設定に対応しています。
アクセストークンを作成し、以下のように記載します。
touch ~/.netrc
machine api.github.com login <GITHUB-USERNAME> password <ACCESS-TOKEN>
今後の検証課題
- CIでの
.netrc
設定方法 - ビルド速度への影響
まとめ
-
Xcode 13.3以降なら、Private RepositoryのRelease AssetをSPMの
binaryTarget
として利用可能 -
.netrc
による認証設定でダウンロードできる - 公開不要で、安全に非公開FrameworkをSPM管理できる
SPMの活用範囲が広がるため、今後CocoaPodsやCarthageからの移行手段の一つとして有力です。
参考リンク