rbenv-communal-gemsインストール(トラブル含)

Ruby - gemの移行でさっと使えるコマンドまとめ - Qiita のコメント欄で良い情報を得ました。

rbenv-communal-gemsというプラグインを利用すると、RubyのABI互換の単位でgemを共通に管理してくれるようになるので、ruby-2.1.2とruby-2.1.3などで同じgemを見てくれるようになります。
Ruby - gemの移行でさっと使えるコマンドまとめ - Qiita

以前から 1.9.3-p484 と 1.9.3-p547 とで重複した rubygems が入っているのがイヤだったのですが、これで共有できる!と思ったので入れてみました。

その前に、ABIって何よ

Application Binary Interface(アプリケーション・バイナリー・インタフェース、ABI)とは、アプリケーションプログラムと基本ソフトウェアであるオペレーティングシステム (OS) の間の低レベルのインタフェースを意味する。
ABIはオブジェクトコードレベルのインタフェースであり、互換ABIをサポートするシステム間では同じ実行ファイルを変更無しで動作させることができる。

Ruby の場合
  • 2.1.0以降

ABI 互換性
ABI は {MAJOR}.{MINOR}.0 のスキーマに従うものとします。
われわれは同一の MINOR レベルのリリースにおける ABI 互換性の維持に最大限注力します。 したがって TEENY は0に固定されます。

上2桁だけで ABI 互換。つまり 2.1.0 も 2.1.1 も ABI 互換。

  • 2.1.0以前

1.9.3 、 2.0.0 など3桁とも合っていないと ABI 互換じゃないです。( 2.0 台は 2.0.0 しか無いですけどね)

話戻してrbenv-communal-gemsインストール

Homebrew でインストールできます。

$ brew install rbenv-communal-gems

'14/10/19追記:

anyenvをインストール&インストール済のrbenvと互換を取る - 別館 子子子子子子(ねこのここねこ)
で anyenv にプラグインを管理させることにしたので

$ git clone git://github.com/tpope/rbenv-communal-gems.git ~/.rbenv/plugins/rbenv-communal-gems

で入れました。

追記ここまで

1.9.3-p547を再インストール

最近調子が悪かったので入れ直しました。

$ CONFIGURE_OPTS="--enable-shared --with-readline-dir=`brew --prefix readline` --with-openssl-dir=`brew --prefix openssl`" rbenv install -f 1.9.3-p547
Downloading ruby-1.9.3-p547.tar.gz...
-> http://dqw8nmjcqpjn7.cloudfront.net/9ba118e4aba04c430bc4d5efb09b31a0277e101c9fd2ef3b80b9c684d7ae57a1
Installing ruby-1.9.3-p547...
Installed ruby-1.9.3-p547 to /Users/riocampos/.rbenv/versions/1.9.3-p547

Communized gems for 1.9.3-p547

最後に「Communized gems for 1.9.3-p547」というメッセージが出ましたね。
~/.rbenv/versions/1.9.3-p547 を確認すると

$ ls -l
total 0
drwxr-xr-x+ 10 riocampos  staff  340 10 18 14:02 bin
drwxr-xr-x+  3 riocampos  staff  102 10 18 14:03 etc
drwxr-xr-x+  3 riocampos  staff  102  6 19 13:37 include
drwxr-xr-x+  9 riocampos  staff  306 10 18 14:02 lib
drwxr-xr-x+  5 riocampos  staff  170  6 19 13:37 share

このように etc フォルダが増えました。この中には gemrc ファイルが入っています。

# added by rbenv communize
install: "--env-shebang"
gemhome: "/Users/riocampos/.rbenv/gems/1.9.1"

現状 /Users/riocampos/.rbenv/gems/1.9.1 は空っぽです。
試しに pry gem をインストール。

$ gem install pry
Fetching: coderay-1.1.0.gem (100%)
Fetching: slop-3.6.0.gem (100%)
Fetching: method_source-0.8.2.gem (100%)
Fetching: pry-0.10.1.gem (100%)
Successfully installed coderay-1.1.0
Successfully installed slop-3.6.0
Successfully installed method_source-0.8.2
Successfully installed pry-0.10.1
4 gems installed
$ ls -l ~/.rbenv/gems/1.9.1/ 
total 0
drwxr-xr-x+ 4 riocampos  staff  136 10 18 14:32 bin
drwxr-xr-x+ 6 riocampos  staff  204 10 18 14:32 cache
drwxr-xr-x+ 2 riocampos  staff   68 10 18 14:32 doc
drwxr-xr-x+ 6 riocampos  staff  204 10 18 14:32 gems
drwxr-xr-x+ 6 riocampos  staff  204 10 18 14:32 specifications
$ ls -l ~/.rbenv/gems/1.9.1/gems/
total 0
drwxr-xr-x+  7 riocampos  staff  238 10 18 14:32 coderay-1.1.0
drwxr-xr-x+ 12 riocampos  staff  408 10 18 14:32 method_source-0.8.2
drwxr-xr-x+  7 riocampos  staff  238 10 18 14:32 pry-0.10.1
drwxr-xr-x+ 12 riocampos  staff  408 10 18 14:32 slop-3.6.0

