職業プログラマの休日出勤

職業プログラマによる日曜自宅プログラミングや思考実験の成果たち。リアル休日出勤が発生すると更新が滞りがちになる。記事の内容は個人の意見であり、所属している(いた)組織の意見ではない。

rb_wait_for_single_fd が無い?

久し振り(?)にRailsな開発環境をローカルに作ろうとしたところ、エラーで苦しんだのでメモです。
コマンド rails new {アプリ名} -d mysql を動かしたところ、エラーになりました。

An error occurred while installing mysql2 (0.5.3), and Bundler cannot continue.
Make sure that `gem install mysql2 -v '0.5.3' --source 'https://rubygems.org/'` succeeds before bundling.

まぁ、よくあるやつですね。よくある原因はOpenSSLとのリンクが上手くできてないっていうものだと思いますが、今回のはそうではありませんでした。
エラーメッセージの別の部分には、以下のようなものがありました。

To see why this extension failed to compile, please check the mkmf.log which can be found here:

  /Users/{わたし}/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/extensions/x86_64-darwin-20/2.7.0/mysql2-0.5.3/mkmf.log

まぁ、ログ見ろよって話なのでログの中身を見ると、こんな感じでした。

have_func: checking for rb_wait_for_single_fd()... -------------------- yes

"clang -o conftest (オプション等を省略)"
conftest.c:14:57: error: use of undeclared identifier 'rb_wait_for_single_fd'
int t(void) { void ((*volatile p)()); p = (void ((*)()))rb_wait_for_single_fd; return !p; }
                                                        ^
1 error generated.
checked program was:
/* begin */
 1: #include "ruby.h"
 2: 
 3: /*top*/
 4: extern int t(void);
 5: int main(int argc, char **argv)
 6: {
 7:   if (argc > 1000000) {
 8:     int (* volatile tp)(void)=(int (*)(void))&t;
 9:     printf("%d", (*tp)());
10:   }
11: 
12:   return !!argv[argc];
13: }
14: int t(void) { void ((*volatile p)()); p = (void ((*)()))rb_wait_for_single_fd; return !p; }
/* end */

どうやら rb_wait_for_single_fd という関数を見つけられないように見えます。これってrubyのビルドに失敗しているのでは?と推測する人が多いと思いますし筆者もそうでした。そう思ってruby自体を再ビルド(rbenv経由で)したりしましたが、結果は同じでした。エラーメッセージでググってもOpenSSL方面の問題でビルド失敗してる人の話ばっかり出てきます*1

この関数名での検索をやめて色々見ていたところ、rubyのmysql2の native extension は、当該環境にインストールされているMySQLを見に行く、的な話を見かけました*2。もしや?と思って brew install mysql すると、無事に native extension が入りました。そんな落とし穴があるとは知らなかったです。rbenvやnodenvといったツールで管理されないものは可能な限りDockerの中で動かす、というのが筆者のローカル開発環境のポリシーなので、手元のMacには直接にはMySQLは入っていなかったのです(むかしちょっとRails触ってたときは入ってた)。もちろん、mysql2のgemのインストール後の開発はDockerの中で動かすMySQLで進めています。

環境情報

*1:https://qiita.com/fukuda_fu/items/463a39406ce713396403 あ、この記事は良い記事ですよ。

*2:リンクが無くて申し訳ないです。すごい大量のタブをブラウザで開いていて何を見てたのかの管理をきちんとできてませんでした。よくないことですね。以後気を付けます。