cygiwnでrvmを使ってruby-1.9.2をビルド&インストールする

herokuのデフォルトのrubyが1.9.2になるとのことで、cygwinにもruby-1.9.2を入れておくことにしました。
直接ソースをビルドしてシステムに入れるのではなく、rvmを使ってHOME下にインストールしました。

以下は、その手順です。

事前準備1: cygwinパッケージのインストール

cygwin上に以下のパッケージが入ってなければ入れます。当然cygwin自体も最新版にしておきます。(上からssl certの更新で使うもの、さらにrvmで必要なもの、さらにrubyのビルドで必要なもの、です)

  • gcc4
  • mingw-win32api
  • make
  • openssl-devel
  • libgdbm-devel
  • zlib-devel
  • tcltk
  • bison
  • autoconf
  • m4
  • libffi4
  • libreadline7
  • libopenssl098
  • procps
  • quilt

(いらないものや足りないものがあるかも)

事前準備2: cygwinSSLルート証明書のアップデート

cygwin付属のルートSSL証明書は古いようで、gitやcurlwgetでrvmのサイトなどへhttps接続しようとすると失敗してしまいます。
そこでまず、cygwin上のcertを更新する必要があります。

git - SSL certificate rejected trying to access GitHub over HTTPS behind firewall - Stack Overflow の回答にあるやり方そのままでOKでした。
具体的には以下の3行を実行します:

cd /usr/ssl/certs 
curl http://curl.haxx.se/ca/cacert.pem | awk 'split_after==1{n++;split_after=0} /-----END CERTIFICATE-----/ {split_after=1} {print > "cert" n ".pem"}' 
c_rehash

rvmのインストールとruby-1.9.2-headのビルド

事前に古いrvmデータは削除しておきます

rm -rf ~/.rvm ~/.rvmrc

https://rvm.beginrescueend.com/に書いてある方法でrvmを入れます。

bash < <(curl -s https://rvm.beginrescueend.com/install/rvm)

certが古いままならばここで何も表示されずに終わってしまいます。certが更新されていればgit経由でrvmをダウンロードしていきます。

次にrvmを使ってruby-1.9.2を入れます:

source $HOME/.rvm/scripts/rvm
rvm install 1.9.2-head -C "--enable-shared optflags='-O2 -march=native'"

certが古かったり、cygwinパッケージが足りなかったりするとダウンロードやビルドに失敗し赤い文字が画面上に出ます(失敗しなければ緑か白の文字だけ出ます)。

ruby-1.9.2のビルドの仕方はcygwinでrvm - akcnvの個人的備忘録 @ ウィキ - アットウィキのものを参考にしています。今の1.9.2-headではLIBRARY_PATHの設定は不要のようです。(ちなみに1.8.7-headのほうは、上記記事にある対策を取る必要がありました。)

あとビルド時間は結構かかります(5%クロックアップしたASUS UL20Aで1時間くらい)。

rvmのruby-1.9.2がきちんと入ったことを確認する

ビルド後、そのままコマンド

rvm use 1.9.2-head

を実行するとrubyコマンドやgemコマンドが、rvm上のruby-1.9.2のものを使うようになります。

以下のような結果になっていれば入っていることになります:

$ ruby -v
ruby 1.9.2p274 (2011-06-06 revision 31932) [i386-cygwin]

システムのrubyコマンドに戻す場合は、

rvm use system

です。

起動時にrvmコマンドを使えるようにする

以下の行を~/.bashrcや~/.bash_profile等に追加すれば、ターミナルを立ち上げた時点でrvmコマンドが使えるようになります。以下の行はrvmのインストーラーが自動で追加するようです。

[[ -s $HOME/.rvm/scripts/rvm ]] && source $HOME/.rvm/scripts/rvm

デフォルトのrubyをrvmのrubyにする

上記の.bash_profileに加え、以下を実行しておけば、次のターミナル起動からは最初からrubyコマンドやgemコマンドが、rvmのruby-1.9.2のものを使うようになります。

rvm use 1.9.2-head --default

rvm gemsetでgem環境を切り分けよう

rvmはrubyランタイムだけでなく、gemパッケージの環境を切り替えることができます。たとえば、webアプリプロジェクトごとに必要なgemパッケージだけを持った環境を作っておくことで、プロジェクトごとにgem環境を切り替えて使うことができます。

gem環境の管理はrvm useした状態に入ってる時にrvm gemsetコマンドを使って行います。

gem環境作成、たとえばminiblogプロジェクトのための"miniblog"環境を作る場合は

rvm use 1.9.2-head
rvm gemset create miniblog

を実行します。

次に作ったgem環境に切り替えます。

rvm gemset use miniblog

この状態であとはgemコマンドでgem installしていけば良いです。

rvm useコマンドで一緒にgem環境も切り替えることも可能です。

rvm use 1.9.2-head@miniblog

ちなみにデフォルトのgem環境は"global"です。

おまけ: cygwinでrvm install 1.8.7-headする方法

インストール方法

curl -O http://dl.dropbox.com/u/14499563/ruby-1.8.7-p348-cygwin/current-cygwin-has-own-setjmph.patch
rvm install 1.8.7-head -C "--enable-shared optflags='-O2 -march=native'" --patch ./current-cygwin-has-own-setjmph.patch
解説

普通にビルドして失敗するのは、cygwinがすでにsetjmp.hを持っているのに、ソースeval.cとgc.c中でifdef __CYGWIN__内でsetjmp/longjmpのプロトタイプ宣言をしているからです(しかも型が違う)。
そのためmakeを失敗させないためには、単純にこの宣言部分を削除するpatchをつくればいいことになります。

patchの作り方(ruby-1.8.7-p348の場合)

cd ~/.rvm/src/ruby-1.8.7-head/
ed eval.c <<EDIT
210,212d
wq
EDIT
ed gc.c <<EDIT
42,44d
wq
EDIT
git diff > ~/current-cygwin-has-own-setjmph.patch

このpatchはdropbox上においておきます。


https://rvm.beginrescueend.com/rubies/patching/によると、 ".rvm/patches/ruby/1.8.7/"にあるpatchは自動適用されているようで、そこに置くようにgithubでpull requestするのが良いようです。