WindowsでWebAssemblyの環境を整える

## WindowsでC/C++をWebAssemblyに変換したい

[WebAssemblyを使ってみる(C/C++をWebAssemblyに変換してChromeで実行)](http://qiita.com/HirokiMiyaoka@github/items/89975a9e8205ced3603f) では主にLinux環境下でC/C++をWebAssemblyに変換していました。

今回はWindowsでその環境を整えます。以下今回の作業環境です。

* Windows 10(64bit)
* VisualStudio 2015
* Cmake 3.5.0
* LLVM 3.9(のはず)

このページではツールのビルドを行い、C/C++をWebAssemblyに変換して実行するのは上の記事で行いますので、ツールの導入以外はそちらを見てください。

## 流れ

必要なツール群は基本以下の流れで用意します。

* Cmake (cmake-gui)を使ってVisualStudioのプロジェクトを書き出す
* ALL_BUILD.vcxprojを開く
* ビルドする
* ビルドした成果物を入れるディレクトリにコピー

今回のディレクトリ構成は以下を想定します。

* C:\Personal\Git 以下に各リポジトリをcloneしたりビルドする。
* C:\dev\bin 以下に成果物のexeなどを入れる。

作業前に成果物を入れるディレクトリにパスを通して、再起動しておくと後でコマンドがスムーズに使えて良いと思います。

では一つ一つビルドしていきます。

## LLVM+clang(WebAssembly対応)

LLVM+clangをVisualStudioでビルドします。

なお、MinGWなどで環境を整え挑戦しましたが、ファイルサイズが大きいの何のと言って70%くらいまでしかビルドが通らないので諦めました。

VisualStudioさんに頑張ってもらいましょう。

### clone

まずLLVMのリポジトリ( http://llvm.org/git/llvm.git )をcloneします。

次にLLVMのビルドを行うbuildフォルダを作っておきます。

その後、clangのリポジトリ( http://llvm.org/git/clang.git ) をcloneし、LLVMリポジトリ内のtoolsフォルダにclangフォルダを移動します。

### Cmake

Cmakeを起動します。

起動したらBowse SourceでLLVMのフォルダを、Browse Buildで先ほど作ったビルドを行うフォルダを指定します。

次にAdd Entryで`LLVM_EXPERIMENTAL_TARGETS_TO_BUILD`という名前の値に`WebAssembly`を指定します。

![llvm_cmake_ss1.png](https://qiita-image-store.s3.amazonaws.com/0/10584/6b9bcd10-a8b8-2b36-cb01-2a3855420a21.png)

ここまで終わると、Cmakeは次のような状態になっているはずです。

![llvm_cmake_ss2.png](https://qiita-image-store.s3.amazonaws.com/0/10584/071503a1-ecb6-448f-35c0-0e6d90046417.png)

ここでGenerateボタンをクリックすると以下の様なダイアログが出るので、`VisualStudio 14 2015`が選択されていることを確認後、Finishをクリックします。

![llvm_cmake_ss3.png](https://qiita-image-store.s3.amazonaws.com/0/10584/377abc00-5b30-988b-6d40-926a84b54477.png)

すべての作業が追わると今回指定した値が一覧で表示されるので、WebAssemblyが有効かどうか確認しておきます。

![llvm_cmake_ss4.png](https://qiita-image-store.s3.amazonaws.com/0/10584/f1ae12a1-0bcd-f33c-e64c-d10442937bb6.png)

### ビルド

buildフォルダに入ると、VisualStudioのプロジェクトファイルがあると思うので、ALL_BUILD.vcxprojを開いてください。開くのにちょっと時間がかかります。

すべてのプロジェクトを開いたら、ビルドボタンをクリックします。一応Releaseにしておくとファイルサイズとか小さくなります。

ビルドにはおよそ2,3時間かかると思います。

### 成果物

成果物はDebugもしくはReleaseフォルダ内のbinにあります。

`clang.exe`や`llc.exe`があることを確認したら、とりあえず中のファイルすべてを、成果物を入れるフォルダ( 今回は C:\dev\bin )にコピーします。

## binaryen

次にbinaryenをビルドします。

### clone

binaryenのリポジトリ( https://github.com/WebAssembly/binaryen.git )をcloneします。

### CMake

CmakeのBrowse SourceとBowse Buildでbinaryenのフォルダを指定します。

Generateボタンを押すと先程と同じくVisualStudioの指定があるので選んでFinishをクリックします。

作業が終わると以下のような状態になっているはずです。

![llvm_cmake_ss5.png](https://qiita-image-store.s3.amazonaws.com/0/10584/4ebdadef-9020-76ad-1cf5-bf066f54879f.png)


### コードの修正とビルド

binaryenのフォルダに入って、ALL_BUILD.vcxprojを開きます。

今回はビルドするとエラーになる箇所があるので、修正します。

`src\wasm-s-parser.h`

```c
    if (!s[2]->dollared() && !std::isdigit(s[2]->str()[0])) {
```

このstd::isdigitがないので、std::を外します。

```c
    if (!s[2]->dollared() && !isdigit(s[2]->str()[0])) {
```

### 成果物

成果物はbin内のDebugもしくはReleaseフォルダ内にあります。

## sexpr-wasm-prototype

### clone

sexpr-wasm-prototypeのリポジトリ( https://github.com/WebAssembly/sexpr-wasm-prototype.git )をcloneします。

### CMake

CmakeのBrowse SourceとBowse Buildでsexpr-wasm-prototypeのフォルダを指定します。

Generateボタンを押すと先程と同じくVisualStudioの指定があるので選んでFinishをクリックします。

作業が終わると以下のような状態になっているはずです。

![llvm_cmake_ss6.png](https://qiita-image-store.s3.amazonaws.com/0/10584/3d2f2f5b-684e-c887-2c3d-07afb340e32b.png)

### プロジェクトの修正とビルド

sexpr-wasm-prototypeのフォルダに入って、ALL_BUILD.vcxprojを開きます。

今回もビルドするとエラーになる箇所があるので、修正します。

まず、警告をエラー扱いしているので、それを外します。

ソリューションエクスプローラー上のsexpr-wasmの上で右クリック→プロパティを開きます。

構成プロパティ→C/C++→全般を選択し、警告をエラーとして扱うの値をいいえにします。

![llvm_cmake_ss7.png](https://qiita-image-store.s3.amazonaws.com/0/10584/13616bbe-b39d-1fb8-36c0-32da7e93b103.png)

wasm-wastも同様に警告をエラーとして扱わないようにします。

もしDebugビルドの場合、このままでは以下の様なエラーが出ます。

```
C4013 関数 'memcpy' は定義されていません。int 型の値を返す外部関数と見なします。
C2040 'memcpy': 'void *(void *,const void *,size_t)' は 'void *(void *,const void *,size_t)' と間接操作のレベルが異なります。
```

英語だと多分これ。

```
C4013: 'memcpy' undefined; assuming extern returning int
C2040: 'memcpy' : 'void (char *,const char *,int )' differs in levels of indirection from 'void *(void *,const void *,unsigned int )'
```

これをなんとかすべく、一箇所コードを修正します。

`wasm-config.h`

このファイルの可能な限り上の方に以下3行を追加します。

```c
#ifndef memcpy
#include<vcruntime_string.h>
#endif
```

これを追加すると、上記エラーが消えます。

### 成果物

リポジトリ内のDebugもしくはReleaseフォルダ内にあります。

## 最後に

これでWindows上でC/C++をWebAssemblyに変換するツール群のビルドは終了です。

パスが通っていれば、[WebAssemblyを使ってみる(C/C++をWebAssemblyに変換してChromeで実行)](http://qiita.com/HirokiMiyaoka@github/items/89975a9e8205ced3603f) で利用している`clang`、`llc`、 `s2wasm`、`sexpr-wasm`の各種コマンドが使えるようになっているはずです。

それでは、後は頑張ってください。