
Now in REALITY Tech #64 iOSのパッケージマネージャーをCocoaPodsからSPMに移行した話
今週の「Now in REALITY Tech」は、REALITY iOSアプリのプロジェクトで依存するライブラリの管理をCocoaPodsとSwift Package Manager(以下、SPM)の併用からSPMに移行対応についてiOSチームからお送りします。
SPM移行の背景と目的
CocoaPodsはRuby製のパッケージマネージャーであるため、RubyのバージョンやCocoaPodsのバージョン差異およびビルド環境(M1 or Intelなど)によってはビルドに失敗することがありました。
これらの問題を解消するために、Xcodeのみでビルド可能なSPMに移行したいという要望がありましたが、SPMは具体的にどのようなメリット、デメリットがあるのか深ぼってみます。
SPMのメリット
SPMはApple公式で提供されているパッケージマネージャーであるため、メ
ンテナンスが充実しています。
また、swift-algorithmsなどのApple製のライブラリはSPMでのみ導入可能であるなどライブラリ提供側もApple製のパッケージマネージャーのみ対応することが増えると予想されるため、パッケージマネージャーをSPMに完結することで、開発者のコストを減らすことが出来ます。
その他、Apple製のCIツールであるXcodeCloudの利用に向けて導入の障壁を減らしたいなど副次的な目的もありました。
SPMのデメリット
SPMのシステム要件はSwiftとgitのみですが、SwiftのバージョンはXcodeに依存するため、開発者間で使用するXcodeのバージョンを合わせる必要があります。
また、SwiftやXcodeのバージョンアップに伴い依存ライブラリのバージョンの更新が必要がなど、バージョンアップに起因する問題に対処する必要もありました。
上記のメリット・デメリットを踏まえ、SPMに移行することによる恩恵の方が高いと判断し、移行する方針となりました。
SPM移行の内容
それでは、実際にCocoaPodsのライブラリをSPMに移行していきましょう。
移行方法および手順としては下記になります。
依存ライブラリがSPMサポートされている場合、SPMに移行する
依存ライブラリがSPMサポートしていない場合、SPM対応のPull Requestを作成する
SPM対応のPRがマージされない場合の対応
リポジトリをForkしてSPM対応版のライブラリを作る
依存ライブラリのファイルをiOSプロジェクトにコピーする
Podsプロジェクトを作成しないようにする
それぞれの対応について詳細を記述します
1. 依存ライブラリがSPMサポートされている場合、SPMに移行する
こちらの対応は一番簡易で、既に依存ライブラリがSPMをサポートしているケースでは、ライブラリのバージョンさえ気をつけていればCocoaPodsからSPMへの移行は簡易に行えます。
注意点としては、依存ライブラリのリポジトリのリリースノートで「Support Swift Package Manager」と記載があったり、Package.swiftが配置されていたとしても実際にimportしてビルドするとビルドエラーになることがあったため、一つ一つビルドできるか試すことが必要となります。
2. 依存ライブラリがSPMサポートしていない場合、SPM対応のPull Requestを作成する
直近でメンテナンスされていないライブラリをアプリで使用している場合、SPM対応されていないケースがあります。
弊社だけでなく、他にもライブラリ利用者がSPMでライブラリを使用できるように、SPMに対応したPull Requestを作成しました。
SPMの対応方法については、Appleにドキュメントがあるのでこちらが参考になります。
https://developer.apple.com/documentation/xcode/swift-packages
https://developer.apple.com/documentation/xcode/creating-a-standalone-swift-package-with-xcode
XibやStoryboard、ローカライズリソースなどのリソースファイルをSwift Packageに含める場合には特定の手順が必要になるケースがあるので注意が必要です。
SPM対応の参考例
ご参考までにオープンソースライブラリへのSPM対応において実際にPRを作成した内容を紹介します。
特にXLPagerTabStripへのPRは、ディレクトリ構成をSPM対応用に変更したり、リソースファイルを扱う上での変更を追加しているため対応の難易度や注意点がわかるかと思います。
3. SPM対応のPRがマージされない場合の対応
2で行ったSPM対応がマージされないケースがありました。この場合には、2つの対応を行いました。
リポジトリをForkしてSPM対応版のライブラリを作る
依存ライブラリのファイルをiOSプロジェクトにコピーする
1は自社でライブラリを管理および保守する運用のもと、元のリポジトリからForkしてSPM対応しました。
2は依存ライブラリ自体が薄い実装であれば、iOSプロジェクトに直接ファイルをコピーして対応しました。ただし、ライセンス表記は適切に行われるように注意しました。弊社では、ライセンス出力をLicensePlistを使用しているため、manualで取り込むようにしています。
Podsプロジェクトを作成しないようにする
1,2,3でCocoaPodsで管理していたライブラリをSPMに移行できたら、最後に後処理としてPodsプロジェクトを削除します。
ただし、SwiftLintなどのCLIツールを引き続きCocoaPodsで管理しているため、PodfileはそのままでPodsプロジェクトを生成しないようにします。
対応としては、Podfileでinstallオプションを追加します。具体的には、integrate_targetsをfalse、skip_pods_project_generationをtrue にします。
対応としては以上で完了です。
// Podfile
platform :ios,'15.0'
install! 'cocoapods', integrate_targets: false, skip_pods_project_generation: true
pod 'SwiftLint'
...
SPM移行による今後の方針
CocoaPodsの撤廃によりxcworkspaceが不要となりxcodeprojのみでビルドできるようになりましたが、弊社ではxcodeprojの生成のためにXcodeGenを使用しています。脱XcodeGenは追加の大幅な工数が必要であったため、今回はxcworkspaceを引き続き使用しPodsプロジェクトのみを削除する対応をとりましたが、将来的にはXcodeGenも撤廃し、Xcodeでプロジェクトを開くだけでビルドできる状態にしていきたいです。
まとめ
長年お世話になっていたCocoaPodsからSPMに移行することにより、開発環境としてはこれから益々恩恵を受けられそうと感じています。
ただ、メジャーでないライブラリはSPM対応以前にメンテナンスも行われていない状況であったりもするため、弊社では依存ライブラリの棚卸しを行い、不要なライブラリを削除することでビルド時間も削減されるので、なるべくライブラリに依存せず不要なライブラリは削除しています。
SPMはXcodeのバージョンやバージョンアップに伴い、不安定なバージョンがあったりしましたが、現在では機能も充実して安定的に利用できているので今後も活用していきたいです。
REALITYでは改善系施策や開発環境の効率化を一緒に考えていける仲間を引き続き募集しております。