Firebase iOS SDK（Crashlytics）をCarthageで管理する

# はじめに

**Firebase iOS SDK**を導入したのですが、**CocoaPods**管理の場合に**ビルド時間がかかる問題**がありました。
このため、**Carthage**で管理するように変更した内容についてまとめました。

なお、基本的にはFirebase公式リポジトリにある[Carthage.md](https://github.com/firebase/firebase-ios-sdk/blob/master/Carthage.md)に記載されている手順通りに対応することで**Carthage**管理することができます。
以下では、上記手順に沿って対応する中でいくつかハマった点について詳しく説明していきます。

## 今回導入した**Firebase iOS SDK**

* **FirebaseCrashlytics**

## 実行環境

|環境|バージョン|
|:-:|:-:|
|macOS Catalina|10.15.3|
|Xcode|11.3.1|
|Firebase iOS SDK|6.18.0|


# Firebase iOS SDKをCarthageで管理する手順

## 1. **Cartfile**に導入する**Firebase iOS SDK**を指定する

```Cartfile
binary "https://dl.google.com/dl/firebase/ios/carthage/FirebaseAnalyticsBinary.json"
binary "https://dl.google.com/dl/firebase/ios/carthage/FirebaseCrashlyticsBinary.json"
```
> Note that FirebaseAnalyticsBinary must always be included.[^2]

とあるので、**FirebaseAnalyticsBinary**も指定してください。

## 2. carthage updateの実行  
`Carthage/Build/iOS`にSDKがダウンロードされます。

```
FIRAnalyticsConnector.framework
Firebase.framework
FirebaseAnalytics.framework
FirebaseCore.framework
FirebaseCoreDiagnostics.framework
FirebaseCrashlytics.framework
FirebaseInstallations.framework
FirebaseInstanceID.framework
GoogleAppMeasurement.framework
GoogleDataTransport.framework
GoogleDataTransportCCTSupport.framework
GoogleUtilities.framework
nanopb.framework
PromisesObjC.framework
```

## 3. Xcode projectにSDKを追加  

**2**でダウンロードしたSDKをXcode projectに追加します。
**FirebaseXXX.framework**は分かりやすいのですが、それ以外にもいくつかの**framework**がダウンロードされています。
忘れずに追加してください。

<img width="699" alt="Screen Shot 2020-03-09 at 10.13.22.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63892/aa2d4aff-4890-3dec-f761-4bee75d88341.png">
**Embed**は、`Do Not Embeded`にしておく必要があります。
ここが`Embeded & Sign`になっていると**Build**は成功しますが、インストール時に以下のエラーになります。
<img width="419" alt="Screen Shot 2020-03-09 at 10.29.47.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63892/20868e65-e670-8029-ccc8-7061bd489f73.png">


## 4. Build SettingsのOther Linker Flagsに`$(OTHER_LDFLAGS) -ObjC`を追加する

> Add $(OTHER_LDFLAGS) -ObjC flag to "Other Linker Flags" in "Build Settings".

**Build Settings**の**Other Linker Flags**に`$(OTHER_LDFLAGS) -ObjC`を追加します。

<img width="573" alt="Screen Shot 2020-03-09 at 10.47.14.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63892/ae55a58d-b108-2774-58a1-49bb4cffba50.png">

上記設定を**PROJECT**側に設定して各**TARGETS**に反映されるように対応しました。

## 5. Build PhasesのCopy Bundle Resourcesに**GoogleService-Info.plist**を追加する
これはCarthage管理に関係なくFirebase iOS SDKの導入に必要な手順となります。
詳細は以下の公式サイトを参照してください。

* [Firebase を iOS プロジェクトに追加する - ステップ 3: Firebase 構成ファイルを追加する](https://firebase.google.com/docs/ios/setup?hl=ja#add-config-file)
* [設定ファイルをダウンロードする](https://support.google.com/firebase/answer/7015592)


## 6. Build PhasesのLink Binary With LibrariesからFirebase.frameworkを削除する

以下の記載に従って、**Build Phases**の**Link Binary With Libraries**から**Firebase.framework**を削除します。

> Delete Firebase.framework from the Link Binary With Libraries Build Phase.


## 7. 利用するFirebase iOS SDKに応じて、必要なライブラリ/フレームワークを追加する

> Some additional libraries/frameworks may be needed depending on which Firebase frameworks you use, for example: libc++.tbd, sqlite3.tbd, StoreKit.framework, etc. For more information, go here.

とあったのですが、**FirebaseCrashlytics**の場合は特に必要なライブラリ/フレームワークの追加がなかったので今回は作業していません :pray: 


## 8. リソースを含むSDKの場合、Build PhasesのCopy Bundle Resourcesにリソースを追加する

今回の**FirebaseCrashlytics**の場合は関係ありませんが、**FireStore**、**FirebaseMLVisionFaceModel**、**FirebaseMLVisionTextModel**の場合は**Build Phases**の**Copy Bundle Resources**にリソースを追加する必要があります。

|SDK|Bundle Resources|
|:-:|:-:|
| Firestore |./Carthage/Build/iOS/gRPC-C++.framework/Resources/gRPCCertificates-Cpp.bundle|
| FirebaseMLVisionFaceModel |./Carthage/Build/iOS/FaceDetector.framework/GoogleMVFaceDetectorResources.bundle|
| FirebaseMLVisionTextModel |./Carthage/Build/iOS/TextDetector.framework/GoogleMVTextDetectorResources.bundle|


## 9. FirebaseCrashlyticsを利用する場合

CocoaPods管理の場合と異なり、**upload-symbols**と**run**スクリプトを別途ダウンロードする必要があります。

>To automatically upload your app's symbols so your app's crashes are symbolicated, download [upload-symbols](https://github.com/firebase/firebase-ios-sdk/raw/master/Crashlytics/upload-symbols) and [run](https://github.com/firebase/firebase-ios-sdk/raw/master/Crashlytics/run). Then follow the [Crashlytics documentation](https://firebase.google.com/docs/crashlytics/get-started-new-sdk?platform=ios) to add a new run script phase in your Xcode project.

私のプロジェクトでは、定期的に以下のスクリプトを実行してダウンロードするように対応しました。

```
curl -L https://github.com/firebase/firebase-ios-sdk/raw/master/Crashlytics/upload-symbols -o FirebaseCrashlytics/upload-symbols
curl -L https://github.com/firebase/firebase-ios-sdk/raw/master/Crashlytics/run -o FirebaseCrashlytics/run
chmod 755 FirebaseCrashlytics/*
```


## 注意事項 

* **Firebase iOS SDK**には静的ライブラリが含まれているため、**Carthage管理**する場合も**copy-frameworks**には追加しないでください。  

* [Carthage.md](https://github.com/firebase/firebase-ios-sdk/blob/master/Carthage.md)に以下の記載があるように、**Firebase iOS SDKのCarthageディストリビューションは実験段階**となっています。
このため、その旨を理解した上で利用する必要があります。 
> This page introduces and provides instructions for an experimental Firebase Carthage distribution. Based on feedback and usage, the Firebase team may decide to make the Carthage distribution official.[^1]




# 参考情報

* Fabric CrashlyticsからFirebase Crashlyticsへの移行方法
    * [Upgrade to the Firebase Crashlytics SDK](https://firebase.google.com/docs/crashlytics/upgrade-sdk?platform=ios)

* CarthageでインストールできるFirebase iOS SDKの一覧（2020/03/09時点）

```
binary "https://dl.google.com/dl/firebase/ios/carthage/FirebaseABTestingBinary.json"
binary "https://dl.google.com/dl/firebase/ios/carthage/FirebaseAdMobBinary.json"
binary "https://dl.google.com/dl/firebase/ios/carthage/FirebaseAnalyticsBinary.json"
binary "https://dl.google.com/dl/firebase/ios/carthage/FirebaseAuthBinary.json"
binary "https://dl.google.com/dl/firebase/ios/carthage/FirebaseCrashlyticsBinary.json"
binary "https://dl.google.com/dl/firebase/ios/carthage/FirebaseDatabaseBinary.json"
binary "https://dl.google.com/dl/firebase/ios/carthage/FirebaseDynamicLinksBinary.json"
binary "https://dl.google.com/dl/firebase/ios/carthage/FirebaseFirestoreBinary.json"
binary "https://dl.google.com/dl/firebase/ios/carthage/FirebaseFunctionsBinary.json"
binary "https://dl.google.com/dl/firebase/ios/carthage/FirebaseGoogleSignInBinary.json"
binary "https://dl.google.com/dl/firebase/ios/carthage/FirebaseInAppMessagingBinary.json"
binary "https://dl.google.com/dl/firebase/ios/carthage/FirebaseMessagingBinary.json"
binary "https://dl.google.com/dl/firebase/ios/carthage/FirebaseMLModelInterpreterBinary.json"
binary "https://dl.google.com/dl/firebase/ios/carthage/FirebaseMLNLLanguageIDBinary.json"
binary "https://dl.google.com/dl/firebase/ios/carthage/FirebaseMLNLSmartReplyBinary.json"
binary "https://dl.google.com/dl/firebase/ios/carthage/FirebaseMLNLTranslateBinary.json"
binary "https://dl.google.com/dl/firebase/ios/carthage/FirebaseMLNaturalLanguageBinary.json"
binary "https://dl.google.com/dl/firebase/ios/carthage/FirebaseMLVisionAutoMLBinary.json"
binary "https://dl.google.com/dl/firebase/ios/carthage/FirebaseMLVisionBarcodeModelBinary.json"
binary "https://dl.google.com/dl/firebase/ios/carthage/FirebaseMLVisionBinary.json"
binary "https://dl.google.com/dl/firebase/ios/carthage/FirebaseMLVisionFaceModelBinary.json"
binary "https://dl.google.com/dl/firebase/ios/carthage/FirebaseMLVisionLabelModelBinary.json"
binary "https://dl.google.com/dl/firebase/ios/carthage/FirebaseMLVisionObjectDetectionBinary.json"
binary "https://dl.google.com/dl/firebase/ios/carthage/FirebaseMLVisionTextModelBinary.json"
binary "https://dl.google.com/dl/firebase/ios/carthage/FirebasePerformanceBinary.json"
binary "https://dl.google.com/dl/firebase/ios/carthage/FirebaseRemoteConfigBinary.json"
binary "https://dl.google.com/dl/firebase/ios/carthage/FirebaseStorageBinary.json"
```

[^1]: https://github.com/firebase/firebase-ios-sdk/blob/master/Carthage.md#context
[^2]: https://github.com/firebase/firebase-ios-sdk/blob/master/Carthage.md#carthage-usage