RubyをWindows上でVisual C++でビルドする2018

!! [2024年1月版をhsbtさんが書いています](https://www.hsbt.org/diary/20240126.html#p02)
!! [2020年12月版をhsbtさんが書いています](https://www.hsbt.org/diary/20200215.html)
!! [2020年2月版をhsbtさんが書いています](https://www.hsbt.org/diary/20200215.html)
!! 最新のVisual Studioでは後述のVisual C++の個別のコンポーネントで必要なものが異なるようです。よくわからない場合はそれっぽいものに片っ端からチェックをつけてみましょう

## 序
普通は[RubyInstaller](https://rubyinstaller.org/)を使うんで、あえて茨の道を行きたい人向けです。以下の記事のアップデート版

* https://qiita.com/nurse/items/6334a88bd446c177b6bd
* https://naruse.hateblo.jp/entry/2017/06/12/143220

## ruby-mswinとは
Microsoft Visual C++を用いて作成されるCRubyです。これはmingw版やcygwin版などとバイナリ互換性がなく、それら用にコンパイルされた拡張ライブラリを用いることが出来ません。

## Visual C++
まずはコンパイラの調達です。すでにVisual Studioをインストール済みならばそれを使えばいいのですが、そうでない場合は[Build Tools for Visual Studio 2017](https://visualstudio.microsoft.com/ja/downloads/#build-tools-for-visual-studio-2017)というIDEなしのインストーラを使うと速いです。

インストーラを実行したら以下を選択の上でインストールします。

* 個別のコンポーネント
  * Windows ユニバーサル CRT
  * Visual C++ Build Tools のコア機能
  * VC++ 2017 バージョン 15.8 v14.15 最新の v141 ツール
  * Windows 10 SDK (10.0.17134.0）
* 言語パック
  * 英語

以降、コマンドプロンプトはスタートメニューの「Visual Studio 2017」→「VS 2017用 x64 Native Tools コマンドプロンプト」を用います。

## BASERUBY
Rubyをソースコードからビルドする場合、特にtarballからではなくリポジトリから取得した場合にはbisonやgrep、sedといったUnixツールが必要ですし、なんとRubyまで必要です。個別に調達すると大変なので、たとえVisual C++でビルドするのだとしても、[RubyInstaller](http://rubyinstaller.org/downloads/)（WITH DEVKITかつx64のもの）をインストールしましょう。インストール中にdevkitのインストールを促されるのでそれも入れます。

インストールできたらC:\Ruby25-x64\msys64\mingw64.exeを実行し、mingw64用msysを起動し、以下の通りbisonとgitをインストールします。

```sh
pacman -S bison git
```

注1: Unixツールは従来Git for Windows SDKを用いる方法を紹介していましたが、RubyInstaller2ではMSYS2を用いるようになったため、RubyInstallerのみで事足りるようになりました
注2: BASERUBYはWSLを用いる方法もあるかもしれません

## vcpkg
ruby-mswin版のインストールにおいて、従来大きなハードルになっていたのが拡張ライブラリの依存先ライブラリのビルドです。しかし2016年、[vcpkgの登場](https://blogs.msdn.microsoft.com/vcblog/2016/09/19/vcpkg-a-tool-to-acquire-and-build-c-open-source-libraries-on-windows/)によってだいぶ便利になりました。以下のようにインストールした後、Rubyで必要となるライブラリをビルドします。

```powershell
\Ruby25-x64\usr\bin\git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
bootstrap-vcpkg.bat
vcpkg --triplet x64-windows install libxml2 libxslt openssl readline zlib
```

## 環境変数
前述の通り、VS2017 x64 Native Tools コマンド プロンプトなどを用いてコンパイラ等の環境変数はあらかじめ設定しているものとして、以下の環境変数を設定します。

```powershell
set PATH=C:\vcpkg\installed\x64-windows\bin;%PATH%;C:\Ruby25-x64\msys64\usr\bin
```
ポイントはvcpkgのものを冒頭に置くということですね。前述の通りRubyInstallerのDLLはruby-mswinと互換性がないため、それらではなくvcpkgで入れた物を見つけられるよう、先に指定する必要があります。

## Rubyのビルド
以下の通りでビルド・インストールできます。（パスは適当に読み替えてください）

```powershell
win32\configure.bat --with-opt-dir=/vcpkg/installed/x64-windows
nmake install
```

なお、libxml2やlibxsltをvcpkgで入れているため、従来mswinでは使うことが難しかったNokogiriもRubyGemsから以下の通りインストールすることが可能です。

```powershell
gem install nokogiri -- --use-system-libraries --with-xml2-dir=/vcpkg/installed/x64-windows --with-xslt-dir=/vcpkg/installed/x64-windows --with-exslt=/vcpkg/installed/x64-windows
```

## FAQ

### 以下のようなエラーが出る

```
C:\>gem install reline-0.0.2.gem
ERROR:  Loading command: install (LoadError)
        126: The specified module could not be found.   - C:/Ruby27-reline/lib/ruby/2.7.0/x64-mswin64_140/openssl.so
ERROR:  While executing gem ... (NoMethodError)
    undefined method `invoke_with_build_args' for nil:NilClass
```

一般化すると、ビルドした `.so` ファイルがロードできないというエラーですね。多くの場合これは `openssl.so` が依存しているDLLファイルが適切にロードされていないからであり、おそらくMSYS用のライブラリが読み込まれてしまっています。

解決策としては上述の「環境変数」の項目を参考に `PATH` を適切に設定すれば直ります。