見出し画像

REALITY iOS でCarthageからSwiftPMに移行した話

こんにちは。REALITY チャーシュー班のションローです。

画像1

チャーシューに焼き目をつけている様子。

一言にチャーシューと言っても作り方は様々で、私が普段作るのは日本では定番のいわゆる煮て作るチャーシューなのですが、この調理法で作られた豚肉の塊をチャーシューと呼ぶのは適切なのだろうか、とずっとモヤモヤしています。

それはさておき、最近我々の界隈ではApple Siliconの話で色々バタバタしておりますね。
その煽りを受けて今までお世話になっていたパッケージマネージャであるところの Carthage を使うのをやめ、 Swift Package Manager(以下SwiftPM)に移行しました。

この記事では、移行時の環境手順課題移行してどうだったかを公開しています。

なぜ移行したのか

恐らく多くの人が対面したであろうCarthageのこちらのissueがキッカケでした。

issue内で紹介されているワークアラウンドを用いてCarthageを使い続けるという選択肢もありましたが

1. (作業当時)ワークアラウンドを用いた状態でアプリアップデートの申請が通る確証が得られなかった
2. issueが完全に対応され、不安なくCarthageを使えるようになるまで時間が掛かりそうに感じた
3. 単純にSwiftPMを使ってみたかった(爆)

という理由で Carthage から SwiftPM への移行を決めました。

特に、我々のチームは現状 CI/CD 環境を社内管理の端末で構築しており(*1)、Xcode のバージョンアップ時のCarthageに起因した更新作業等もそれなりに手間だと感じていた部分もわりと大きかったです。

どのような環境か

弊プロダクトは XcodeGen で xcodeproj ファイルを自動生成しているため、SwiftPMのパッケージは project.yml に記述しています。
XcodeGen を使った SwiftPM の導入はこちらのドキュメントをご参照下さい。

どのように移行したか

以下は対応時の issue で、赤線で囲っている部分が今回やったことになります。
この当時はiOS14のリリース近辺でややストレスフルだったことがあり、若干強い言葉が出てきていますができればスルーしてください。

スクリーンショット 2020-12-12 16.03.25

移行作業

移行は以下の手順で行いました。

1. Carthage 関連のリソース削除
2. Carthage から SwiftPM へ移せるパッケージを移行する
3. SwiftPM 対応されていないパッケージ等を CocoaPods に移行する

1 は Cartfile Cartfile.resolved の削除、及び project.yml から Carthage 関連の記述の削除だけでした

画像4

...
           - carthage: RxSwift	
           - carthage: RxCocoa	
           - carthage: RxRelay	
           - carthage: RxBlocking	
           - carthage: RxTest
...

削除の様子。 R.I.P 🙏

2,3 に関しては書いてあるとおりですが、FirebaseRxSwiftは CocoaPods に移しました。
Firebaseは当時まだSwiftPMがbeta版だった為で、RxSwiftの理由については後述します。
ちなみに Firebase のSwiftPM対応は現在本リリースされていますが、ぱっと見あんまり安定してなさそうなので、現状ではSwiftPM以外で管理するのが安牌ですね。

ちなみに以下は project.yml 内のSwiftPM関連の記述の一部です。
都合上全公開ができないのですが、雰囲気だけ持って帰ってもらえると幸いです。
パッケージの宣言

...
49 packages:
50     DeviceKit:
51         url: https://github.com/devicekit/DeviceKit.git
52         from: 2.0.0
...

ターゲットの依存

141     Umbrella:
142         type: framework
143         sources: Umbrella
144         platform: iOS
145         deploymentTarget: 12.0
146         dependencies:
147             - package: DeviceKit
...

移行時に困った事と対応

移行時に発生した課題は以下でした。 

1.  Xcode上で依存解決がコケる
2. project.yml のPackageで指定する名前を間違えていた
3. RxTest をテストターゲットから参照しようとするとコンパイルエラーになった

1 のXcode上で依存解決がコケるは現在もちょいちょい起きており、なんらかの原因でキャッシュがぶっ壊れたり(?)した際にエラーになります。
(例えばブランチ切替時に依存関係が更新されたときとか)

画像5

殆どのケースは GUI で Reset Package Caches すれば直ります。が、ややダルいですね。もうちょい安定してほしい。

2 project.yml のPackageで指定する名前を間違えた はそのまんまのポカミスで、シンプルに指定する名前を間違えてハマってしまいました

画像6

これは project.yml の package 以下に

49 packages:
50     swift-protobuf:
51         url: https://github.com/apple/swift-protobuf.git
...

のように(何故か勘違いをして)リポジトリ名を書いてしまっていたんですが、本来はPackage名を書くのがデフォルトで、上記エラーが吐かれていました。

正しくは

49 packages:
50     SwiftProtobuf:
51         url: https://github.com/apple/swift-protobuf.git
...

だったというオチ。
Package名が何かを確認するにはリポジトリのPackage.swiftを見に行かないと行けないのでやや面倒なのですがまぁ仕方ないのかなと思います。

3RxTest をテストターゲットから参照しようとするとコンパイルエラーになった はこの辺の話で、SwiftPMのバグによってRxSwiftが適切に使えない状態にあるようです。
https://github.com/ReactiveX/RxSwift/issues/2210

自分の手元で起きた問題としては

- XcodeがSwiftPM経由でライブラリを参照する際にDynamic Libraryの指定ができず、Static Libraryが強制されてしまう(謎)
- Static Library で RxSwiftをアプリモジュールとテストモジュールから参照しようとするとシンボルの重複でコンパイルエラーになる

という感じでした。
頑張れば回避できるのかもしれませんが、コスパが悪そうだったのでRxSwiftをCocoaPodsに逃がす事でお茶を濁しました。

移行してどうだったか

細かい問題はあれど、CocoaPodsと併用する前提であれば悪くないなという感触です。
クリーンビルド時間が若干伸びましたが問題になるほどではありませんでした。

一方でSwiftPM単体で見ると、対応していないライブラリの存在や細かい課題がそれなりに存在しているため、短期-中期ではCocoaPodsと併用しつつ徐々にSwiftPMの割合を増やすのが安牌かなーと思っています。

まとめ

CarthageからSwiftPMへ移行するにあたってやったことと思ったことをまとめてみました。

「自分もSwiftPMを使ってアプリ開発がしたい!」あるいは「開発環境の改善に興味があります!」というiOSエンジニアの方は随時募集中ですので、ご興味ある方はぜひ応募頂けると幸いです。

応募までは行かないけどちょっと話を聞いてみたい!という人は以下のアカウントまでお気軽にお声がけください。

ちなみに冒頭のチャーシューは日清のカップヌードルに入れて食べました。

とても美味しかったです。

画像2

おわり

*1: 最近は Bitrise も併用しており、ちょっとずつ移行しています