久し振り(?)に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:リンクが無くて申し訳ないです。すごい大量のタブをブラウザで開いていて何を見てたのかの管理をきちんとできてませんでした。よくないことですね。以後気を付けます。