The other day I was installing mysql2 gem on macOS for Ruby 2.6.2, something that was supposed to be less than a walk in the park. I knew I would most likely have some hiccups when compiling gem’s native extension, but that usually and rather unglamorously boils down to finding the correct MySQL dev libraries. However, there were unexpected twists and turns.
Installing the mysql2 gem
$ asdf shell ruby 2.6.2 $ gem install mysql2 Building native extensions. This could take a while... ERROR: Error installing mysql2: ERROR: Failed to build gem native extension. ... mysql client is missing. You may need to 'brew install mysql' or 'port install mysql', and try again. ...
Ok, so gem’s build script is politely telling me that I need to first install MySQL using the Homebrew package manager. Since I don’t need the whole database server but only some development libraries (will be using MySQL from a Docker container), I tried installing the usual
$ brew install mysql-devel ... Error: No available formula with the name "mysql-devel"
$ brew install mysql-connector-c ... 🍺 /usr/local/Cellar/mysql-connector-c/6.1.11: 79 files, 15.3MB $ gem install mysql2 Building native extensions. This could take a while... ERROR: Error installing mysql2: ERROR: Failed to build gem native extension. ... compiling statement.c linking shared-object mysql2/mysql2.bundle ld: library not found for -l-Wno-atomic-implicit-seq-cst clang: error: linker command failed with exit code 1 (use -v to see invocation) make: *** [mysql2.bundle] Error 1 make failed, exit code 2
Linker coldly reported
library not found error so I had to take a bit longer look at the build log. Finally managed to found one rather interesting line more towards the beginning of it:
Using mysql_config at /usr/local/bin/mysql_config.
After some reading how mysql2 gem builds its native extension and checking the content of mentioned mysql_config script, I suspected something might be wrong there - linker command “-l-Wno-atomic-implicit-seq-cst” just didn’t make any sense.
A more detailed look at that config script revealed the culprit:
# /usr/local/bin/mysql_config ... # Create options libs="-L$pkglibdir" libs="$libs -l " embedded_libs="-L$pkglibdir" embedded_libs="$embedded_libs -l " ...
embedded_libs contained errors - they were cut off after the
-l parameter. I quickly tracked the error to the https://dev.mysql.com/downloads/connector/c repository where the problematic file was present (homebrew’s formula pulls package from there). After some tinkering, I managed to produce the correct version of the
# Create options libs="-L$pkglibdir" libs="$libs -lmysqlclient -lcrypto -lssl" embedded_libs="-L$pkglibdir" embedded_libs="$embedded_libs -lmysqlclient -lcrypto -lssl"
Trying to install the gem now, ends up with yet another error:
$ gem install mysql2 ... ld: library not found for -lcrypto
This one is easy. We just need to give instructions to the linker where to find the necessary
libcrypto (part of the
$ brew install openssl # if you haven't done that already $ gem install mysql2 -- --with-ldflags=-L/usr/local/opt/openssl/lib
Alternative solution (TL;DR)
Another solution that doesn’t require fixing the
mysql_config is providing all folders to the native extension’s build command.
mysql2gem will then use those settings and not the ones provided by the
$ gem install mysql2 -- \ --with-ldflags=-L/usr/local/opt/openssl/lib \ -L/usr/local/opt/mysql-connector-c/lib -lmysqlclient -lcrypto -lssl \ --with-cppflags=-I/usr/local/opt/mysql-connector-c/include