MongrelはRuby 1.9と互換性が無い

#25 (mongrel not compatible with Ruby 1.9) - Mongrel - Trac

がーん。

Note that currently gem install mongrel under 1.9 doesn't work [and it shouldn't] but it fails because it requires fastthread, and fastthread doesn't compile under 1.9 [at least not the gem version]. Thanks for your help in this.

しかし、fastthreadに依存しているのが問題であり、それを外せば良いようにも見える。

こんなやりとりも。
mongrel and fastthread on ruby 1.9 - Ruby Forum

どちらにしろランタイムの関係で現在のWindows用バイナリはRuby1.9では動かないので、今回はmongrelをビルドしてみよう。

1. gemをインストール
取り敢えず最新のgemをインストールしてみる。何度も書いているが私の環境はいわゆる"DMZ"にあるので、リモートのgemを取得できない。(gemはプロキシには対応しているのだが、RubyはNTLM Windowsドメイン認証をサポートしておらず、認証フェーズで失敗する HTTP STATUS=407) なので、rubyforgeからgemをHTTPでダウンロードしてインストールする。

http://rubyforge.org/frs/download.php/37325/mongrel-1.1.5-x86-mswin32-60.gem
パッケージをrubyのルートにコピーしてgemコマンド実行

gem install mongrel --local

インストール自体は問題無く終了するが、ビルドの環境が違うのでこのままでは動かない。


2. 拡張ライブラリィ(http11)をコンパイル
mongrelの拡張ライブラリィのディレクトリ(ext\)に移動して、extconf.rbを実行してMakeFileを生成する

cd E:\ruby1.9.2\lib\ruby\gems\1.9.1\gems\mongrel-1.1.5-x86-mswin32-60\ext\http11
>ruby extconf.rb
checking for main() in c.lib... no
creating Makefile

>nmake

Microsoft(R) Program Maintenance Utility Version 8.00.50727.762
Copyright (C) Microsoft Corporation.  All rights reserved.

        e:\ruby\bin\ruby -e "puts 'EXPORTS', 'Init_http11'"  > http11-i386-mswin32_80.def
        cl -nologo -I. -Ie:/ruby/include/ruby-1.9.1/i386-mswin32_80 -Ie:/ruby/include/ruby-1.9.1/ruby/backward -Ie:/ruby/include/ruby-1.9.1 -I. -MD -Zi  -O2b2xty-  -Zm600 -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE -Fohttp11.obj -c -Tchttp11.c
http11.c
http11.c(77) : error C2039: 'ptr' : 'RString' のメンバではありません。
        e:\ruby\include\ruby-1.9.1\ruby/ruby.h(602) : 'RString' の宣言を確認してください。
http11.c(77) : error C2039: 'len' : 'RString' のメンバではありません。
        e:\ruby\include\ruby-1.9.1\ruby/ruby.h(602) : 'RString' の宣言を確認してください。
http11.c(172) : error C2039: 'ptr' : 'RString' のメンバではありません。
        e:\ruby\include\ruby-1.9.1\ruby/ruby.h(602) : 'RString' の宣言を確認してください。
http11.c(172) : warning C4047: '関数' : 間接参照のレベルが 'const char *' と 'int' で異なっています。
http11.c(172) : warning C4024: 'strchr' : の型が 1 の仮引数および実引数と異なります。
http11.c(172) : error C2198: 'strchr' : 呼び出しに対する引数が少なすぎます。
http11.c(174) : error C2039: 'ptr' : 'RString' のメンバではありません。
        e:\ruby\include\ruby-1.9.1\ruby/ruby.h(602) : 'RString' の宣言を確認してください。
http11.c(174) : error C2198: 'rb_str_substr' : 呼び出しに対する引数が少なすぎます。
http11.c(176) : error C2039: 'ptr' : 'RString' のメンバではありません。
        e:\ruby\include\ruby-1.9.1\ruby/ruby.h(602) : 'RString' の宣言を確認してください。
http11.c(177) : error C2039: 'len' : 'RString' のメンバではありません。
        e:\ruby\include\ruby-1.9.1\ruby/ruby.h(602) : 'RString' の宣言を確認してください。
