M1 Mac での mysql2 インストールエラーの解決例

Rails で MySQL を使うときの Bundle install における定番のエラー。 mysql2 がインストールできない問題。

M1 Mac 環境における解決方法のメモ。過去、Intel環境でも発生していた問題ですが、従来うまくいっていた bundle config だけでは不足していたので再調査しました。

開発環境は人によって条件が異なりますので、必ずしも他のケースで当てはまるとは限りません。イチ解決策のケースとして参照してください。

結論

今回の自分のケースではこれで動きました。(macOS Monterey - version 12.0.1)

# 最終的にこれが通った
bundle config --local build.mysql2 --with-ldflags=-L/opt/homebrew/lib --with-opt-dir="$(brew --prefix openssl@1.1)"

# /opt/homebrew/opt/openssl@1.1 が解決される

コンフィグは以下の通り

more .bundle/config
---
BUNDLE_PATH: "vendor/bundle"
BUNDLE_BUILD__MYSQL2: "--with-ldflags=-L/opt/homebrew/lib --with-opt-dir=/opt/homebrew/opt/openssl@1.1"

前提として以下の通りセットアップが必要

brew install openssl@1.1
# brew info openssl@1.1
# openssl@1.1: stable 1.1.1l (bottled) [keg-only]
# Cryptography and SSL/TLS Toolkit

brew install mysql
# brew info mysql
# mysql: stable 8.0.27 (bottled)
# Open source relational database management system

brew install zstd
# brew info zstd
# zstd: stable 1.5.0 (bottled), HEAD
# Zstandard is a real-time compression algorithm

MySQLエラーの切り分け

試したこと

  • mysql-client だけで澄まないか →NG
    • MySQL サーバーそのものは、最近は Docker で済ませることが多いため、macOSネイティブ環境を汚したくなかったからシンプルにできないかを施行した意図
  • bundle config --local build.mysql2 "--with-ldflags=-L$(brew --prefix openssl@1.1)/lib --with-cppflags=-I$(brew --prefix openssl@1.1)/include" →NG
  • bundle config --local build.mysql2 --with-ldflags=-L/opt/homebrew/lib --with-opt-dir=/opt/homebrew/opt/openssl →NG
Gem::Ext::BuildError: ERROR: Failed to build gem native extension.

    current directory: /Users/your_name/your_project/vendor/bundle/ruby/2.7.0/gems/mysql2-0.5.3/ext/mysql2
/Users/your_name/.rbenv/versions/2.7.3/bin/ruby -I /Users/your_name/.rbenv/versions/2.7.3/lib/ruby/2.7.0 -r ./siteconf20211030-19299-mmi7si.rb extconf.rb
--with-ldflags\\=-L/usr/local/opt/openssl/lib --with-cppflags\\=-I/usr/local/opt/openssl/include
checking for rb_absint_size()... yes
checking for rb_absint_singlebit_p()... yes
checking for rb_wait_for_single_fd()... yes
*** extconf.rb failed ***
Could not create Makefile due to some reason, probably lack of necessary
libraries and/or headers.  Check the mkmf.log file for more details.  You may
need configuration options.

Provided configuration options:
	--with-opt-dir
	--without-opt-dir
	--with-opt-include
	--without-opt-include=${opt-dir}/include
	--with-opt-lib
	--without-opt-lib=${opt-dir}/lib
	--with-make-prog
	--without-make-prog
	--srcdir=.
	--curdir
	--ruby=/Users/your_name/.rbenv/versions/2.7.3/bin/$(RUBY_BASE_NAME)
	--with-mysql-dir
	--without-mysql-dir
	--with-mysql-include
	--without-mysql-include=${mysql-dir}/include
	--with-mysql-lib
	--without-mysql-lib=${mysql-dir}/lib
	--with-mysql-config
	--without-mysql-config
	--with-mysqlclient-dir
	--without-mysqlclient-dir
	--with-mysqlclient-include
	--without-mysqlclient-include=${mysqlclient-dir}/include
	--with-mysqlclient-lib
	--without-mysqlclient-lib=${mysqlclient-dir}/lib
	--with-mysqlclientlib
	--without-mysqlclientlib
/Users/your_name/.rbenv/versions/2.7.3/lib/ruby/2.7.0/mkmf.rb:1050:in `block in find_library': undefined method `split' for nil:NilClass (NoMethodError)
	from /Users/your_name/.rbenv/versions/2.7.3/lib/ruby/2.7.0/mkmf.rb:1050:in `collect'
	from /Users/your_name/.rbenv/versions/2.7.3/lib/ruby/2.7.0/mkmf.rb:1050:in `find_library'
	from extconf.rb:87:in `<main>'

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

  /Users/your_name/your_project/vendor/bundle/ruby/2.7.0/extensions/arm64-darwin-21/2.7.0/mysql2-0.5.3/mkmf.log

extconf failed, exit code 1

Gem files will remain installed in /Users/your_name/your_project/vendor/bundle/ruby/2.7.0/gems/mysql2-0.5.3 for inspection.
Results logged to /Users/your_name/your_project/vendor/bundle/ruby/2.7.0/extensions/arm64-darwin-21/2.7.0/mysql2-0.5.3/gem_make.out

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.

In Gemfile:
  mysql2

ld: library not found for -lzstd

checking for SERVER_QUERY_WAS_SLOW in mysql.h... yes
checking for MYSQL_OPTION_MULTI_STATEMENTS_ON in mysql.h... yes
checking for MYSQL_OPTION_MULTI_STATEMENTS_OFF in mysql.h... yes
checking for my_bool in mysql.h... no
-----
Don't know how to set rpath on your system, if MySQL libraries are not in path mysql2 may not load
-----
-----
Setting libpath to /opt/homebrew/Cellar/mysql/8.0.27/lib
-----
creating Makefile

current directory: /Users/yourname/ghq/src/github.com/dobassy/Ragme/vendor/bundle/ruby/2.7.0/gems/mysql2-0.5.3/ext/mysql2
make "DESTDIR=" clean

current directory: /Users/yourname/ghq/src/github.com/dobassy/Ragme/vendor/bundle/ruby/2.7.0/gems/mysql2-0.5.3/ext/mysql2
make "DESTDIR="
compiling client.c

....中略

34 warnings generated.
linking shared-object mysql2/mysql2.bundle
ld: library not found for -lzstd
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [mysql2.bundle] Error 1

make failed, exit code 2

$ brew install zstd
Warning: zstd 1.5.0 is already installed and up-to-date.
To reinstall 1.5.0, run:
  brew reinstall zstd

参考情報 mysql - ld: library not found for -lzstd while bundle install for mysql2 gem Ruby on macOS Big Sur 11.4 - Stack Overflow