このように、 gem ファイルは今まで ~/.rbenv/versions//lib/ruby/gems//gems にインストールされていましたが、 rbenv-communal-gems により~/.rbenv/gems//gems にインストールされるようになりました。なお ~/.rbenv/versions//lib/ruby/gems/ には ~/.rbenv/gems/ へ張られたエイリアスが作られます。

トラブル:既存 gem が入っているバージョンの Ruby を rbenv-communal-gems 管理下に入れると gem を消された

普段メインに使っている Ruby は 1.9.3-p484 です。
rbenv global 1.9.3-p547 の環境で

$ rbenv communize 1.9.3-p484 
Communized gems for 1.9.3-p484

を実行したところ、~/.rbenv/versions/1.9.3-p484/etc/gemrc が出来ていました。
そして gem を保持するために ~/.rbenv/versions/1.9.3-p484/lib/ruby/gems/ の中身を ~/.rbenv/gems/1.9.1 へ移して…くれず、中身をきれいさっぱり消して、単なる ~/.rbenv/gems/1.9.1 へのリンクにしてくれましたorz
仕方ないので Time Machine で復活させましたw
そして改めてやり直した rbenv global 1.9.3-p484 の環境でも…同様に消してくれましたwwwww
やってらんねーぜw

お作法

まず ~/.rbenv/versions//lib/ruby/gems/ フォルダを移動

ただし、このまま gems フォルダが無いと

$ rbenv communize 1.9.3-p484 
No gem directory for 1.9.3-p484

と文句を言う。
ので gems フォルダ作っておく。

rbenv communize 実行
$ rbenv communize 1.9.3-p484 
Communized gems for 1.9.3-p484

先ほど作った gems フォルダ rbenv communize で削除されて gems リンク(~/.rbenv/gems/1.9.1 へのリンク)を作成& ~/.rbenv/versions/1.9.3-p484/etc/gemrc ファイル作成

先ほど移動した gems フォルダの中身を ~/.rbenv/gems/ の中に上手に移動させる

私の場合は 1.9.3-p484 ばかり使っていたので 1.9.3-p547 で入れた gem はどーでもいいです(上記で pry 入れただけだし)。なので、そのまま上書きしました。

gem list で動作確認

移動させた gem が動いてました。

試しに 2.0.0-p576 をインストール

$ CONFIGURE_OPTS="--enable-shared --with-readline-dir=`brew --prefix readline` --with-openssl-dir=`brew --prefix openssl`" rbenv install 2.0.0-p576
Downloading ruby-2.0.0-p576.tar.gz...
-> http://dqw8nmjcqpjn7.cloudfront.net/9f5a593d81768c856155be6b2d2e357b961b5c43e04ba54c1ee511987fac2b66
Installing ruby-2.0.0-p576...
Installed ruby-2.0.0-p576 to /Users/riocampos/.rbenv/versions/2.0.0-p576

Communized gems for 2.0.0-p576
$ rbenv global 2.0.0-p576 
$ ruby -v
ruby 2.0.0p576 (2014-09-19 revision 47628) [x86_64-darwin13.4.0]
$ ls -l ~/.rbenv/versions/2.0.0-p576/lib/ruby 
total 8
drwxr-xr-x+ 135 riocampos  staff  4590 10 18 18:07 2.0.0
lrwxr-xr-x    1 riocampos  staff    16 10 18 18:07 gems -> ../../../../gems
drwxr-xr-x+   3 riocampos  staff   102 10 18 18:07 site_ruby
drwxr-xr-x+   3 riocampos  staff   102 10 18 18:07 vendor_ruby
$ ls -l ~/.rbenv/gems/
total 0
drwxr-xr-x+ 8 riocampos  staff  272 10 18 17:32 1.9.1

ここでテキトーな gem を入れます。pry gem でも入れましょう。

$ gem install pry
Successfully installed coderay-1.1.0
Fetching: slop-3.6.0.gem (100%)
Successfully installed slop-3.6.0
Fetching: method_source-0.8.2.gem (100%)
Successfully installed method_source-0.8.2
Fetching: pry-0.10.1.gem (100%)
Successfully installed pry-0.10.1
4 gems installed
$ ls -l ~/.rbenv/gems/
total 0
drwxr-xr-x+ 8 riocampos  staff  272 10 18 17:32 1.9.1
drwxr-xr-x+ 8 riocampos  staff  272 10 18 18:08 2.0.0
$ ls -l ~/.rbenv/gems/2.0.0/
total 0
drwxr-xr-x+ 4 riocampos  staff  136 10 18 18:09 bin
drwxr-xr-x+ 2 riocampos  staff   68 10 18 18:08 build_info
drwxr-xr-x+ 6 riocampos  staff  204 10 18 18:09 cache
drwxr-xr-x+ 2 riocampos  staff   68 10 18 18:08 doc
drwxr-xr-x+ 6 riocampos  staff  204 10 18 18:09 gems
drwxr-xr-x+ 6 riocampos  staff  204 10 18 18:09 specifications

