続・ruby 1.9.1-p0 @ Visual C++ 2005

rubygems Hpricot はバイナリだった

ようやく rubygems が動く環境も整備できたので、息切れしつつ hpricot をインストール。テストのためにアプリを動かしてみると、msvcrt-ruby18.dll がねーよというエラーが出てくれた。どうやら、rubygems の Hpricot(mswin32) は ソースコードじゃなくてバイナリで、しかも ruby 1.8 用らしい。
仕方ないので、Hpricot の公式サイトにアクセスしてみると、Not Found。どうして・・・? ここで諦めては努力が水泡に帰してしまうので、hpricot-0.6.164.gem で検索して、強引にゲットしてきた。
早速 gem に食べさせてみると、zlib と違って今度は本当にビルドできない。なにやら RArray の ptr とか len がないとかエラーを吐いている。1.8 → 1.9 で RArray の仕様が変更されたんだろう。
gem から spec と ソースを抜いて 1.9 仕様に書き換えた。

--- data/ext/fast_xs/fast_xs.c.old	2009-01-10 12:48:01.000000000 +0900
+++ data/ext/fast_xs/fast_xs.c	2009-01-10 12:48:33.934417600 +0900
@@ -166,14 +166,14 @@
 
 	array = RARRAY(rb_rescue(unpack_utf8, self, unpack_uchar, self));
 
-	tmp = array->ptr;
-	for (i = array->len; --i >= 0; tmp++)
+  tmp = RARRAY_PTR(array);
+	for (i = RARRAY_LEN(array); --i >= 0; tmp++)
 		s_len += escaped_len(NUM2INT(*tmp));
 
 	c = s = alloca(s_len + 1);
 
-	tmp = array->ptr;
-	for (i = array->len; --i >= 0; tmp++)
+  tmp = RARRAY_PTR(array);
+	for (i = RARRAY_LEN(array); --i >= 0; tmp++)
 		c += escape(c, NUM2INT(*tmp));
 
 	*c = '\0';

これを gem にパックし直して、もう一度。

fast_xs.obj : error LNK2019: 未解決の外部シンボル '_ruby_digitmap' ...

どういうことなの・・・?試しに VC++8 IDE で _ruby_digitmap を参照するコードを書いて検証してみた。

int main() {
  extern const char ruby_digitmap[];
  printf("%d\n", ruby_digitmap[0]);
  return 0;
}

追加ライブラリに msvcr80-ruby191.lib を指定してビルドしてみると、全く同じエラーが出てきてしまった。つまり、lib ファイルがおかしいってことか・・・

mkexports.rb は使えない子?

lib ファイルを生成する元になる def ファイルを生成するのに mkexports.rb が使われているようだ。obj ファイルを入力すると、def の文字列を出力する仕組みらしい。
ruby_digitmap を定義している bignum.obj を食べさせてみると、

VERSION 1.9
EXPORTS
...
ruby_digitmap DATA

ググってみると、ruby_digitmap = _ruby_digitmap とするべきらしいのだけど、ruby_digitmap だけになっている。どおりで通らないわけだ。恐らく他のも同じ調子なんだろう。仕方ないので、手動で def ファイルを生成して自動生成物と置き換え。
再度 gem に hpricot を食わせると、エラーもなくインストールが終わってくれた。
ビルドだけでも大変だったのに、こっちも気疲れするイベントだったとは。色々試してみたいのに・・・