libv8 のバージョンを探す
2013年の Ruby on Rails Advent Calendar に参加しようと思ったら、その日のぶんが空いていたので、当日の 23:45 からプログラムを書いてそのまま記事にするというエクストリームアドベントをすることとなりました。プログラマ的には 33 時までは当日だから問題ないよね。
さて今回は Ruby on Rails というか therubyracer というか libv8 の話です。
Ruby on Rails では therubyracer gem をちょくちょく使いますね。therubyracer gem は Ruby から使用できる v8 エンジンで、環境ごとに適切なバイナリパッケージがインストールされるのですが、時折やたらと時間がかかることがあります。*1
この適切なバージョンを見つけ出すためのスクリプトを作成しました。
これを走らせると、
$ ruby libv8_check.rb gem 'libv8', '3.16.14.3'
と、Gemfile に書くべき行を表示してくれます。
何が表示されているか?
libv8 gem には、特定の環境用にビルドされたバイナリ gem と汎用の gem とがあります。この汎用gemをインストールすると非常に時間がかかることになります。
したがって、汎用 gem をインストールするのは避けたいのですが、バイナリパッケージが存在するかどうかの確認は案外手間がかかり、「誰でもできる」とは言い難い状況でした。
ということで、その確認を簡単にするためににこのスクリプトを作成した、ということになります。
このスクリプトは、「存在している libv8 gem の中でもっとも新しい、ユーザ環境で使用できるバイナリ gem のバージョンを表示する」ということをしています。つまり Linux x86_64 環境であればその環境用のバイナリ gem を、また MacOS X 用であればそれ用のバイナリ gem を確認して出力します。
ただ、バイナリパッケージのない環境も存在します。そういう環境で実行した場合は、下のように ~> を使用したバージョンを表示します。
gem 'libv8', '~> 3.16.14.3'
やっていること
環境の選択
bundle install の際、インストールするべきバージョンを選択しているのは bundler ですが、環境やバイナリパッケージを選択しているのは rubygems です。
rubygems の中では Gem::Platform クラスがこのあたりをコントロールしていますので、少しだけこれを借りています。
rubygems API v1 の利用
はじめは Gem クラスを利用して完全なバージョンを取得しようと思ったのですが、「特定の gem の全バージョンを取得する」ということをできるメソッドが見つからず。
Rubygems API を直接利用することにしたところ、これが非常に簡単!
$ curl http://rubygems.org/api/v1/versions/libv8.yaml --- - authors: Charles Lowell built_at: '2013-12-05T00:00:00Z' description: Distributes the V8 JavaScript engine in binary and source forms in order to support fast builds of The Ruby Racer downloads_count: 79 number: 3.16.14.3 summary: Distribution of the V8 JavaScript engine platform: x86_64-solaris-2.11 prerelease: false licenses: - MIT requirements: [] - authors: Charles Lowell built_at: '2013-12-04T00:00:00Z' description: Distributes the V8 JavaScript engine in binary and source forms in order to support fast builds of The Ruby Racer downloads_count: 96 ...
API については http://github.com/rubygems/rubygems.org を git clone して rake routes とか適当にして確認していましたが、ちゃんと公式ドキュメントが整備されていたようです…。
GET - /api/v1/versions/[GEM NAME].(json|xml|yaml)
Returns an array of gem version details like the below:
$ curl https://rubygems.org/api/v1/versions/coulda.json
[
http://guides.rubygems.org/rubygems-org-api/#gem_version_methods
{
"number" : "0.6.3",
"built_at" : "2010-12-23T05:00:00Z",
"summary" : "Test::Unit-based acceptance testing DSL",
"downloads_count" : 175,
"platform" : "ruby",
"authors" : "Evan David Light",
"description" : "Behaviour Driven Development derived from Cucumber but
as an internal DSL with methods for reuse",
"prerelease" : false,
}
]
おわりに
ということで、 Ruby on Rails を使用するうえで比較的欠かせない libv8 の gem をより短い時間でインストールできるようにするべく、適切なバージョンを探し出してくれるスクリプトをこねこねと作成しました。
今回ざっくり実装したこの機能ですが、あと若干汎用化すると「バイナリパッケージが準備された gem かどうかを判定する」機能となるので、そこまで作ってから gem として公開しようかなあなどともくろんでいます。さすがに今日中は無理でした。
以上、2013年 の Ruby on Rails Calendar 9 日目の記事でした。
…あれ?この記事 Rails 関係あったと言えるのかな? …まあいいか!
*1:このへんの詳細については以前書いた http://d.hatena.ne.jp/suu-g/20121222/1356189597 参照のこと