Carthage の不要な .bcsymbolmap ファイルを削除する

## はじめに

carthage を使っていると `Carthage/Build/*/` ディレクトリに .bcsymbolmap ファイルがどんどん溜まってくる経験はないでしょうか？
ビルド時の成果物を元に要不要を選別し、不要な .bcsymbolmap　ファイルを削除するスクリプトを作ったのでご紹介します。

スクリプトはこちらです。
https://gist.github.com/fujikky/13383f5b6e36f71f3bce155e41036e08

## bcsymbolmap とは

`carthage update` コマンドなどでバイナリをビルドしたあとは `*.framework` ファイルや `*.framework.dSYM` ファイルの他に　`*.bcsymbolmap` というファイルも作られます。

.bcsymbolmap ファイルとは　bitcode と dSYM ファイルをマッピングするファイルのようで、 App Store へのサブミット時に必要になるファイルです。

参考: *[How to handle bitcode - SlideShare](https://www.slideshare.net/syoikeda/how-to-handle-bitcode)*

## 問題になるケース

.bcsymbolmap　はモジュールをビルドするたびに新しくファイルが作られるため `carthage update` を繰り返すたびに増えていきます。

たとえば開発効率改善のためビルド後のバイナリをリポジトリにそのままコミットしていたり、 S3 などに上げているケースがあると思うのですが、その場合古い .bcsymbolmap がずっと残っていると、キャッシュの容量をどんどん圧迫していきます。これらの不要なファイルは随時消えてほしいわけです。

ファイル名からはどの　.bcsymbolmap　が使われているのかが分からないため、今まではアップデートのたびにビルドディレクトリを一旦すべて削除してから再ビルドするという方法をとっていました。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">Carthage の古い bcsymbolmap ファイル消してくれない問題は、単純に rm -rf Carthage やってから carthage update やってました… <a href="https://twitter.com/hashtag/ios_test_night?src=hash&amp;ref_src=twsrc%5Etfw">#ios_test_night</a></p>&mdash; fujikky (@fujikky) <a href="https://twitter.com/fujikky/status/890166630398910464?ref_src=twsrc%5Etfw">2017年7月26日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

ただ、 Carthage の `--cache-builds` というオプションを使うと、再ビルドが不要なものは省いてくれるようになったので、ビルド時間削減のためにできるだけビルドディレクトリをまるごと削除という対応はしたくありません。

そこで今回のシェルスクリプトを書きました。

## cleanup_bcsymbolmap シェルスクリプト

スクリプトは `Carthage` フォルダがあるプロジェクトのルートで実行してください。

```
$ ./cleanup_bcsymbolmap --help
Usage: ./cleanup_bcsymbolmap [Options]
Options:
    -h, --help                Display usage
    -p, --project-directory   Directory containing Carthage project
    -f, --force               Omit confirmation
```

実行すると、残すファイルと削除するファイルがリストアップされ、確認のために　`y` を入力すると削除されます。

```
$ ./Scripts/cleanup_bcsymbolmap
....................

Keeps:
/Users/*****/Carthage/Build/iOS/********-****-****-****-************.bcsymbolmap used in RxSwift
/Users/*****/Carthage/Build/iOS/********-****-****-****-************.bcsymbolmap used in RxCocoa
/Users/*****/Carthage/Build/iOS/********-****-****-****-************.bcsymbolmap used in RxBlocking
/Users/*****/Carthage/Build/iOS/********-****-****-****-************.bcsymbolmap used in RxSwift
/Users/*****/Carthage/Build/iOS/********-****-****-****-************.bcsymbolmap used in RxCocoa
/Users/*****/Carthage/Build/iOS/********-****-****-****-************.bcsymbolmap used in RxBlocking

Removes:
/Users/*****/Carthage/Build/iOS/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXXX.bcsymbolmap
/Users/*****/Carthage/Build/iOS/YYYYYYYY-YYYY-YYYY-YYYY-YYYYYYYYYYYYY.bcsymbolmap

Are you sure to remove? (y/n): y
Removed: /Users/*****/Carthage/Build/iOS/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXXX.bcsymbolmap
Removed: /Users/*****/Carthage/Build/iOS/YYYYYYYY-YYYY-YYYY-YYYY-YYYYYYYYYYYYY.bcsymbolmap
```

実現をしているコアの部分ですが

```
$ xcrun dwarfdump --uuid Carthage/Build/iOS/RxSwift.framework/RxSwift

UUID: ********-****-****-****-************ (i386) Carthage/Build/iOS/RxSwift.framework/RxSwift
UUID: ********-****-****-****-************ (x86_64) Carthage/Build/iOS/RxSwift.framework/RxSwift
UUID: ********-****-****-****-************ (armv7) Carthage/Build/iOS/RxSwift.framework/RxSwift
UUID: ********-****-****-****-************ (arm64) Carthage/Build/iOS/RxSwift.framework/RxSwift
```

というコマンドで、フレームワークの各アーキテクチャ用の UUID が取れるので、それを元に現在のディレクトリ内の .bcsymbolmap ファイルと照合し、不要なファイルを洗い出しているという感じです。

## Carthage 公式での対応

なお、 `carthage cleanup` というコマンドを実装するという Pull Request が今年の初め頃に上がっていましたが、~~2018年9月26日現在、動きはない模様です。~~
2019年9月24日にマージされました。

https://github.com/Carthage/Carthage/pull/2333

これが実装されれば、公式で対応できるのでもっと便利そうですね。