最新版RubyのVisualStudio2012コンパイル環境構築

<h2>■ きっかけ</h2>
Ruby を VisualStudio2012(=msvcr110) の C++ に組み込むため、x64-mswin64 版 Ruby ビルド環境を構築しました。
つまりは x64-msvcr110-ruby2xx.dll とその関連ファイル一式が欲しかったということです。

<h2>■ なぜ環境から作る破目になったのか？</h2>
上記の通り、モノさえ手に入ればなんでも良かったのですがネット上で見つけることができませんでした。Windows 環境における Ruby 構築は鬼門と云われるだけあって関連ライブラリが VisualStudio によるビルド対応を投げていたりします。（Linux 発祥の古株オープン系アプリは VisualStudio でビルドするという行為そのものが苦行になりつつあります。Windows は Microsoft の自分勝手な OS 改変の繰り返しにより開発者も対応に嫌気が差してきていてオープンなマルチプラットフォーム開発環境から締め出されつつあるのかなと）もっとも Cygwin や MinGW でのビルドならさほど問題はないのですが、今回は VisualStudio 縛りがあることで対応を投げているライブラリもビルドしなければなりませんでした。

<h2>■ ダウンロード</h2>
今回ビルドに使用したソースコードのダウンロード先です。

● Ruby
ソースのダウンロード先です。最新の安定バージョンは 2.1.2 です。Git や Subversion で最新バージョンのクローンを入手することもできます。下でコンパイルエラー事例２に書きましたが、現在 2.1.0-2.2.0dev ではコンパイルが通らない可能性があります。ruby-2.0.0-p481 では正常にコンパイル確認が通ることを確認しました。最新版でコンパイルの確認ができ次第更新する予定です。

