OSSライセンス表記の自動生成機能をCocoaPods Pluginで改善した話

モバイルファースト室の@y_310です。

iOSアプリでオープンソースなライブラリを使う場合、サーバサイドアプリケーション以上にソフトウェアライセンスを意識する必要があります。 多くのライブラリはMITライセンスや修正BSDライセンスで提供されていますが、それらのライブラリを使う場合、再配布時に元のライセンス条文を配布物のどこかに含めることが要求されています。

とは言え、アプリケーションに含めたライブラリのライセンスを確認して確実に配布物に含めていく作業というのはどうしても漏れがちで手間なものです。

そこでiOSで標準的に使われているパッケージ管理ツールであるCocoaPodsでは、ライブラリのインストール時に自動的に各ライブラリのライセンス表記を集約し1つのplistファイルにまとめてくれる機能を持っています。 あとはこのファイルをSettings.bundleの中に移動すれば設定アプリの中にライセンスが表示されるようになります。

この辺りのやり方についてはCocoaPodsのWikiに掲載されています。

https://github.com/CocoaPods/CocoaPods/wiki/Acknowledgements

GitHubなどで公に公開されているライブラリのみを使用する場合はこれで終わりです。 しかし社内用のライブラリなど外部に公開していないものがPodfileに含まれている場合、それも自動的にこのファイルに含まれてしまうためあまり具合が良くありません。

ここでようやく本題ですが、この問題を解決するためにcocoapods-ack_filterというCocoaPods Pluginを作りました。

このプラグインを使うと、plistファイルを生成する際に、ライセンス本文が指定した正規表現にマッチするライブラリを除外することができます。

CocoaPods Pluginとは

CocoaPods PluginはCocoaPods 0.28から導入されたプラグイン機構で、podコマンドに機能追加ができるようになります。 作り方の詳細はこちらのオフィシャルブログに書かれています。 http://blog.cocoapods.org/CocoaPods-0.28/

PluginのルールにそってRubyのgemを作るだけなので、Rubyに慣れている人であれば簡単に作ることができます。

インストール

gem install cocoapods-ack_filter

設定

まず、除外したいライブラリのpodspecを変更します。このtextに指定した文字列にマッチさせてライセンス表記を除外させます。

Pod::Spec.new do |s|
  ...
  s.license = { type: 'Private Library', text: 'Copyright 2014 MyCompany Inc. All Rights Reserved.' }
  ...
end

Podfileに以下のpost_installブロックを追加し、正規表現と出力先のパスを適切に変更します。

# Podfile

pod 'AFNetworking'
pod 'MyCompanyLib'

post_install do
  Pod::Command::AckFilter.filter(
    pattern: /MyCompany/,
    output: 'OurApp/Settings.bundle/Acknowledgements.plist'
  )
end

実行

いつものようにpod installするだけです。

pod install

これで、outputに指定したパスにライセンスの記載が不要なライブラリを除外したplistファイルが出力されます。

ちなみにCocoaPods Pluginとして実装しているのでコマンドラインから実行することもできます。

pod ack-filter MyCompany --output=OurApp/Settings.bundle/Acknowledgements.plist

生成されたAcknowledgements.plistは変更管理できるようにリポジトリに含めておきましょう。

まとめ

cocoapods-ack_filterを使うことでライセンス表示ファイルの生成を日常のワークフローの中で完全に自動化することが出来ました。 セットアップも簡単なので新しいアプリに導入する際も少ない工数ですぐに導入できます。

/* */ @import "/css/theme/report/report.css"; /* */ /* */ body{ background-image: url('http://cdn-ak.f.st-hatena.com/images/fotolife/c/cookpadtech/20140527/20140527163350.png'); background-repeat: repeat-x; background-color:transparent; background-attachment: scroll; background-position: left top;} /* */ body{ border-top: 3px solid orange; color: #3c3c3c; font-family: 'Helvetica Neue', Helvetica, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', Meiryo, Osaka, 'MS Pゴシック', sans-serif; line-height: 1.8; font-size: 16px; } a { text-decoration: underline; color: #693e1c; } a:hover { color: #80400e; text-decoration: underline; } .entry-title a{ color: rgb(176, 108, 28); cursor: auto; display: inline; font-family: 'Helvetica Neue', Helvetica, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', Meiryo, Osaka, 'MS Pゴシック', sans-serif; font-size: 30px; font-weight: bold; height: auto; line-height: 40.5px; text-decoration: underline solid rgb(176, 108, 28); width: auto; line-height: 1.35; } .date a { color: #9b8b6c; font-size: 14px; text-decoration: none; font-weight: normal; } .urllist-title-link { font-size: 14px; } /* Recent Entries */ .recent-entries a{ color: #693e1c; } .recent-entries a:visited { color: #4d2200; text-decoration: none; } .hatena-module-recent-entries li { padding-bottom: 8px; border-bottom-width: 0px; } /*Widget*/ .hatena-module-body li { list-style-type: circle; } .hatena-module-body a{ text-decoration: none; } .hatena-module-body a:hover{ text-decoration: underline; } /* Widget name */ .hatena-module-title, .hatena-module-title a{ color: #b06c1c; margin-top: 20px; margin-bottom: 7px; } /* work frame*/ #container { width: 970px; text-align: center; margin: 0 auto; background: transparent; padding: 0 30px; } #wrapper { float: left; overflow: hidden; width: 660px; } #box2 { width: 240px; float: right; font-size: 14px; word-wrap: break-word; } /*#blog-title-inner{*/ /*margin-top: 3px;*/ /*height: 125px;*/ /*background-position: left 0px;*/ /*}*/ /*.header-image-only #blog-title-inner {*/ /*background-repeat: no-repeat;*/ /*position: relative;*/ /*height: 200px;*/ /*display: none;*/ /*}*/ /*#blog-title {*/ /*margin-top: 3px;*/ /*height: 125px;*/ /*background-image: url('http://cdn-ak.f.st-hatena.com/images/fotolife/c/cookpadtech/20140527/20140527172848.png');*/ /*background-repeat: no-repeat;*/ /*background-position: left 0px;*/ /*}*/