WindowsにおけるMySQL Connector/Cを使わないmysql2 gemパッケージのインストール方法

自宅で使用しているRedmineのバージョンアップにおいて、mysql2のgemパッケージが上手くインストールされなくて困っていましたが、何とか解決したので、解決記念に備忘録として置いておきます。
ちなみに、一般的に広く知らているMySQL Connector/Cを使用する方法をなぜ回避したかったかというと、当該ライブラリの更新が2017年(6年前)で止まってしまっていたからです。

なお、本記事では、Redmineのインストール方法そのものについては扱いません。ご了承ください。

# 前提条件
* OS : Windows11
* Ruby : Ruby+Devkit 3.1.4-1(x64) (https://rubyinstaller.org/downloads/)
* MySQL : Mysql5.7
* (Redmine : Redmine5.0.4)
  ※これをインストールする際にmysql2のgemパッケージが必要だった
* Rubyのインストールディレクトリ : C:\Path\To\Ruby
* Mysqlのインストールディレクトリ : C:\Path\To\Mysql
* MySQL Connector/Cのインストールディレクトリ : C\Path\To\mysql-connector-c

自分の場合は、Redmine5のインストールの際のbundle installにおいて上手くmysql2が入らないという症状を起こしていましたが、windowsでrailsの環境を構築しようとした際に同様のエラーが出ているような記述がインターネット上で散見されますので、案外いろんなところに応用が利くかもしれません(上手くいかなくても自己責任でお願いします)。

# 結論
以下の方法で上手くいきました。

1\. 必要パッケージのインストール
```
C:\>ridk enable
C:\>ridk install 1 2 3
C:\>pacman -S mingw-w64-x86_64-libmariadbclient --noconfirm
```
2\. mysql2のgemパッケージのインストール
```
C:\>gem install mysql2 --platform="ruby" -- --with-mysql-lib=C:\Path\To\Ruby3\msys64\mingw64\lib --with-mysql-include=C:\Path\To\Ruby\msys64\mingw64\include\mysql
Using msys2 packages: mingw-w64-ucrt-x86_64-libmariadbclient
Building native extensions with: '--with-mysql-dir=C:\Ruby3\msys64\mingw64'
This could take a while...
Successfully installed mysql2-0.5.5
Parsing documentation for mysql2-0.5.5
Installing ri documentation for mysql2-0.5.5
Done installing documentation for mysql2 after 0 seconds
1 gem installed
```
# Why?
なぜこれで上手くいったのか、個人的な考察を載せておきます。msys2有識者の方、もし間違っている箇所がありましたら、ご教示いただければ幸いです。
ただし、完全に余談(「余談」と書いて「ほんぺん」と読む)になる上に、お見苦しく分かりにくい文章に仕立てあがっています。興味のある方だけお読みください。また、卒研などでLinux環境下で様々な環境構築の沼に陥った経験から、勘に従ってコマンドを走らせている部分があります。理系出身の人間がこんなことを言っていいのかわかりませんが、本記事は必ずしも理論的な文章にはなっておりませんので、そこのところはご容赦ください。

## mysql2のgemパッケージのビルドで用いられるライブラリ
<details><summary>まず、何もしないでgem install mysql2を走らせるとこのようなログが得られます。</summary>

```
C:\>gem install mysql2
Fetching mysql2-0.5.5.gem
Temporarily enhancing PATH for MSYS/MINGW...
Using msys2 packages: mingw-w64-ucrt-x86_64-libmariadbclient
Building native extensions. This could take a while...
ERROR:  Error installing mysql2:
        ERROR: Failed to build gem native extension.

    current directory: C:/Ruby3/lib/ruby/gems/3.1.0/gems/mysql2-0.5.5/ext/mysql2
C:/Ruby3/bin/ruby.exe -I C:/Ruby3/lib/ruby/3.1.0 extconf.rb
checking for rb_absint_size()... yes
checking for rb_absint_singlebit_p()... yes
checking for rb_gc_mark_movable()... yes
checking for rb_wait_for_single_fd()... yes
checking for rb_enc_interned_str() in ruby.h... 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=C:/Ruby3/bin/$(RUBY_BASE_NAME)
        --with-openssl-dir
        --without-openssl-dir
        --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
C:/Ruby3/lib/ruby/3.1.0/mkmf.rb:1083:in `block in find_library': undefined method `split' for nil:NilClass (NoMethodError)

    paths = paths.flat_map {|path| path.split(File::PATH_SEPARATOR)}
                                       ^^^^^^
        from C:/Ruby3/lib/ruby/3.1.0/mkmf.rb:1083:in `each'
        from C:/Ruby3/lib/ruby/3.1.0/mkmf.rb:1083:in `flat_map'
        from C:/Ruby3/lib/ruby/3.1.0/mkmf.rb:1083:in `find_library'
        from extconf.rb:131:in `<main>'

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

  C:/Ruby3/lib/ruby/gems/3.1.0/extensions/x64-mingw-ucrt/3.1.0/mysql2-0.5.5/mkmf.log

extconf failed, exit code 1

Gem files will remain installed in C:/Ruby3/lib/ruby/gems/3.1.0/gems/mysql2-0.5.5 for inspection.
Results logged to C:/Ruby3/lib/ruby/gems/3.1.0/extensions/x64-mingw-ucrt/3.1.0/mysql2-0.5.5/gem_make.out
```
</details>

ここで、ログの中に
```
Temporarily enhancing PATH for MSYS/MINGW...
Using msys2 packages: mingw-w64-ucrt-x86_64-libmariadbclient
```
とありまして、Rubyに付随するMSYS/MINGWに含まれている、mingw-w64-ucrt-x86_64-libmariadbclientを使用して、mysql2のgemパッケージをインストールしようとしていることが分かります。しかし、関数か何かの不足からか、上手くいっていません。

ここで、mingw-w64-ucrt-x86_64-libmariadbclientが何かというと、ucrt64版(これが何かは筆者もあまり理解していません)のlibmariadbclientであるらしいです。pacmanの-Ssオプションを使って調べてみたところ、msys2でインストールできるlibmariadbclientは6種類あるようで、デフォルトで最初からインストールされるのがucrt64版のようです。
```
C:\>pacman -Ss mariadb
clangarm64/mingw-w64-clang-aarch64-libmariadbclient 3.1.13-1
    MariaDB client libraries (mingw-w64)
mingw32/mingw-w64-i686-libmariadbclient 3.1.13-1
    MariaDB client libraries (mingw-w64)
mingw64/mingw-w64-x86_64-libmariadbclient 3.1.13-1
    MariaDB client libraries (mingw-w64)
ucrt64/mingw-w64-ucrt-x86_64-libmariadbclient 3.1.13-1 [インストール済み]
    MariaDB client libraries (mingw-w64)
clang32/mingw-w64-clang-i686-libmariadbclient 3.1.13-1
    MariaDB client libraries (mingw-w64)
clang64/mingw-w64-clang-x86_64-libmariadbclient 3.1.13-1
    MariaDB client libraries (mingw-w64)
```
ucrt版libmariadbclientのインストール先は、C:\Path\To\Ruby\msys64\ucrt64\bin, C:\Path\To\Ruby\msys64\ucrt64\lib及びC:\Path\To\Ruby\msys64\ucrt64\includeとなります。インストールされるファイルの一覧は、msys2の公式サイト https://packages.msys2.org/package/mingw-w64-ucrt-x86_64-libmariadbclient に書いてあり、libmariadbclientのみならず、libmysqlclientやmysql.hも含まれています。

## mingw64版のlibmariadbcilentなら上手く行った

ここで参考にしたのが、ubuntuでのmysql2のgemパッケージのインストールの際に必要な作業です。Ubuntuではlibmysqlclient-devパッケージのインストールが必要でした。
```
$ sudo apt install libmysqlclient-dev
```
これをヒントに考え、libmysqlclient-devに相当するパッケージがインストールされていないから、今回のビルドは上手くいっていないという仮説を立てました。ここで、例のpacman -Ssコマンドでそれらしいパッケージが無いか調べてみます。
```
C:\>pacman -Ss mysql

C:\> 
```
…特に何も出てきません。ここで、ひとまず今度はpacman -Ss mariadbをやってみます。そうすると、前節で得られた実行結果が返ってきます。ここで、公式のmingw-w64-ucrt-x86_64-libmariadbclientのページ https://packages.msys2.org/package/mingw-w64-ucrt-x86_64-libmariadbclient を見ると、当該パッケージの中にはmariadbに関するファイルのみならず、libmysqlclient.dll.aやmysql.hなどのmysqlに関するパッケージも含まれていることが分かります。つまり、この時点でlibmysqlclientに相当するパッケージはインストールされているのです。

ではなぜ上手く行かないのか。先ほどの仮説はひっくり返されてしまい、どうしてこうなったかの原因も正直よくわからず、困ってしまいました。ただし、なんとなくmingw64版のlibmariadbclientを代わりに使えば上手くいくんじゃないかという勘が働き(Windowsでgccとかgfortranを動かそうとすると、真っ先にMinGWがサーチにヒットしますゆえ、MinGWの環境は少しだけ触ったことがあるという理由から、なんとなくMinGWを試したというのが本当のところです)やってみたというところです。結局、これが正解だったようです。
```
C:\>pacman -S mingw-w64-x86_64-libmariadbclient --noconfirm
```
mingw64版のlibmariadbclientのインストール先は、C:\Path\To\Ruby\msys64\mingw64となります。したがって、以下のようにビルドに使うファイルのパスを示してmysql2のgemパッケージのインストールを行えば、ビルドが通ります。
なお、自分の用途の場合、Redmineのlocalにgemをインストールしてもらわないといけないために、C:\Path\To\Redmineにディレクトリ移動してます。
```
C:\>cd C:\Path\To\Redmine
C:\Path\To\Redmine\gem install mysql2 --platform="ruby" -- --with-mysql-dir=C:\Path\To\Ruby\msys64\mingw64
```
ちなみに、以下のような方法で、さらに細かくlibraryとincludeのディレクトリのパスを指定してあげても行けると思います。
```
C:\Path\To\Redmine>gem install mysql2 --platform="ruby" -- --with-mysql-lib=C:\Path\To\Ruby\msys64\mingw64\lib --with-mysql-include=C:\Path\To\Ruby\msys64\mingw64\include\mysql
```

# 他に試した方法

## Mysql Connector/Cを使用する方法

インターネット上で検索をかけるとそれなりに出てくる、結構メジャーな方法だと思います。自分もこの方法を一度は採用して成功しましたが、古すぎるライブラリの利用が嫌でしたので結局他の方法を利用しました。
方法は以下の通りです。

1\. https://downloads.mysql.com/archives/c-c/ から、mysql-connector-c-x.x.xx-win64.zipをダウンロードしてきて、C:C\Path\To\mysql-connector-cに展開する。
2\. 以下のコマンドを走らせる。
```
C:\>gem install mysql2 --platform="ruby" -- --with-mysql-dir=C:\Path\To\mysql-connector
```
3\. C:\Path\To\mysql-connector-c\lib\libmysql.dllをコピーしてC:\Path\To\Ruby\bin\に貼り付け、名前をlibmariadb.dllに変更する

この方法は試したところ、一応上手く行きましたが、やはり不利パッケージはセキュリティ上の問題があったりして、使うのには漠然とした不安があり、使いたくないというところがありますので、回避する方法を探すこととなりました(自分の場合、LAN内でポート開放もしない状態で使っているため、あまり気にする必要はないかもしれませんが)。

## Mysql Community Serverのlibmysqlclientを使用する方法

C:\Path\To\Mysql\lib及びC:\Path\To\Mysql\includeにlibmysqlclientやmysql.hが存在しますので、それを指定してmysql2のgemパッケージのインストールを行う方法です。コマンドは以下の通りです。
```
C:\>gem install mysql2 --platform="ruby" -- --with-mysql-lib=C:\Path\To\Mysql\lib --with-mysql-include=C:\Path\To\Mysql\include
```
この方法は、Ruby+Devkit 3.1.4-1(x64) + Mysql5.7.41の組み合わせでは失敗しました。