http11.c(177) : error C2198: 'rb_str_substr' : 呼び出しに対する引数が少なすぎます。
http11.c(298) : error C2039: 'ptr' : 'RString' のメンバではありません。
        e:\ruby\include\ruby-1.9.1\ruby/ruby.h(602) : 'RString' の宣言を確認してください。
http11.c(299) : error C2039: 'len' : 'RString' のメンバではありません。
        e:\ruby\include\ruby-1.9.1\ruby/ruby.h(602) : 'RString' の宣言を確認してください。
NMAKE : fatal error U1077: '"D:\Program Files\Microsoft Visual Studio 8\VC\BIN\cl.EXE"' : リターン コード '0x2'
Stop.

RStringの宣言でばしばしエラーが出る。
これに関してはパッチが出ているので、まずはそれを当てる。(rakeの差分は無視した)

Index: Rakefile
===================================================================
--- Rakefile	(revision 888)
+++ Rakefile	(working copy)
@@ -1,4 +1,4 @@
-
+PLATFORM = RUBY_PLATFORM if !defined?(PLATFORM)
 require 'rubygems'
 gem 'echoe', '>=2.7'
 require 'echoe'
Index: ext/http11/http11.c
===================================================================
--- ext/http11/http11.c	(revision 888)
+++ ext/http11/http11.c	(working copy)
@@ -74,7 +74,7 @@
   f = rb_str_dup(global_http_prefix);
   f = rb_str_buf_cat(f, field, flen); 
 
