自作ライブラリを CocoaPods と Carthage 両方に対応させる

# これはなに
Swift のパッケージマネージャは、クライアントサイドには `CocoaPods`, `Carthage` があります。
長らく [CocoaPods](https://github.com/CocoaPods/CocoaPods) 一本でしたが、最近 Swift では [Carthage](https://github.com/Carthage/Carthage) を利用する人も増え、どちらを使うかは開発者によります。ライブラリとしてはどちらも対応していた方が嬉しいですね。
つい最近、拙作ではありますが、 [RxWebKit](https://github.com/RxSwiftCommunity/RxWebKit) というライブラリを両者に対応させたのでその備忘録です。

**ライブラリを使う方ではなく、作る方の話です。**
**また、CocoaPods はハマらなかったのでほぼ Carthage の話になっています。**

# RxWebKit
- Star はこちら [RxWebKit](https://github.com/RxSwiftCommunity/RxWebKit)

[RxSwift](https://github.com/ReactiveX/RxSwift) というリアクティブプログラミングの巨大ライブラリの WebKit ラッパーです。
RxSwift リポジトリでは `Foundation` と `UIKit` で利用できるものしか扱わず、他のフレームワークに依存するものを [RxSwiftCommunity](https://github.com/RxSwiftCommunity) にて運用しています。
このライブラリは `WKWebView` のプロパティを KVO にて監視、変更を受け取れるものになっています。詳細は [README](https://github.com/RxSwiftCommunity/RxWebKit/blob/master/README.md) をご覧ください。

さて、このリポジトリは以下の性質を持っています。

- CocoaPods に対応
- Carthage に対応
- サンプルプログラムを持つ
- RxSwift, RxCocoa に依存する

ディレクトリ構成は以下です。(設定ファイルなどは省く)

```
- Example(AppDelegate.swift, ViewController.swift)
- RxWebKit
   - Source(RxWebKit.swift)
- Cartfile
- Podfile
- RxWebKit.podspec
```

- RxWebKit フォルダ … 本体
- Example フォルダ、Cartfile、Podfile … サンプルプログラム用
- RxWebKit.podspec … CocoaPods 用

ターゲットは以下です。

![](https://qiita-image-store.s3.amazonaws.com/0/56442/fb2e5361-b585-20d4-864e-76f6c8dbda04.png)

```
- Example
- RxWebKit … サンプルプログラム用
- RxWebKit-iOS … Carthage 用
```

# CocoaPods 対応
http://qiita.com/mokemokechicken/items/bf233951d0d531c6823a
こちらの記事が詳しいです。
さすが長いこと Objective-C を支えてきただけあり、簡単です。注意することは一つ。

- 読み込みソースのディレクトリを間違えない

まあこれも `pod lib lint` コマンドで調べられるので試行錯誤は必要でしょうが対応できるでしょう。

# Carthage 対応
意外と苦労しました。というのも CocoaPods のようにコマンドが揃っているわけでもなく、ドキュメントも少ないです。。
コマンドがないのはそれだけシンプルということですが、本記事が何かの参考になれば幸いです。

さて、`carthage update` をする際に何が行われるかというと、dynamic framework をインポートするということが行われます。
ハマりポイントは以下の3点でした。

1. Carthage は自分で dynamic framework を用意しなければいけないこと
1. ビルドできない名前になっていること
1. RxSwift という依存ライブラリがあること

### Carthage は自分で dynamic framework を用意しなければならない
CocoaPods は配布するソースを `.podspec` で記述すればフレームワークの作成は CocoaPods が勝手にやってくれます。
Carthage はフレームワーク自体を配布するので、それを用意します。

それが今回の例だと、 `RxWebKit-iOS` ターゲットになります。
配布するためには、 `RxWebKit-iOS` のスキームを **Shared** にします。
`RxWebKit` の方はサンプルで使うだけなので Shared にしません。
こうすると、Carthage で取り込んだ際に `RxWebKit-iOS` だけが取り込まれます。
![](https://qiita-image-store.s3.amazonaws.com/0/56442/2b8c5432-8dfd-2961-0a30-4ca199bec3c3.png)

配布したいソースファイルはどう指定するかというと、そのファイルのターゲットを追加することでできます。
![](https://qiita-image-store.s3.amazonaws.com/0/56442/d4a0eaad-8a36-23e9-0be0-2e8cc8aba8dc.png)

`import RxWebKit` で取り込むために、`RxWebKit` と `RxWebKit-iOS` に追加します。 `Example` に含めるとサンプルで import しなくても使えるようになってしまうのでやりません。

### ビルドができない名前
これで `RxWebKit-iOS` フレームワークができました。しかしビルドができません。
PRODUCT_NAME が正しくないと言われます。これは名前にハイフンがあるとダメなようで、修正します。

- http://stackoverflow.com/questions/27613812/add-project-reference-to-swift-ios-xcode-project-and-debug

ここの名前が import する時の名前になると思われるので、`RxWebKit-iOS` を `RxWebKit` に変更します。
![](https://qiita-image-store.s3.amazonaws.com/0/56442/2f106577-1840-de40-aee5-08409c1705f7.png)

依存ライブラリがない場合はこれでビルドできると思います。

ちなみに、他の Carthage 対応ライブラリをざっと見てみると、ターゲットごとに

- Product-iOS
- Product-OSX
- Product-WatchOS

となっているのが多いのでハイフンで分けるのが一般的なのかもしれません（自由だと思うけど）。

### 依存ライブラリがある
今回は、 `RxSwift`, `RxCocoa` というフレームワークに依存しています。
なので、まだビルドできません。

何が必要かというと、`RxWebKit-iOS` に依存ライブラリを追加する必要があります。
`Linked Frameworks and Libraries` に追加します。
場所は Carthage で入れた場所、つまり `$(SRCROOT)/Carthage/Build/` 以下にあります。
![](https://qiita-image-store.s3.amazonaws.com/0/56442/a5ed45a6-45f7-dc11-6355-32d4373617bf.png)

これで完了です。

後はコミットをしてプッシュし、タグを付ければおしまいです。

# まとめ
これで CocoaPods, Carthage 両方に対応させることができました。
CocoaPods は `pod` コマンドと前述のリンクの情報で対応が簡単にできました。
Carthage は本家に書いてある `carthage build --no-skip-current` が通るだけではうまくいかないことがあったので、 Carthage 用にターゲットを分ける必要がありました。

依存ライブラリが両者に対応していると、両者に対応せざるを得ないので頑張ってやってみましょう。

## 感想
CocoaPods は登録が必要でしたが Carthage は GitHub にプッシュするだけなので更新が楽だと感じました。
テストもプッシュする前にローカルのリポジトリに対して `carthage update` で確認ができるので安心でした。