[開発元] https://www.ruby-lang.org/ja/
[Git] https://github.com/ruby/ruby
[Subversion] http://svn.ruby-lang.org/repos/ruby/trunk
*必要 [bison](http://gnuwin32.sourceforge.net/packages/bison.htm), [sed](http://www.kt.rim.or.jp/~kbk/sed/)(onigsedの場合はsed.exeにリネーム), [gperf](http://gnuwin32.sourceforge.net/packages/gperf.htm)

以下ググれば手に入る物は省略させて下さい。readline の最新版は6.3ですが、VisualStudio に対応しなくなって久しいので対応していただいたモノを使用します。Perl は導入しやすい Strawberry Perl をリンクしてあります。Perl は 64bit である必要はありません。

● [libiconv-1.14-mod](https://drive.google.com/file/d/0B-6mv8KBOIafSkF5S3RUOFFVYUE/edit?usp=sharing) *libiconv-1.11.1 までは nmake サポート
● libxslt-1.1.28 *依存:libxml2
● openssl-1.0.1i *必要 [Perl](http://strawberryperl.com/), [NASM](http://www.nasm.us/pub/nasm/releasebuilds/2.11.05/win32/)
● [readline-4.3-2](http://jarp.does.notwork.org/win32/)
● yaml-0.1.6
● zlib-1.2.8

<h2>■ 資料</h2>
● Ruby 環境構築講座 Windows 編 - 達人出版会
VisualStudio2010 ビルド版 Ruby の MSI を公開されている arton 氏の著書、参考にさせていただきました。

Ref. ActiveScriptRuby and Other packages
http://www.artonx.org/data/asr/

<h2>■ 参考ページ</h2>
● 全体
Ref. x64-mswin64版Ruby 2.0.0-preview1をVisual Studio 2012 for Desktopでビルドした - 単なる日記＠はてな
http://d.hatena.ne.jp/iwadon/20121119/1353330176

● libiconv
Ref. How to Build libiconv with Microsoft Visual Studio - CodeProject
http://www.codeproject.com/Articles/302012/How-to-Build-libiconv-with-Microsoft-Visual-Studio

● OpenSSL 
Ref. Building OpenSSL for Visual Studio - Dev Room
http://developer.covenanteyes.com/building-openssl-for-visual-studio/

<h2>■ 環境</h2>
<h3>1. ライブラリの格納場所</h3>
コンパイルしたライブラリを後に Ruby のコンパイルで参照するためにディレクトリを作成して Windows の環境変数に登録します。Linux を踏襲してとあるディレクトリの中に bin, lib, include を作成して環境変数の PATH, LIB, INCLUDE として登録して下さい。ここでは __"C:\Users\\[Username]" に作成して環境変数に登録__しているものとします。コンパイルした Ruby もここに作成されます。以下ここをホームディレクトリとして扱います。

<h3>2. コンパイル環境</h3>
VisualStudio2012 Pro 以上がインストールされていることを前提として進めます。x64 版の nmake が使用できる環境が必要です。
`プログラム > Microsoft Visual Studio 2012 > Visual Studio Tools > VS2012 x64 Native Tools コマンド プロンプト`
から起動するか、コマンドプロンプトから以下を実行します。（Windows7 x64 環境の場合）
`> "C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\vcvarsall.bat" amd64`

以下のようなバッチファイルを "vc110.bat" として bin に入れておくと、任意の位置からコマンドプロンプトを立ち上げた後に `> vc110 amd64` で環境を呼び出せるので便利です。2行目は [bison](http://gnuwin32.sourceforge.net/packages/bison.htm) をインストーラーで入れたためここで PATH に追加しています。"C:\Users\\[Username]" に直接インストールした場合は必要ありません。

```bat:bin/vc110.bat
@echo off
@SET PATH=C:\Program Files (x86)\GnuWin32\bin;%PATH%	;bison の実行パスを PATH に追加
call "C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\vcvarsall.bat" %1
```

<h3>● 注意</h3>
MinGW/msys 環境や Cygwin の bin, lib, include などを PATH 登録している場合は、ビルド時に他の DLLや LIB が競合してしまう可能性があります。特に OpenSSL は使用頻度が高いため一時的に PATH 登録から外すなど、VisualStudio ビルド以外のライブラリを読み込まないように対策を講じておく方が無難です。

<h2>■ ライブラリコンパイル</h2>
<h3>● libiconv-1.14-mod のコンパイル</h3>
libiconv-1.14-mod は libiconv-1.13 用のパッチ [libiconv-1.13-ja-1.patch.gz](http://www2d.biglobe.ne.jp/~msyk/software/libiconv-1.13-ja-patch.html) を libiconv-1.14 用にあべちん氏([サイト](http://blog.k-tai-douga.com/article/39676791.html))が修正したものを適用したバージョンです。日本語環境における文字コードの修正と追加がなされています。

コンパイルについては [How to Build libiconv with Microsoft Visual Studio - CodeProject](
http://www.codeproject.com/Articles/302012/How-to-Build-libiconv-with-Microsoft-Visual-Studio) を参考に作成しました。解説は長くなるのでソリューションファイルを用意しました。

[libiconv-1.14-mod](https://drive.google.com/file/d/0B-6mv8KBOIafZmRKYVltbFZZQlE/edit?usp=sharing) - VisualStudio2012 で作成したソリューションファイル

x64/Release でビルド後 libiconv/Release_amd64 に作成されたファイルをコピーして下さい。

・libiconv/Release_amd64/iconv.dll を bin にコピー
・libiconv/Release_amd64/iconv.lib を lib にコピー
・libiconv/include/iconv.h を include にコピー

以上で libiconv-1.14-mod ライブラリは完了です。

<h3>● libiconv-1.11.1 のコンパイル（libiconv-1.14-mod の妥協案）</h3>
libiconv-1.11.1 は nmake に対応した最後のバージョンです。**libiconv-1.14-mod を作成している場合は必要ありません。**ソースファイルを解凍してできた libiconv-1.11.1 に amd64 モードの nmake が使用できるコマンドプロンプトで入ります。以下のコマンドを入力します。

```
> nmake -f makefile.msvc NO_NLS=1 DLL=1 MFLAGS=-MT
> nmake PREFIX=C:\Users\[Username] -f makefile.msvc NO_NLS=1 DLL=1 MFLAGS=-MT install
```

・bin/iconv.dll
・bin/iconv.exe(不要)
・lib/iconv.lib
・include/iconv.h

がインストールされて libiconv-1.11.1 ライブラリは完了です。

<h3>● openssl-1.0.1i のコンパイル</h3>

ソースファイルを解凍してできた openssl-1.0.1i に amd64 モードの nmake が使用できるコマンドプロンプトで入ります。 openssl はコンパイル設定に perl を、コンパイルに nasm を使用します。 `> nasm -v`, `> perl -v` と打ち込んで NASM または Perl のバージョンについて表示されれば大丈夫です。設定では 32bit/64bit, dll/staticlib の設定を指定します。今回は 64bit/staticlib を作成します。以下のコマンドを入力します。

```
> perl Configure VC-WIN64A --prefix=C:\Users\[Username]
> ms\do_win64a
> nmake -f ms\nt.mak
> nmake -f ms\nt.mak install 
```

成功すれば、

・bin/openssl.exe(不要)
・lib/ssleay32.lib
・lib/libeay32.lib
・include/openssl/

がインストールされて openssl は完了です。

また、64bit/dll で作成したい場合、私の環境では nasm のコンパイルがうまく動きませんでしたが、 **no-nasm** オプションで無効にすればビルドすることができました。nasm が原因と思われるエラーが解決しない場合は以下のコマンドで作成できるかもしれません。

```
> perl Configure no-asm VC-WIN64A --prefix=C:\Users\[Username]
> ms\do_win64a
> nmake -f ms\ntdll.mak
> nmake -f ms\ntdll.mak install 
```

<h3>● readline-4.3-2 のコンパイル</h3>
readline は Ruby の irb で使用されているコマンドラインの行入力に編集機能を付加するライブラリです。残念ながら現在最新版の 6.3 では VisualStudio の対応はされていません。ここでは [eban 氏のサイト](http://jarp.does.notwork.org/win32/)から多バイト文字などの修正が適用された readline-4.3-2-src.zip を使用します。

ソースファイルを解凍してできた readline-4.3-2-src フォルダに amd64 モードの nmake が使用できるコマンドプロンプトで入ります。

```
> cd win32
> nmake
> nmake prefix=C:\Users\[Username] install
```

成功すれば、

・bin/readline.dll
・lib/readline.lib
・lib/history.lib
・include/readline/

がインストールされて readline ライブラリは完了です。

<h3>● yaml-0.1.6 のコンパイル</h3>
ソースファイルを解凍して yaml-0.1.6\win32\vs2008 に入ります。VisualStudio2012 用のソリューションファイルは存在しませんが、vs2008/libyaml.sln を VisualStudio2012 用に更新すれば問題ありません。
更新後、今度は x64 によるビルド環境がありません。構成マネージャーで win32 を元に x64 環境を構築します。

![libyaml.jpg](https://qiita-image-store.s3.amazonaws.com/0/23268/0dcfca3f-c585-a72c-dc9e-24b9c36cffc8.jpeg)

ビルド前にプリプロセッサ命令を追加する必要があります。今回のビルド対象になるのは yamldll プロジェクトなのですが、このプロジェクトのプロパティ「構成プロパティ > C/C++ > プリプロセッサ」を開いてプリプロセッサの定義に `WIN32;NDEBUG;` を追加します。

![libyaml_prep.jpg](https://qiita-image-store.s3.amazonaws.com/0/23268/0d4d4687-eadd-3829-f8f6-0b47ab430ce6.jpeg)

あとは設定を適用してから yamldll プロジェクトを x64/Release でビルドして下さい。このプリプロセッサ定義を追加しなくてもビルドは通りますが、Ruby を構築するときにエラーの原因となります。

・yaml-0.1.6\win32\vs2008\x64\Release\yaml.dll を bin にコピー
・yaml-0.1.6\win32\vs2008\x64\Release\yaml.lib を lib にコピー
・yaml-0.1.6\include\yaml.h を include にコピー

以上で yaml ライブラリは完了です。


<h3>● zlib-1.2.8</h3>
ソースファイルを解凍してできた zlib-1.2.8 フォルダに amd64 モードの nmake が使用できるコマンドプロンプトで入ります。

```
> cd /zlib-1.2.8
> nmake -f win32\Makefile.msc
```
zlib はフォルダ直下に目的のファイルが作成されるため、自前でコピーします。

・zlib-1.2.8/zlib1.dll を bin にコピー
・zlib-1.2.8/zdll.lib, zlib-1.2.8/zlib.lib を lib にコピー
・zlib-1.2.8/zconf.h, zlib-1.2.8/zlib.h を include にコピー

以上で zlib ライブラリは完了です。

<h2>■ Ruby コンパイル</h2>
<h3>● コンパイル手順</h3>
ここまでの全てのライブラリが用意できれば Ruby 本体のビルド環境が整っています。ライブラリと同様に ruby を C:\Users\[Username] にインストールします。ライブラリ同様 amd64 モードの nmake が使用できるコマンドプロンプトでソースファイルを解凍した ruby-2.x.x に入ります。

まずは Makefile を作成します。

```
> win32\configure --prefix=C:\Users\[Username] --target=x64-mswin64
> nmake V=1
> nmake install
```

nmake の `V=1` は詳細表示用のオプションです。 `> nmake` でビルドが止まってしまったときにエラーの詳細を知るヒントが欲しい場合に指定します。指定しなくてもビルドの結果は変わりません。

<h3>● コンパイルエラー事例１</h3>`> nmake`
miniruby.exe のコンパイルでリンクエラーが発生する。

以下のバグレポートと同じ問題が発生、リンクが上手く行きませんでした。
Ref. Bug #7660: VC Builds Broken - ruby-trunk - Ruby Issue Tracking System
https://bugs.ruby-lang.org/issues/7660

コンパイルルールを修正することで解決しました。具体的には以下のように *Configure 実行後* Makefile.sub から該当行を削除しました。

```sh:\win32\Makefile.sub
-.c.obj:
-	$(ECHO) compiling $(<:\=/)
-	$(Q) $(CC) $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) $(COUTFLAG)$@ -c -Tc$(<:\=/)
```

 <h3>● コンパイルエラー事例２</h3>`> nmake`
これも nmake で起きます。

```
compiling ../.././ext/psych/yaml/api.c
api.c
```

の後に YAML 関係の関数または変数の定義エラーで通らなくなります。
 Bug #9189 から判断して Ruby の一次展開先(※)に多バイト文字が使用されているとダメなのかと判断して修正してみましたが展開先を変えても解決せず、 ruby-2.0.0-p481 はコンパイルできるため Ruby 側のエラーと判断しました。ただ Ruby のコンパイルパスに多バイト文字とスペースを入れない方が無難だと思います。

※一次展開先：`> miniruby.exe -e "system('set TEMP')"` で確認可能
Ref. Bug #9189: Build failure on Windows in case of nonascii TEMP environment. - ruby-trunk - Ruby Issue Tracking System
https://bugs.ruby-lang.org/issues/9189

<h2>■ まとめ</h2>
説明が雑なところもあったと思いますが、一通り VisualStudio2012 環境で 64bit 版 Ruby の構築方法を書きました。私は C++ への組み込み用にコンパイルがしたかったので、通常の Windows 環境で使用する Ruby としては gem の使用等に問題が起きるかもしれません。その辺りは参考ページや arton氏の Ruby 環境構築講座 Windows 編を参考にして下さい。