-  for(ch = RSTRING(f)->ptr, end = ch + RSTRING(f)->len; ch < end; ch++) {
+  for(ch = RSTRING_PTR(f), end = ch + RSTRING_LEN(f); ch < end; ch++) {
     if(*ch == '-') {
       *ch = '_';
     } else {
@@ -169,12 +169,12 @@
   rb_hash_aset(req, global_gateway_interface, global_gateway_interface_value);
   if((temp = rb_hash_aref(req, global_http_host)) != Qnil) {
     /* ruby better close strings off with a '\0' dammit */
-    colon = strchr(RSTRING(temp)->ptr, ':');
+    colon = strchr(RSTRING_PTR(temp), ':');
     if(colon != NULL) {
-      rb_hash_aset(req, global_server_name, rb_str_substr(temp, 0, colon - RSTRING(temp)->ptr));
+      rb_hash_aset(req, global_server_name, rb_str_substr(temp, 0, colon - RSTRING_PTR(temp)));
       rb_hash_aset(req, global_server_port, 
-          rb_str_substr(temp, colon - RSTRING(temp)->ptr+1, 
-            RSTRING(temp)->len));
+          rb_str_substr(temp, colon - RSTRING_PTR(temp)+1, 
+            RSTRING_LEN(temp)));
     } else {
       rb_hash_aset(req, global_server_name, temp);
       rb_hash_aset(req, global_server_port, global_port_80);
@@ -295,8 +295,8 @@
   DATA_GET(self, http_parser, http);
 
   from = FIX2INT(start);
-  dptr = RSTRING(data)->ptr;
-  dlen = RSTRING(data)->len;
+  dptr = RSTRING_PTR(data);
+  dlen = RSTRING_LEN(data);
 
   if(from >= dlen) {
     rb_raise(eHttpParserError, "Requested start is after data buffer end.");
Index: ext/http11/ext_help.h
===================================================================
--- ext/http11/ext_help.h	(revision 888)
+++ ext/http11/ext_help.h	(working copy)
@@ -11,4 +11,13 @@
 #define TRACE() 
 #endif
 
+/* ruby 1.9 compat */
+#ifndef RSTRING_PTR
+#define RSTRING_PTR(str) RSTRING(str)->ptr
+#endif
+
+#ifndef RSTRING_LEN
+#define RSTRING_LEN(str) RSTRING(str)->len
+#endif
+
 #endif


再びコンパイル、インストール

>e:
>cd E:\ruby1.9.2\lib\ruby\gems\1.9.1\gems\mongrel-1.1.5-x86-mswin32-60\ext\http11
>"%VS80COMNTOOLS%vsvars32.bat"
Setting environment for using Microsoft Visual Studio 2005 x86 tools.

>ruby extconf.rb
checking for main() in c.lib... no
creating Makefile

>nmake

Microsoft(R) Program Maintenance Utility Version 8.00.50727.762
Copyright (C) Microsoft Corporation.  All rights reserved.
:
略
   ライブラリ http11-i386-mswin32_80.lib とオブジェクト http11-i386-mswin32_80.exp を作成中
        mt -nologo -manifest http11.so.manifest -outputresource:http11.so;2

>nmake install
:
略
install -c -p -m 0755 http11.so e:\ruby\lib\ruby\site_ruby\1.9.1\i386-msvcr80

オーケー。コンパイルとインストールは出来た。パッチは正しそうだが、実行してみよう。

3. 動作確認

>ruby script/server --prefix=/addressbook
=> Booting Mongrel (use 'script/server webrick' to force WEBrick)
=> Rails 2.2.2 application starting on http://0.0.0.0:3000
=> Call with -d to detach
=> Ctrl-C to shutdown server
e:/ruby/lib/ruby/gems/1.9.1/gems/mongrel-1.1.5-x86-mswin32-60/lib/mongrel/handlers.rb:214: warning: else without rescue is uselessExiting
E:/www/addressbook/vendor/rails/activesupport/lib/active_support/dependencies.rb:153:in `require': e:/ruby/lib/ruby/gems/1.9.1/gems/mongrel-1.1.5-x86-mswin32-60/lib/mongrel/handlers.rb:208: syntax error, unexpected ':', expecting keyword_then or ',' or ';'
 or '\n' (SyntaxError)
...te(modified_since) rescue nil : false
...                               ^
e:/ruby/lib/ruby/gems/1.9.1/gems/mongrel-1.1.5-x86-mswin32-60/lib/mongrel/handlers.rb:209: syntax error, unexpected ':', expecting keyword_end
...                              : false
...                               ^
e:/ruby/lib/ruby/gems/1.9.1/gems/mongrel-1.1.5-x86-mswin32-60/lib/mongrel/handlers.rb:210: syntax error, unexpected ':', expecting keyword_end
...                              : false
...                               ^
e:/ruby/lib/ruby/gems/1.9.1/gems/mongrel-1.1.5-x86-mswin32-60/lib/mongrel/handlers.rb:211: syntax error, unexpected ':', expecting keyword_end
...                              : false
...                               ^
e:/ruby/lib/ruby/gems/1.9.1/gems/mongrel-1.1.5-x86-mswin32-60/lib/mongrel/handlers.rb:212: syntax error, unexpected ':', expecting keyword_end
...).include?(etag)              : false
...                               ^
e:/ruby/lib/ruby/gems/1.9.1/gems/mongrel-1.1.5-x86-mswin32-60/lib/mongrel/handlers.rb:468: syntax error, unexpected keyword_end, expecting $end
:
略

う゛えー、シンタクスエラーがなんで今更。と、ここでmongrel本家のトラック-チケットを思い出した。

add_thens.diff (1.7 kB) - added by rogerdpack on 09/06/08 11:48:20.
このパッチはこの問題のFIX用だろう。

Index: lib/mongrel/handlers.rb
===================================================================
--- lib/mongrel/handlers.rb	(revision 1036)
+++ lib/mongrel/handlers.rb	(working copy)
@@ -205,11 +205,11 @@
       # test to see if this is a conditional request, and test if
       # the response would be identical to the last response
       same_response = case
-                      when modified_since && !last_response_time = Time.httpdate(modified_since) rescue nil : false
-                      when modified_since && last_response_time > Time.now                                  : false
-                      when modified_since && mtime > last_response_time                                     : false
-                      when none_match     && none_match == '*'                                              : false
-                      when none_match     && !none_match.strip.split(/\s*,\s*/).include?(etag)              : false
+                      when modified_since && !last_response_time = Time.httpdate(modified_since) rescue nil then false
+                      when modified_since && last_response_time > Time.now                                  then false
+                      when modified_since && mtime > last_response_time                                     then false
+                      when none_match     && none_match == '*'                                              then false
+                      when none_match     && !none_match.strip.split(/\s*,\s*/).include?(etag)              then false
                       else modified_since || none_match  # validation successful if we get this far and at least one of the header exists
                       end
 

パッチをあてて再度実行してみよう。

/vendor/rails/railties/lib/initializer.rb:259:in `rescue in require_frameworks': no such file to load -- openssl (RuntimeError)
:
略

opensslが必要なんだな。これはzlibと同様に組み込んでやればOK。大分慣れてきたぞ。
以前のエントリでzlibを組み込んだ時と同様に、extconf.rbを実行してMakeFileを作成し、nmakeで拡張ライブラリィをコンパイル、インストールする。

install -c -p -m 0755 openssl.so e:\ruby\lib\ruby\site_ruby\1.9.1\i386-msvcr80
install -c -p -m 0644 ./lib/openssl/bn.rb e:/ruby/lib/ruby/site_ruby/1.9.1/openssl
install -c -p -m 0644 ./lib/openssl/buffering.rb e:/ruby/lib/ruby/site_ruby/1.9.1/openssl
install -c -p -m 0644 ./lib/openssl/cipher.rb e:/ruby/lib/ruby/site_ruby/1.9.1/openssl
install -c -p -m 0644 ./lib/openssl/digest.rb e:/ruby/lib/ruby/site_ruby/1.9.1/openssl
install -c -p -m 0644 ./lib/openssl/ssl-internal.rb e:/ruby/lib/ruby/site_ruby/1.9.1/openssl
install -c -p -m 0644 ./lib/openssl/ssl.rb e:/ruby/lib/ruby/site_ruby/1.9.1/openssl
install -c -p -m 0644 ./lib/openssl/x509-internal.rb e:/ruby/lib/ruby/site_ruby/1.9.1/openssl
install -c -p -m 0644 ./lib/openssl/x509.rb e:/ruby/lib/ruby/site_ruby/1.9.1/openssl
install -c -p -m 0644 ./lib/openssl.rb e:/ruby/lib/ruby/site_ruby/1.9.1

今度こそ上手く動くだろう。

e:
cd E:\www\addressbook
>ruby script/server --prefix=/addressbook
=> Booting Mongrel (use 'script/server webrick' to force WEBrick)
=> Rails 2.2.2 application starting on http://0.0.0.0:3000
=> Call with -d to detach
=> Ctrl-C to shutdown server
** Starting Mongrel listening at 0.0.0.0:3000
** Starting Rails with development environment...
** Mounting Rails at /addressbook...
e:/ruby/lib/ruby/gems/1.9.1/gems/activerecord-oracle_enhanced-adapter-1.1.9/lib/active_record/connection_adapters/oracle_enhancd_adapter.rb:940:in `<class:Cursor>': undefined method `define_a_column' for class `OCI8::Cursor' (NameError)
        from e:/ruby/lib/ruby/gems/1.9.1/gems/activerecord-oracle_enhanced-adapter-1.1.9/lib/active_record/connection_adapters/racle_enhanced_adapter.rb:939:in `<class:OCI8>'
        from e:/ruby/lib/ruby/gems/1.9.1/gems/activerecord-oracle_enhanced-adapter-1.1.9/lib/active_record/connection_adapters/racle_enhanced_adapter.rb:935:in `<top (required)>'
        :
        :略
        :
        from E:/www/addressbook/vendor/rails/activesupport/lib/active_support/dependencies.rb:153:in `require'
        :
        :
        :略
        :

.... 動いたが今度はOCI8でエラー。まあ、ruby-oci8_2.0はunstableとのことだし、ray_apps_blogを見ても、oracle_enhanced_adapterがruby1.9及びruby-oci8_2.0に対応した様子も無いので動かなくても仕方が無いし、散々苦労したMongrelだけでも動いて良かったと思おう。

仕事で使うRuby1.9環境はあと少しの辛抱といった所か。

それにしても、rubyforgeのソースが軒並み古いのが気に掛かる。パッチも分散しているし、Mongrelは現在きちんとメンテされているんだろうかと余計な心配をしてしまった。