HOME  >  Ruby >  Windows 7 に Ruby 2.0 x64 を その5 ~EventMachine の問題と対策~

Windows 7 に Ruby 2.0 x64 を その5 ~EventMachine の問題と対策~

2014/5/13 追記 公式に修正が取り込まれました。gem も公開されていました。
なのでこの記事はもはや *無意味* です。

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 つのエラーに対処。
  1. undefined method `each' for "i386-mingw32":String
  2. error: conflicting declaration 'typedef _pid_t pid_t'
  3. rubyeventmachine.so (LoadError)
  4. 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 `'
        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 `
'
rubyeventmachine.so は存在してるのですが、依存関係にある libgcc_s_sjlj-1.dll と libstdc++.dll が
実行時に見つからなくてエラーになっています。

というわけで 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 が動きました……。
2014/02/22 | カテゴリ:Ruby | トラックバック(1) | コメント(0)
コメントの投稿












管理者にだけ表示を許可する
トラックバック
この記事のトラックバックURL
http://uisteven.blog.fc2.com/tb.php/49-ab41e9b6

-
管理人の承認後に表示されます
[2016/12/05 09:38]
外部リンク

カンパのお願い
公開しているソフトウェアはフリーウェアなので無料でご利用いただけます。 気に入ってくださった方は、Amazon でお買い物をする際に下記のリンクを経由して頂ければ励みになります。

検索BOX・タグ一覧
サイト内検索

全記事一覧,全タグ一覧へ