【Ruby】OS XでDigest::MD5を使おうとすると「Symbol not found: _rb_Digest_MD5_Finish (LoadError)」なるエラーが出る問題
週末に久々に会った友人から「お前アナログゲーム以外のこともブログに書けよ」って言われたので、メモ代わりに最近が自分が嵌った落とし穴について。
YosemiteでRuby 2.2を入れたところ、MD5を扱う標準ライブラリのDigest::MD5
が使えなくて困った。
発生した問題
例えばこんな感じでRubyをインストールする。
$ rbenv install 2.2.1 # rbenvでCRuby 2.2.1をインストール $ rbenv local 2.2.1 # 現在のディレクトリで2.2.1を使用
で、digest/md5
をrequire
すると……
$ ruby -e 'require "digest/md5"' /Users/autopp/.rbenv/versions/2.2.1/lib/ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:in `require': dlopen(/Users/autopp/.rbenv/versions/2.2.1/lib/ruby/2.2.0/x86_64-darwin14/digest/md5.bundle, 9): Symbol not found: _rb_Digest_MD5_Finish (LoadError) Referenced from: /Users/autopp/.rbenv/versions/2.2.1/lib/ruby/2.2.0/x86_64-darwin14/digest/md5.bundle Expected in: flat namespace in /Users/autopp/.rbenv/versions/2.2.1/lib/ruby/2.2.0/x86_64-darwin14/digest/md5.bundle - /Users/autopp/.rbenv/versions/2.2.1/lib/ruby/2.2.0/x86_64-darwin14/digest/md5.bundle from /Users/autopp/.rbenv/versions/2.2.1/lib/ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:in `require' from -e:1:in `<main>'
あまり目にしない例外を吐いて死ぬ。
ここではrbenv
を使っているが、恐らく他のツールや野良ビルドでも発生する。
またRubyのバージョンは2.1でも発生することを確認している。
Digest::MD5
はまあ色んな所で使われていて、例えばbundler/setup
なんかも使えなくなってしまうため、これは無視できない問題である。
解決策
先ほどのエラーログではCのdlopen
のエラー出力らしきものが含まれていることから「たぶんRuby自体のインストールに問題があったんだろうな」というところまでは検討が付くが、思い当たる節は特に無い。
ひたすらクエスチョンマークを頭から垂れ流しながらググっていてたら、次のstackoverflowの質問に行き着いた。
Mountain Lion - Rails - Symbol not found: _rb_Digest_MD5_Finish (LoadError)
これのアンサーによると、Mac OSでRubyをインストールする時に環境変数C_INCLUDE_PATH
が設定されているとマズイらしい。
なんじゃそりゃと思うような、まあそんなこともあるかと思うような……
手元の環境で確認してみると確かに定義されている。
$ if [[ $C_INCLUDE_PATH ]]; then echo yes; fi yes
Rubyのインストール時にこの環境変数がセットされてさえいなければいいらしいので、以下の手順で再インストールすればよい。
$ rbenv uninstall 2.2.1 # 一度アンインストールして $ unset C_INCLUDE_PATH # 環境変数を一時的に削除して $ rbenv install 2.2.1 # 再インストール
改めてdigest/md5
をrequire
してみる。
$ rbenv local 2.2.1 $ ruby -e 'require "digest/md5"; puts "OK"' OK
OK。
この問題、踏むと致命的なわりにはあまり情報が出てこなかった。
そもそもC_INCLUDE_PATH
は普通はセットしないので、踏んだ人も少ないのだろうと推測(gcc
やclang
なら-I
オプションで十分なはず)。
正直なところ自分もいつC_INCLUDE_PATH
なんかを設定したのか覚えが無いが、たぶん昔何かの都合で.bashrc
に書いたのがずっと残っていたのだろう。
なんにせよアナログゲーム以外の記事も書いたので、友人(非エンジニア)の不満も解消できただろう。 これで次はアナログゲームの記事が書ける。