Ruby 1.9.1〜を構成する三つのバージョン
Ruby 1.9.1RC1の標準的な$LOAD_PATH
は以下のようになる。
/usr/local/lib/ruby/site_ruby/1.9.1 /usr/local/lib/ruby/site_ruby/1.9.1/i686-linux /usr/local/lib/ruby/site_ruby /usr/local/lib/ruby/vendor_ruby/1.9.1 /usr/local/lib/ruby/vendor_ruby/1.9.1/i686-linux /usr/local/lib/ruby/vendor_ruby /usr/local/lib/ruby/1.9.1 /usr/local/lib/ruby/1.9.1/i686-linux
ここで気になるのは末尾付近の1.9.1
である。
Ruby 1.8シリーズまではこの部分に入るのは1.8
のようにマイナーバージョン(X.Y.ZのY)までであった。これはマイナーバージョンレベルでの互換性が保たれる――か、少なくともそのようにする意志があると考えられる。ところが今回のリリースされた実装ではこの部分にフルバージョン(X.Y.Zのすべて)が埋め込まれている。となると1.9.1以降ではそのレベルで、つまりマイナーバージョンアップされるごとにすべての互換性が失われるのだろうか。
もしそうであるならばとても困ったことになる。というのは、将来リリースされるRuby 1.9.2にはバグ修正やことによってはセキュリティ修正が含まれているはずであり、通常はできるだけ早くバージョンアップすべきものとなる。ところが、前述のような事情においては互換性の点からRuby本体以外とは別にインストールしたすべてのコード(Rubyで書かれたコードとC言語などで書かれた拡張ライブラリの両方)が利用できなくなる心配があり、マイナーバージョンアップであってもおいそれとは実施できない。ついでに言えばすべてのコードが$LOAD_PATH
から外れてしまうことにもなる。
そのような危惧をもって質問したのが[ruby-dev:37748]である。
実はこのメールを送る前にIRCで意図を尋ねていたのであって、質問というよりも確認を目的とするものとなってしまっているのだが、ともあれ結論としてはそのような心配はない。
現在の実装では$LOADPATH
にRuby本体のフルバージョンが埋め込まれているのであが、それは単にコード側が間に合っていないことによるそうだ。本来の意図に従うと$LOADPATH
に含まれているのはRuby言語レベルでの互換性を表す文字列である。Ruby言語レベルでのAPIバージョンとも言える。これはRuby本体のバージョンとは別のもので、Ruby言語レベルで互換性がなくなったときに上がることが予定されている。したがって、Ruby 1.9.2がリリースされた際、互換性が保たれていれば$LOAD_PATH
には1.9.1
が含まれることになる(保たれなければ1.9.1
以外の何かになる)。
このRuby言語のAPIバージョンは、バイナリ互換性を表すものではないが、$LOAD_PATH
の中の拡張ライブラリ用のパスに対しても同様に埋め込まれている。これはRubyで書かれたライブラリから拡張ライブラリをrequire
しているものがあるためで、相互に関係し合うことを考えて一方の互換性がなくなったときには他方でも互性換がなくなったものとみなす。
バイナリ互換性についてはlibruby.so
のsonameなどによって運用されることになる。現在の実装ではマイナーバージョンまでを含んだlibruby.so.1.9
などが設定されるようになっている(コンパイラに-Wl,-soname,lib$(RUBYSONAME).so.$(MAJOR).$(MINOR)
が与えられている)が、これはおそらくRuby 1.9.1リリース時には変更されるものと予想される。
まとめるとRuby 1.9.1以降では、Ruby本体のバージョン、Ruby言語レベルでの互換性を示すバージョン、Rubyインタプリタのバイナリ互換性を示すバージョンという三つのバージョンが運用されることになる。後二者に変化があればRuby体本のバージョンは上がるが、Ruby本体のバージョンが上がっても後二者が変わらないことはありうる。なお、バイナリ互換性については1.9シリーズの中のどこかで失われる可能性があるそうだ。
ところで$LOADPATH
の中の/usr/local
の部分はconfigure
の--prefix
で指定したパスであり、/usr/local/lib
に続くruby
の部分は同じく--program-prefix
や--program-suffix
での指定を加えたRubyインタプリタ名である。たとえば--prefix=/opt --program-suffix=1.9.1rc1としたならば、
$LOADPATH
の最初のエントリは/opt/lib/ruby1.9.1rc1/site_ruby/1.9.1
となる。
このように$LOADPATH
にRubyインタプリタの名前が入ることで何か困るということは、それを知って運用している分にはあまりないと言えるかもしれない。だが、これまでたとえばRubyコマンドにバージョンを付ける形でインストールしていたというような環境では、上述の三つのバージョンの問題とは別に、マイナーバージョンアップごとに$LOADPATH
の内容が変わってしまう問題が生じることになる。しかもこの部分の文字列を指定する方法は提供されておらず、これを回避するにはソースコードに手を加えるしかない。
それではいくらか不便であるためconfigure
で指定できるようにしてはどうかと提供してみたのが[ruby-dev:37749]である。実際にはRubyライブラリと拡張ライブラリのそれぞれの場所を個別に指定できるようにしているつもりで、/usr/share
と/usr/lib
の使いわけを意識したものでもある。とはいうものの、アーキテクチャ依存のRubyコードを、アーキテクチャ用のパス(/usr/local/lib/ruby/i686-linux
など)に配置するといった認識が一般にあるとは思えないので(mkmf.rb
にも対応はないと思う)、その入口くらいにしかならないかもしれない。