ついに重い腰をあげて、軽量プログラミング言語のバージョン管理はじめました。Perl? そんなものは知りません。
バージョン管理ってなんでしょうか。Subversion とか Git みたいな VCS のことでしょうか。似ていますが、ちがいます。
こんなことはありませんか。
- クライアントが提供する環境が PHP 4 なので、普段の PHP 5 とは別に開発環境を用意しなければならなくなった。
- 最新の Python 3 を導入したら、ほとんどの Python ライブラリが Python 2 系にしか対応していなくて、Python 2 もインストールする必要があった。
- 最新の Ruby 2.0 にアップデートしたら、いつも使っている Ruby のツールが動作しなくなった。
- Node.js がバージョンアップしたので更新したら、ほとんどのライブラリが動かなくなってバージョンをもどす必要がでた。
PHP、Python、Ruby、Node.js のような軽量プログラミング言語を使っていると、このような問題によく直面します。
この問題の難しいところは、 「古いバージョンだと対応できなくなったから、最新バージョンに更新した」だけでは 、問題解決とならないところです。
時には、 「最新バージョンに更新したら、古いバージョンが必要になった」 みたいなことが生じます。
更に、 「この案件では古いバージョンが必要で、その案件では最新バージョンが必要で...」 といった具合に、案件ごとに必要とされる要件は変わるものです。
こういった状況に、いったいどうやって対処するのが良いでしょうか。案件ごとに専用のコンピュータを用意しますか。でも案件の開発者が複数人いたら、どうしますか。これは厄介な問題です。
今回学びたいのは、こういった問題の解決のための、「軽量プログラミング言語のバージョン管理」です。
さて、これらの軽量プログラミング言語を使用したことがある人ならば、gem
pip
npm
のようなコマンドも使用したことがあるでしょう。
これらは順に、Ruby、Python、Node.js のパッケージ管理システムです (PHP にも Pear や Pyrus といったパッケージ管理システムがあります)。
これらパッケージ管理と、バージョン管理とは、何がちがうのでしょう。前者も使用するライブラリのバージョンを管理する仕組みですし、バージョン管理といえるのではないでしょうか。
実際の違いは以下の通りです:
- パッケージ管理とは、軽量プログラミング言語ごとのライブラリから 使用したいライブラリとそのバージョンを管理 する仕組み。
- バージョン管理とは、軽量プログラミング言語 そのもののバージョンを管理 する仕組み。
この違いは理解しておきましょう。
さて、これらをふまえた上で、実際のバージョン管理を始めるにはどうしたら良いでしょう。もちろんそのためのツールを導入するのが賢明です。
しかし、このバージョン管理ツール、結構な種類があります:
この中で Ruby 界隈では近年 rbenv が普及しているようです。
rbenv の特徴としては;
- グローバル環境のバージョン切替に対応
- ローカル環境のバージョン切替に対応
- プラグインによる機能拡張
- バージョン管理に特化したシンプルな設計
などが挙げられます。
個人的見解で言わせてもらえば、これは Node.js の流行と共に訪れた UNIX 思想の再評価の結果だと思います。
rbenv はもう一つの rvm より "do one thing and do it well" の考えに近い実装となっており、シンプルな機能になっています。
シンプルな分、汎用性が高く、rbenv の実装を;
- PHP で再現した phpenv
- Python で再現した pyenv
- Node.js で再現した nenv
が存在します。
従って rbenv の使い方を学ぶことで、PHP、Python、Ruby、Node.js のバージョン管理を同じ方法でできるようになります。
今回はそれをふまえ、rbenv の仕組みを学び、Ruby 以外にもその仕組みを適用したいと思います。
rbenv はシンプルなツールです。ですので実際にバージョン管理で使用するためには ruby-build という別のツールも組み合わせる必要があります。
rbenv はあくまでバージョン管理ツールです。バージョン管理される Ruby のソースコードをダウンロードしてきたり、コンパイルする機能はもちません。そういった機能は ruby-build として提供されているわけです。
ワークフローとしては以下のようになります:
ruby-build
でソースコードをダウンロードしてコンパイル- コンパイルした Ruby を
rbenv
の管理下に設置 rbenv
でその Ruby に切り替えて使用
このようにして使用したい Ruby のバージョンを ruby-build
で取得し、rbenv
で実際に使えるように切り替える仕組みとなっています。
前述の通り rbenv を使うには、Ruby のコンパイルを担当する ruby-build
と、Ruby のバージョン切り替えを担当する rbenv
の 2 つのツールが必要です。
入手やインストール方法は以下のサイトで確認できます:
Mac OS X 環境では Homebrew と組み合わせたインストール方法が一般的でしょう。
まず Homebrew から ruby-build
をインストールします:
brew install ruby-build
ruby-build
のインストール先は Homebrew のコマンドで確認できます:
brew --prefix ruby-build
つづいて GitHub から rbenv
をダウンロードし PATH を通してインストールします:
git clone https://github.com/sstephenson/rbenv.git ~/.rbenv
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
exec $SHELL -l
これで ruby-build
と rbenv
コマンドが使えるようになります。
ruby-build は Ruby のダウンロードとコンパイルを担当するツールです。なので、複数のバージョンを簡単に取得できる仕組みが提供されています。
本来であれば;
- どこからダウンロードして
- どういったコンパイルオプションでコンパイルするのか
指定しなければなりません。
しかし ruby-build
では予めこれらの設定が用意してあります。設定済のインストール可能はバージョン一覧は、次のコマンドで確認できます:
ruby-build --definitions
例えば最新の Ruby 2.0.0-p195
をダウンロード、コンパイルして、/path/to/ruby
に格納するコマンドは次の通りです:
ruby-build 2.0.0-p195 /path/to/ruby
このように単純にバージョンと格納先だけ指定してやれば、後は自動でダウンロードとコンパイルを実行してくれます。
以下は ruby-build
のインストール先ディレクトリ構成です:
ruby-build/
├── bin/
└── share/
└── ruby-build/
└── {バージョン}
ruby-build/share/ruby-build
以下には Ruby のバージョンと対応した名前のファイルが格納されています。これが前述の ruby-build --definitions
コマンドで出力される一覧と対応しています。
この {バージョン}
ファイルはテキストファイルです。この中に、ダウンロード先やコンパイルオプションが記述されています。もしコンパイルエラーでインストールできない時は、このファイルのコンパイルオプションや設定を見直してみましょう。
もちろん、記述形式に沿って、自分で {バージョン}
ファイルを書き、追加してやることも可能です。
コンパイルオプションは環境変数から上書きすることも可能です。上書きするときは CONFIGURE_OPTS
環境変数に値を渡して ruby-build
を実行します。
下記は Mac OS X で Homebrew でインストールされた openssl
と readline
を依存関係に指定する例です:
CONFIGURE_OPTS="--with-openssl-dir=$(brew --prefix openssl) \
--with-readline-dir=$(brew --prefix readline)" \
ruby-build 2.0.0-p195 ~/path/to/ruby
こうすることで、バージョンファイルを書き換えなくても、コンパイルオプションを指定することができます。
これが ruby-build の基本になります。
rbenv は Ruby のバージョン切り替えを担当するツールです。前述の ruby-build でコンパイルした Ruby を rbenv の管理下に格納することで、それらの Ruby を簡単に切り替えられるようになります。
以下は rbenv
のインストール先ディレクトリ構成です:
.rbenv/
├── bin/
├── completions/
├── libexec/
├── shims/
├── test/
└── versions
└── {バージョン}/
rbenv では .rbenv/versions
というディレクトリがあります。そしてその下にそれぞれの Ruby バージョンのディレクトリを作成します。この中に実際の Ruby が格納される仕組みです。
ここで話を ruby-build に戻します。
ruby-build で Ruby をコンパイルするときのコマンドを以下のようにしてみましょう:
ruby-build 2.0.0-p195 ~/.rbenv/versions/2.0.0-p195
rbenv が ~/.rbenv
下にインストールされていれば、上記コマンドで、前述の通り .rbenv/versions
下にコンパイルされた Ruby を格納できます。
つまり ruby-build
のコンパイル先を rbenv の versions
ディレクトリにしてやることで、rbenv に Ruby をインストールしてやることになるのです。
前述の通り Ruby のインストールは次のコマンドです:
ruby-build 2.0.0-p195 ~/.rbenv/versions/2.0.0-p195
しかし ruby-build
と rbenv
がインストールされた環境では、次のコマンドでも同じ結果が得られます:
rbenv install 2.0.0-p195
rbenv install
は ruby-build
コマンドのショートカットです。
そしてインストール可能な Ruby 一覧を確認するコマンドもあります:
rbenv install --list
これは前述の ruby-build --definitions
コマンドのショートカットです。
これらも覚えておくと便利です。
さて、ではインストールされている Ruby バージョン一覧も確認したいところです。そのためのコマンドは次の通りです:
rbenv versions
上記コマンドを実行すると以下のような出力が得られます:
system
* 2.0.0-p195 (set by /Users/User/.rbenv/version)
system
は文字通りシステムに標準でインストールされている Ruby を指します。行頭の *
は現在有効な Ruby を指します。
上記の例では、Ruby の 2.0.0-p195
が現在有効になっているのがわかります。
default_configure_options
CONFIGURE_OPTS