~/.rbenv/gems/ にバージョン名のフォルダが作られました。
なので、 rbenv-communal-gems にまだ対応させていない2.1系に関しても、上で書いた「お作法」通りに gems フォルダを動かせば良さそうですね。OKでした。

アンインストール(2017/1/18追加)

rbenv-communal-gems をアンインストールしました。ABIが同じ複数バージョンをインストールした場合に古いバージョンを消すとエラーが出るので、やはり使いづらいと思うようになりました。

gemフォルダを再配置

The opposite command is rbenv sequester, which removes the symlink and recreates it as an empty directory.
tpope/rbenv-communal-gems: Share gems across multiple rbenv Ruby installs

$ rbenv sequester --all
Sequestered gems for 1.8.7-p375
Sequestered gems for 1.9.3-p551
Sequestered gems for 2.0.0-p643
Sequestered gems for 2.1.10
Sequestered gems for 2.2.4
Sequestered gems for 2.3.3
Sequestered gems for 2.5.0

いろいろ入れてあったのでこんな感じ。
これにより上にあった

~/.rbenv/versions//lib/ruby/gems/ には ~/.rbenv/gems/ へ張られたエイリアスが作られます。

で作られたエイリアスが消され、空のフォルダが作られます。空のフォルダなので、~/.rbenv/gems/ 以下の適切なバージョン番号のフォルダを手作業で移動すれば良いです。

rbenv-communal-gems 削除

~/.rbenv/plugins/rbenv-communal-gems フォルダを削除します。
念のためシェルは新しく開きます。
これで OK ですね。

と思いきや。

.gemrcのgemhome設定を削除

まだRuby 2.3.3をメインに使っているのですが、なぜか gem が2.5.0のほうを見てしまう。確認してみよう。

$ gem environment
RubyGems Environment:
  - RUBYGEMS VERSION: 2.5.2
  - RUBY VERSION: 2.3.3 (2016-11-21 patchlevel 222) [x86_64-darwin16]
  - INSTALLATION DIRECTORY: /Users/riocampos/.anyenv/envs/rbenv/gems/2.5.0
  - USER INSTALLATION DIRECTORY: /Users/riocampos/.gem/ruby/2.3.0
  - RUBY EXECUTABLE: /Users/riocampos/.anyenv/envs/rbenv/versions/2.3.3/bin/ruby
  - EXECUTABLE DIRECTORY: /Users/riocampos/.anyenv/envs/rbenv/gems/2.5.0/bin
  - SPEC CACHE DIRECTORY: /Users/riocampos/.gem/specs
  - SYSTEM CONFIGURATION DIRECTORY: /Users/riocampos/.anyenv/envs/rbenv/versions/2.3.3/etc
  - RUBYGEMS PLATFORMS:
    - ruby
    - x86_64-darwin-16
  - GEM PATHS:
     - /Users/riocampos/.anyenv/envs/rbenv/gems/2.5.0
     - /Users/riocampos/.gem/ruby/2.3.0
     - /Users/riocampos/.anyenv/envs/rbenv/versions/2.3.3/lib/ruby/gems/2.3.0
 (以下略)

anyenv とかになっているのは無視してください(使ってるので)。いずれにせよ GEM PATHS が明らかにおかしい。rbenv-communal-gems をアンインストールする参考に見た
rbenv-communal-gems を使うと GEM_HOME が無視される - Qiita
を確認したところ、 ~/.gemrc に

gemhome: "/Users/riocampos/.anyenv/envs/rbenv/gems/2.5.0"

と直書きされていました。この行を削除し再度確認。

$ gem environment
RubyGems Environment:
  - RUBYGEMS VERSION: 2.5.2
  - RUBY VERSION: 2.3.3 (2016-11-21 patchlevel 222) [x86_64-darwin16]
  - INSTALLATION DIRECTORY: /Users/riocampos/.anyenv/envs/rbenv/versions/2.3.3/lib/ruby/gems/2.3.0
  - USER INSTALLATION DIRECTORY: /Users/riocampos/.gem/ruby/2.3.0
  - RUBY EXECUTABLE: /Users/riocampos/.anyenv/envs/rbenv/versions/2.3.3/bin/ruby
  - EXECUTABLE DIRECTORY: /Users/riocampos/.anyenv/envs/rbenv/versions/2.3.3/bin
  - SPEC CACHE DIRECTORY: /Users/riocampos/.gem/specs
  - SYSTEM CONFIGURATION DIRECTORY: /Users/riocampos/.anyenv/envs/rbenv/versions/2.3.3/etc
  - RUBYGEMS PLATFORMS:
    - ruby
    - x86_64-darwin-16
  - GEM PATHS:
     - /Users/riocampos/.anyenv/envs/rbenv/versions/2.3.3/lib/ruby/gems/2.3.0
     - /Users/riocampos/.gem/ruby/2.3.0
 (以下略)

これにより正常に動作するようになりました。