はじめに
タイトル通り Swift Package Manager (以下 SwiftPM) で作ったライブラリを xcframework にする方法を n 番煎じですが備忘録がてら書きます。
xcframework についてはこちら
環境
Mint を使って上記で前置きした CLI ツールをインストールした。
最近まで Xcode12.5.1 環境がないとビルドができなかったが Xcode13.x でもビルドが可能な状態になっていました!!
- Xcode 13.4
- Swift 5.6.1
- Mint 0.17.1
- swift-create-xcframework v2.2.0
mint install unsignedapps/swift-create-xcframework@v2.2.0
または Mintfile
に以下を追記して mint bootstrap
でも可能です。
unsignedapps/swift-create-xcframework@v2.2.0
ライブラリを作る
Xcode からでもコマンドからでもいいですが適当にライブラリを作りました。
たったこれだけのライブラリを作りました。
- 内部からのみ変更が可能な
text: String
プロパティ text: String
の内部をコンソールに表示するメソッド (echo()
)text: String
を変更するメソッド (updateText(_:)
)
xcframework
ビルドをする
Package.swift
があるディレクトリに移動し以下を実行します。
mint run swift-create-xcframework --clean MyLibrary --output Products --platform ios
引数の説明は今回は省略します。
また、 --zip
フラグがあるのでこれをつかうことで xcframework を zip に固めて一緒にハッシュ値も出力してくれるので
SwiftPM で配布したいときに targets
に対して binaryTarget
で URL 指定での配布が簡単に行うことができます。
上記でビルドが完了したら --output
で指定したディレクトリに成果物が出力されます。
組み込んでみる
とりあえずまっさらなプロジェクトを作ってプロジェクトに xcframework を依存フレームワークに追加してみました。
ちょっとした画面を作ってみる
雑な部分が多々あるが一旦こんな感じで表示される Interface を作ってみた。以下ソースコード
import MyLibrary import UIKit class ViewController: UIViewController { // MARK: - Properties @IBOutlet private var textField: UITextField! @IBOutlet private var button: UIButton! private var library = MyLibrary() // MARK: - Life Cycle override func viewDidLoad() { super.viewDidLoad() library.echo() } @IBAction private func onTapButton(_ sender: Any) { guard let text = textField.text else { return } library.changeText(text) textField.text = "" library.echo() } }
以下実行をして、 UITextField に aaaaaaa
と入力して UIButton を1度タップしたときの結果である。
Hello, World! aaaaaaa
ちゃんと目的通りのログが表示されていることが確認できた。
ちなみに定義へジャンプしてみると実際にどんなコードが実装されているのかは確認することができない。
これは、 xcframework 内にある swiftinterface
とほぼ一致する内容である。
依存ライブラリを増やしてみる
ライブラリ側の Package.swift
を変更した。
dependencies: [ + .package(url: "https://github.com/nnsnodnb/AnyErrorConvertible", from: "1.0.0") - ], targets: [ .target( name: "MyLibrary", + dependencies: ["AnyErrorConvertible"]), - dependencies: []),
とりあえず依存を追加しただけでもう1度 xcframework をビルドして、
アプリケーション側に Xcode で SwiftPM に dependencies に指定したライブラリを追加して再度アプリケーションをビルドをしてみた。
dyld[59403]: Library not loaded: @rpath/AnyErrorConvertible.framework/AnyErrorConvertible Referenced from: /Users/nnsnodnb/Library/Developer/Xcode/DerivedData/App-fdpxqniiilivhieveezgolatvbsq/Build/Products/Debug-iphonesimulator/MyLibrary.framework/MyLibrary Reason: tried: '/Users/nnsnodnb/Library/Developer/Xcode/DerivedData/App-fdpxqniiilivhieveezgolatvbsq/Build/Products/Debug-iphonesimulator/AnyErrorConvertible.framework/AnyErrorConvertible' (no such file), '/Users/nnsnodnb/Library/Developer/Xcode/DerivedData/App-fdpxqniiilivhieveezgolatvbsq/Build/Products/Debug-iphonesimulator/PackageFrameworks/AnyErrorConvertible.framework/AnyErrorConvertible' (no such file), '/Applications/Xcode13.4.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/usr/lib/swift/AnyErrorConvertible.framework/AnyErrorConvertible' (no such file), '/usr/lib/swift/AnyErrorConvertible.framework/AnyErrorConvertible' (no such file), '/Applications/Xcode13.4.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/Applications/Xcode13.4.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/AnyErrorConvertible.framework/AnyErrorConvertible' (no such file), '/Applications/Xcode13.4.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/AnyErrorConvertible.framework/AnyErrorConvertible' (no such file), '/Users/nnsnodnb/Library/Developer/CoreSimulator/Devices/4B6FDEB8-4036-4F9C-BD83-5B4E4ECCAB63/data/Containers/Bundle/Application/9FA861B6-B93D-4BAA-A87E-50E679D6FF97/App.app/Frameworks/AnyErrorConvertible.framework/AnyErrorConvertible' (no such file), '/Users/nnsnodnb/Library/Developer/CoreSimulator/Devices/4B6FDEB8-4036-4F9C-BD83-5B4E4ECCAB63/data/Containers/Bundle/Application/9FA861B6-B93D-4BAA-A87E-50E679D6FF97/App.app/Frameworks/AnyErrorConvertible.framework/AnyErrorConvertible' (no such file), '/Applications/Xcode13.4.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/System/Library/Frameworks/AnyErrorConvertible.framework/AnyErrorConvertible' (no such file) Library not loaded: @rpath/AnyErrorConvertible.framework/AnyErrorConvertible Referenced from: /Users/nnsnodnb/Library/Developer/Xcode/DerivedData/App-fdpxqniiilivhieveezgolatvbsq/Build/Products/Debug-iphonesimulator/MyLibrary.framework/MyLibrary Reason: tried: '/Users/nnsnodnb/Library/Developer/Xcode/DerivedData/App-fdpxqniiilivhieveezgolatvbsq/Build/Products/Debug-iphonesimulator/AnyErrorConvertible.framework/AnyErrorConvertible' (no such file), '/Users/nnsnodnb/Library/Developer/Xcode/DerivedData/App-fdpxqniiilivhieveezgolatvbsq/Build/Products/Debug-iphonesimulator/PackageFrameworks/AnyErrorConvertible.framework/AnyErrorConvertible' (no such file), '/Applications/Xcode13.4.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/usr/lib/swift/AnyErrorConvertible.framework/AnyErrorConvertible' (no such file), '/usr/lib/swift/AnyErrorConvertible.framework/AnyErrorConvertible' (no such file), '/Applications/Xcode13.4
というような感じでエラーが発生した。フレームワークが見つからないらしい。
外部ライブラリを依存するときは別でライブラリを追加を委ねるようにするのはだめなのかな😫
ここらへん全く詳しくないので詳しい人教えてほしいです。
とりあえず SwiftPM だけで対応させたい場合は xcframework を依存ライブラリごとビルドをすることでこれを回避することは確認している。
mint run swift-create-xcframework@v2.2.0 --clean MyLibrary AnyErrorConvertible --output Products --platform ios
という感じで外部ライブラリをビルド対象に追加した。
外部ライブラリも同様に xcframework がビルドされるので xcframework としてプロジェクトに追加する。
これで動作する。
もしくは、 CocoaPods に頼ってもいいということであれば CocoaPods で外部ライブラリをプロジェクトに追加したら同様に動作が確認できた。
最後に
ということで SwiftPM 製のライブラリを xcframework ビルドするという記事を書いた。
滅多に今回のようなライブラリを xcframework ビルドして配布をするようなパターンはないかと思うがその想定があると仮定した。
久しぶりに書いたから敬体と常体混合になったがまぁいいでしょう。