めらんこーど地階 RSSフィード

2009-01-10

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

| 12:41 | 続・ruby 1.9.1-p0 @ Visual C++ 2005 を含むブックマーク 続・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 を食わせると、エラーもなくインストールが終わってくれた。

ビルドだけでも大変だったのに、こっちも気疲れするイベントだったとは。色々試してみたいのに・・・

ruby 1.9.1-p0 @ Visual C++ 2005

| 11:58 | ruby 1.9.1-p0 @ Visual C++ 2005 を含むブックマーク ruby 1.9.1-p0 @ Visual C++ 2005 のブックマークコメント

12月31日、Ruby 1.9系統初の安定版となるRuby 1.9.1のリリース候補版が公開された。Ruby公式サイトダウンロードURLが掲載されている。

Ruby 1.9.1 リリース候補版公開:CodeZine(コードジン)

年明け以降公式サイトを訪問してなかったので、全く気付かなかった。安定版としての 1.9.1 のリリースは今月下旬以降になりそうかな?

とりあえず試してみようかと思ったけど、ruby 1.8で、外部からパッケージを持ってきたり、rubygem install するたびに、Visual C++ 6.0 の CD を入れて環境設定するのが面倒くさかったので、今開発環境にしている Visual C++ 2005 でソースコードからビルドすることにした。

公式サイトから 1.9.1 RC の tar ball をダウンロードして展開、ruby-1.9.1-rc1/win32/ に入り、README.win32 を開いて手順を確認。それほど難しくなさそうだ、けど・・・

1.開発環境の環境変数設定

方法としては例の環境変数設定バッチファイルを叩くか、VC++コンソールを開くか、自分で設定するか、の三通りあるけど、今回はバッチファイルを叩いた。

>"\Program Files\Microsoft Visual Studio 8\vc\vcvarsall.bat"
Setting environment for using Microsoft Visual Studio 2005 x86 tools.

後々で気付いたけど、ここで手順に書いてない罠があった。zlib のヘッダ、ライブラリがあるディレクトリをそれぞれ INCLUDE, LIB 環境変数に通しておかないと、zlib モジュールインストールされずに、rubygems が拗ねてしまう。デフォルト環境変数設定では、zlib は存在しないので、この罠にはまってしまった。手順書だけでなくトップの README にも書いてないし・・・

>SET INCLUDE=c:\lib\zlib\include;%INCLUDE%
>SET LIB=c:\lib\zlib\lib;%LIB%

SVN リポジトリから取ってきた場合は、他に bison, sed が必要になるらしいけど、ftp から落としてきた物なので、必要なさそうかな。

2.configure

Windows ならでは、ってことでバッチファイル版の configure.bat が用意されている。

D:\ruby 下にインストールしたいので、パラメータにパスを指定して configure。

>configure --prefix=D:\ruby
...

configure 出来たら、Makefile を開いて名前を変えたり出来るよ、と手順にあるけど、デフォルトの名前で十分なので、それはしなかった。

3.make, test, install

ここまで来れば、あとは無事通ってくれることを祈るのみ。Visual C++ では make じゃなくて nmake。

>nmake
...
>nmake test
...
>nmake install
...

なんとか、無事に通ってくれたけど、この先何かが起きようとは誰も知る由もなかった・・・

rubygems が動かない?

hpricot は標準で入っていないので rubygems で入れる必要があった。ということで、rubygems で入れようとすると、なんか zlib ねーよっていうエラーが。これが 2. で言った罠で、しっかり引っかかってしまった。ひどいよね。

仕方ないので後付で zlib をビルドしに行った。ruby-1.9.1-rc1/ext/zlib に入り、extconf.rb で Makefile を生成して、nmake。

>nmake
...
zlib.c
指定されたパスが見つかりません。
...
        mt -nologo -manifest zlib.so.manifest -outputresource:zlib.so;2
指定されたパスが見つかりません。
...

とりあえず生成は出来ているみたいだけど、なんかおかしいエラーが・・・?

rbconfig が変だ?

nmake は /N オプションで実行コマンドリストが見られるので、出してみると

>nmake /N
...
        C:\WINDOWS\system32\cmd.exe /C \win32\rm.bat zlib.so
...
        C:\WINDOWS\system32\cmd.exe /C \win32\rm.bat zlib.so.manifest

わけがわからない。Makefile を見てみると、

RM = $(COMSPEC) /C $(top_srcdir:/=\)\win32\rm.bat

これが原因らしい。top_srcdir が設定されてないので、そんなバッチファイルはないと転けているわけか。RM の出所はどこだろう・・・? Makefile を生成する extconf.rb によると、mkmf モジュールが関わっているらしい。

mkmf モジュールの本体は \lib\ruby\1.9.1\mkmf.rb。覗いてgrepしてみると、あったあった。

RM = #{config_string('RM') || '$(RUBY) -run -e rm -- -f'}

つまり、config_string('RM') がそんな感じに設定されているということかな。

config_string は何かというと、ただの関数で 72 行目に定義が書いてあった。

def config_string(key, config = CONFIG)
  s = config[key] and !s.empty? and block_given? ? yield(s) : s
end

CONFIG 配列から文字列を引く関数らしい。CONFIG の定義は8行目。

CONFIG = RbConfig::MAKEFILE_CONFIG

RbConfig にその定義を羅列した配列があるようだ。RbConfig は \lib\ruby\1.9.1\i386-mswin32_80(ビルド環境依存?) の rbconfig.rb がその本体。覗いて検索すると・・・

  CONFIG["CP"] = "copy > nul"
  CONFIG["RM"] = "$(COMSPEC) /C $(top_srcdir:/=\)\win32\rm.bat"
  CONFIG["ALLOCA"] = ""

これはひどい。抹消したい気持ちを抑えて、当該行だけデリートしておいた。

再度ビルドし直してみると、エラーもなく完了。すっきり。

試してみる

ビルドだけで体力を使い果たしたので、hpricotのインストールや新機能のお試しは後にしよう・・・