CocoaPodsでは公式なSpecリポジトリがGitHub上に公開されています。
https://github.com/CocoaPods/Specs
従来からこれとは別にPrivateなSpecリポジトリを用意する方法がありました。さらにCocoaPods 0.34から Podfile
に宣言できるようになったことで明示的に参照するSpecリポジトリが指定できます。
source 'https://github.com/makotokw/CocoaPodsSpecs.git'
source 'https://github.com/CocoaPods/Specs.git'
今回は自前のSpecリポジトリの作成と利用法について書きます。
自前のSpecリポジトリが必要なケース
CocoaPodsではPodfile
に以下のように書くことで本家のリポジトリにない自前のPodを使うことができます。
pod 'WZYFlatUIColor', :git => 'https://github.com/makotokw/CocoaWZYFlatUIColor.git'
これで済むならSpecリポジトリを用意する必要はありません。Specリポジトリが必要になる理由としては以下のようなものがあります。
- Podの依存関係やバージョンを適切に管理したい
- 柔軟にPodのバージョンを指定したい
Podの依存関係
長くライブラリを開発しているとさらに共通の処理を別の共有ライブラリに作成して逃したくなります。そうするとPodとPod間に依存関係が必要になります。CocoaPodsではPodごとのPodspecファイルに dependency
シンタックスを使って依存関係を宣言することができます。
spec.dependency 'CommonLibrary2'
しかしdependency
シンタックスでは :git
オプションがサポートされておらずSpecリポジトリにあるPodでなければ依存関係に指定できません。Specリポジトリを用意しないで解決するにはdependency
シンタックスを使わずにアプリケーション側で Podfile
に以下のようにPodに依存するPodを全て指定する必要があります。
pod 'CommonLibrary', :git => 'https://github.com/makotokw/CommonLibrary.git'
pod 'CommonLibrary2', :git => 'https://github.com/makotokw/CommonLibrary2.git'
しかし、この回避策ではアプリケーションの開発者がライブラリの依存関係を全て把握し、依存関係に変更があった場合にPodfile
の内容を同期しなければなりません。
Podのバージョン管理
長く開発していると全てのアプリケーションが同じバージョンのライブラリを利用することは難しくなります。例えば、ある共有ライブラリでv2.0からiOS5を切るといった選択をした場合、iOS5対応のアプリではv1.*を使うということで以下のように書きたいものです。
pod 'CommonLibrary', '~> 1.0'
これを git
オプションで参照するPodの場合は branch
や tag
を使って管理することになります。
pod 'CommonLibrary', :git => '...', :branch => 'develop'
pod 'CommonLibrary2', :git => '...', :tag => '1.0'
この場合 '~> 1.0'
のようなバージョン比較の記述が利用できません。
またアプリケーションとライブラリの依存ならともかく、以下のようにライブラリ間でバージョンの依存関係ができてしまうとアプリケーション開発者がすべてのライブラリの依存関係を Podfile
で管理するのは難しくなってきます。
- CommonLibrary
v1.0
が CommonLibrary2v1.*
に依存する - CommonLibrary
v1.1
が CommonLibrary2v2.*
に依存する
CommonLibraryがどのライブラリのバージョンに依存しているかはカプセル化されているべき内容です。自前のSpecリポジトリを用意すれば :git
オプションに頼ることなくライブラリを利用でき、バージョン利用の柔軟性や、Pod間の依存関係をライブラリの開発者に任せることができます。
それまではアプリケーションごとの Podfile
で頑張ってはいましたが管理が限界に来ていたため sources
の指定が義務付けられたCocoaPods 0.34のタイミングで自前のSpecリポジトリの利用に踏み切りました。
Specリポジトリを作成する
本家がそうであるようにSpecリポジトリはただのGitリポジトリとして存在します。Private Specリポジトリと呼ばれることもありますが、実際にPrivateかどうかはこのGitリポジトリの公開範囲できまります。GitリポジトリがPrivateであればそのSpecリポジトリはPrivateなものになりますし、GitHubなどでPublicなSpecリポジトリとして公開することも可能です。
Specリポジトリは以下のような構造でファイルを管理することで利用できます。
.
└── [SPEC_NAME]
└── [VERSION]
└── [SPEC_NAME].podspec
しかしPodのリリースの度にバージョンフォルダを作成してPodspecファイルを追加するのは面倒なので、これを行ってくれる pod repo push
コマンドを利用します。
リポジトリの登録
pod repo push
を使う準備作業として、まず push する先のSpecリポジトリを名前付きで登録します。Gitのリモートリポジトリのようなものだと考えると良いでしょう。
pod repo add REPO_NAME SOURCE_URL
たとえば以下のように書くことができます。
pod repo add makotokw git@github.com:makotokw/CocoaPodsSpecs.git
Podを登録する
SpecリポジトリにPodを登録するにはPodspecファイルを用意して、事前に登録しておいたREPO_NAME
に対して pod repo push
を使うことで行えます。このコマンドでは指定したPodspecファイルの内容に準じて適切な階層にファイルを追加し、Gitのpushまでを行ってくれます。
この作業はPodの新しいバージョンをリリースする度に行い、既に登録済みのバージョンがあった場合は既存のものを差し替えることができます。
pod repo push makotokw CommonLibrary.podspec --allow-warnings
pod repo push
ではPodspecファイルの内容を検証し、問題があれば登録できません。本家のSpecリポジトリに登録する際に使われることもあってか検証は厳し目になっています。
例えばLicense情報の指定がないと警告になり登録できないなど、PrivateなSpecリポジトリの場合には本質的ではない検証もあるため --allow-warnings
で警告を許可するのも有効です。
なお pod spec lint NAME.podspec
で登録する前に検証ができます。この際にdependency
で本家のSpecリポジトリに登録されていないPodに依存している場合は --sources
にSpecリポジトリを指定する必要があり、以下のような形で実行します。警告を無視するのであれば--allow-warnings
を指定できます。
pod spec lint NAME.podspec --sources=makotokw --allow-warnings
pod spec lint
ではPodspecファイルでsource
に指定したソースコードが検証されます。以下のように指定している場合はGit上のソースコードが検証の対象になります。
spec.source = { :git => "https://github.com/makotokw/CommonLibrary.git", :tag => "v1.0.0" }
ローカルのソースコードで確認したい場合は pod lib lint
コマンドを代わりに使うことができます。
pod lib lint NAME.podspec --sources=makotokw,master --allow-warnings
作成したSpecリポジトリを利用する
冒頭にも書きましたが作成したSpecリポジトリを利用するにはPodfile
のsourceで宣言します。
source 'https://github.com/makotokw/CocoaPodsSpecs.git'
source 'https://github.com/CocoaPods/Specs.git'
Specリポジトリは宣言した順番に検索されます。(以前は名前順でSpecsリポジトリが検索され、本家がmaster
という名前のため自前のリポジトリ名がM
より前か後ろかで挙動が変わる問題がありました)
従って自前のSpecリポジトリを先に宣言しておけば、本家のSpecリポジトリで公開されているPodをforkし、自前のSpecリポジトリに登録することでforkした方を優先して利用するといった使い方ができます。(ただしpod install
時に同名のPodが複数のSpecリポジトリから検出されると警告はでます)
Specリポジトリを使う際の注意点
CocoaPodsのバージョンによって許可されていたシンタックスが非推奨になったり、挙動が変わることによってSpecリポジトリにあるPodspecファイルを書き直すなどメンテナンスが必要になることがあります。
実際問題、0.35の際に循環依存のチェックが入って修正を余儀なくされました。本家のSpecリポジトリでもみんなで修正している様が伺えます。#12783, #12819
これはSpecリポジトリに限った話ではありませんが、CocoaPodsを使う場合は更新情報をチェックして特にBreakingな修正には動作を確認しておく必要があります。時にはXcodeのバージョンにも左右されることもあります。
CocoaPodsは便利ですが深く付き合うにはそれなりの覚悟も必要です。
まとめ
Private Specリポジトリ自体は昔からありましたが、source
の宣言がサポートされようやくライブラリ開発者にとってもアプリケーション開発者にとっても利用しやすくなったと思います。幾つものアプリケーションを開発している方はうまくライブラリを再利用することで生産性を高めていくとよいでしょう。
一方で本家のリポジトリに登録する、自前のSpecリポジトリを公開するなど自作のPodをオープンにしてくことも忘れないようにしたいと思います。
CocoaPodsはバージョン更新によって挙動が変わるのでチームで使うにはどのバージョンを使うか、いつアップデートするかなどSpecリポジトリの管理も含めてチームの中で誰が責任をもって運用するかが重要です。