Windows 7 に Ruby 2.0 x64 を その5 ~EventMachine の問題と対策~
2014/5/13 追記 公式に修正が取り込まれました。gem も公開されていました。
なのでこの記事はもはや *無意味* です。
Windows 7, Ruby2.0 で guard-livereload を使おうと思い、インストールしようとしたら
EventMachine が必要といわれ、入れようとしたらビルドエラー発生。
ということで、EventMachine を修正してみました。
GitHub 上にソースをおいたので、以下のコマンドでインストールできます。
# プルリクエストしたので、そのうち取り込まれる……といいな。
2014/5/13 追記 マージされました。
# 他にも、ちょこっと直しています。
修正したソースの詳細を見たい方は、 GitHub 上のソース差分 をどうぞ。
なので、事前に配列かどうかチェックします。
やっとビルドできたと思ったら
実行時に見つからなくてエラーになっています。
というわけで libgcc_s_sjlj-1.dll と libstdc++.dll を読まないようにするため、
ビルド時のオプションに、
ソースみまくったところ、EventMachine のソケットの後処理に問題がありました。
Windows のソケットは
最初の数回だけは動いていたので、GC が悪さしてるのか?とか迷走したり。
# 実際
# なんで普通に動いちゃったのか、いまだにわからない……。
ここまできて、やっとまともに guard-livereload が動きました……。
なのでこの記事はもはや *無意味* です。
Windows 7, Ruby2.0 で guard-livereload を使おうと思い、インストールしようとしたら
EventMachine が必要といわれ、入れようとしたらビルドエラー発生。
ということで、EventMachine を修正してみました。
GitHub 上にソースをおいたので、以下のコマンドでインストールできます。
# プルリクエストしたので、そのうち取り込まれる……といいな。
2014/5/13 追記 マージされました。
gem specific_install -l 'git://github.com/u338steven/eventmachine.git'specific_install をインストールしていない方は、以下のコマンドで用意してください。
gem install specific_install# ビルドエラーを修正しただけだと、guard-livereload が変な挙動をしたので、
# 他にも、ちょこっと直しています。
修正した内容
以下 4 つのエラーに対処。- undefined method `each' for "i386-mingw32":String
- error: conflicting declaration 'typedef _pid_t pid_t'
- rubyeventmachine.so (LoadError)
- guard-livereload の妙な動き(EventMachine が原因)
修正したソースの詳細を見たい方は、 GitHub 上のソース差分 をどうぞ。
1. undefined method `each' for "i386-mingw32":String
ある変数に配列が入ったり、配列以外が入ったりしていたのが原因でした。なので、事前に配列かどうかチェックします。
if ext.cross_platform.is_a?(Array) then ext.cross_platform.each do |platform| (略) end
2. error: conflicting declaration 'typedef _pid_t pid_t'
これは、ccoenen さんのパッチをそのまま流用してます。pid_t
が重複して定義されちゃってるので、#ifndef
を使って定義済かチェックしてます。
c:\ruby\devkit\mingw\bin\../lib/gcc/x86_64-w64-mingw32/4.7.2/../../../../x86_64-w64-mingw32/include/sys/types.h:68:16: error: conflicting declaration 'typedef _pid_t pid_t' In file included from ../../../../ext/binder.cpp:20:0: ../../../../ext/project.h:97:13: error: 'pid_t' has a previous declaration as 'typedef int pid_t' In file included from ../../../../ext/project.h:151:0, from ../../../../ext/binder.cpp:20:
#ifndef _PID_T_ #define _PID_T_ typedef int pid_t; #endifここまでで、ビルドエラーの修正は終了です。
3. rubyeventmachine.so (LoadError)
次は、実行時のエラー。やっとビルドできたと思ったら
require 'eventmachine'
するだけでエラーが発生します。
Unable to load the EventMachine C extension; To use the pure-ruby reactor, require 'em/pure_ruby' C:/ruby/lib/ruby/site_ruby/2.0.0/rubygems/core_ext/kernel_require.rb:55:in `require': 126: 指定されたモジュールが見つかりません。 - C:/ruby/lib/ruby/gems/2.0.0/extensions/x64-mingw32/2.0.0/eventmachine-1.0.3/rubyeventmachine.so (LoadError) from C:/ruby/lib/ruby/site_ruby/2.0.0/rubygems/core_ext/kernel_require.rb:55:in `require' from C:/ruby/lib/ruby/gems/2.0.0/gems/eventmachine-1.0.3/lib/eventmachine.rb:8:in `rubyeventmachine.so は存在してるのですが、依存関係にある libgcc_s_sjlj-1.dll と libstdc++.dll が' from C:/ruby/lib/ruby/site_ruby/2.0.0/rubygems/core_ext/kernel_require.rb:135:in `require' from C:/ruby/lib/ruby/site_ruby/2.0.0/rubygems/core_ext/kernel_require.rb:135:in `rescue in require' from C:/ruby/lib/ruby/site_ruby/2.0.0/rubygems/core_ext/kernel_require.rb:144:in `require' from require.rb:1:in ` '
実行時に見つからなくてエラーになっています。
というわけで libgcc_s_sjlj-1.dll と libstdc++.dll を読まないようにするため、
ビルド時のオプションに、
-static-libgcc
, -static-libstdc++
を追加します。
CONFIG['LDSHAREDXX'] = "$(CXX) -shared -static-libgcc -static-libstdc++"ここまでで、EventMachine が一応使えるようになります。
4. guard-livereload の妙な動き(EventMachine が原因)
やっと EventMachine が動いて guard-livereload を使えると思ったら、 guard-livereload 起動後、最初の数回だけまともに動いて、以降リロードされないという謎現象が発生。ソースみまくったところ、EventMachine のソケットの後処理に問題がありました。
Windows のソケットは
close
じゃなく、closesocket
で閉じます。#define close closesocketこれには、なかなか気づかなくて、ものすごくハマりました。
最初の数回だけは動いていたので、GC が悪さしてるのか?とか迷走したり。
# 実際
GC.disable
すると、何故か普通に動いちゃったし。# なんで普通に動いちゃったのか、いまだにわからない……。
ここまできて、やっとまともに guard-livereload が動きました……。