rustからWebAssemblyへコンパイル

## はじめに
日頃仕事ではWEB周りの開発をしているので、「rustで書いたコードをコンパイル→WebAssembly」を試してみたいと思います。

Emscriptenなしで、Rust単体でのwasmへのコンパイルが可能になりました。
[wasm32-unknown-unknown landed & enabled](https://www.hellorust.com/news/native-wasm-target.html)

## 環境
- ArchLinux(Kernel 4.12.4-1）
- Intel(R) Core(TM) i7-4790T CPU @ 2.70GHz
- Memory 16GB
- Vivaldi 1.11.917.39

## インストール
rustcを公式パッケージからインストールしていたのですが、「wasm32-unknown-emscripten」をターゲットに指定し、
コンパイルする必要があるので、rustupをインストールしました。
（おそらく、競合している旨のメッセージがでるかと思いますが、そのまま上書きする形でインストールを進めます）

rustをWebAssemblyにコンパイルする際、emscriptenを使用してWebAssemblyにコンパイルするので、emscriptenもインストールします（cargoでビルドした際に、[emcc](https://kripken.github.io/emscripten-site/docs/tools_reference/emcc.html)を使用します）。
また、コンパイルの過程でcmakeを使用するので、同時にcmakeもインストールします。

```bash
$ yaourt -S rustup
$ yaourt -S emscripten
$ yaourt -S cmake
```

## emscriptenとは？

emscriptenとは、C/C++のコードからJavaScriptを出力するコンパイラです。
超ざっくりいうと、「C/C++からLLVM-IR(中間言語）を生成し、それらをJavaScriptへ変換」、といった流れになります。

## 環境設定

インストールしたrustupを使用して、ターゲットを追加します。
また、WebAssembly用のプロジェクトを作成します。

```bash
$ rustup target add wasm32-unknown-emscripten
$ rustup target list

aarch64-apple-ios
aarch64-linux-android
aarch64-unknown-fuchsia
aarch64-unknown-linux-gnu
arm-linux-androideabi
arm-unknown-linux-gnueabi
arm-unknown-linux-gnueabihf
arm-unknown-linux-musleabi
arm-unknown-linux-musleabihf
armv7-apple-ios
armv7-linux-androideabi
armv7-unknown-linux-gnueabihf
armv7-unknown-linux-musleabihf
armv7s-apple-ios
asmjs-unknown-emscripten
i386-apple-ios
i586-pc-windows-msvc
i586-unknown-linux-gnu
i686-apple-darwin
i686-linux-android
i686-pc-windows-gnu
i686-pc-windows-msvc
i686-unknown-freebsd
i686-unknown-linux-gnu
i686-unknown-linux-musl
mips-unknown-linux-gnu
mips-unknown-linux-musl
mips64-unknown-linux-gnuabi64
mips64el-unknown-linux-gnuabi64
mipsel-unknown-linux-gnu
mipsel-unknown-linux-musl
powerpc-unknown-linux-gnu
powerpc64-unknown-linux-gnu
powerpc64le-unknown-linux-gnu
s390x-unknown-linux-gnu
sparc64-unknown-linux-gnu
wasm32-unknown-emscripten (installed) ※ wasm32-unknown-emscriptenがインストールされている
x86_64-apple-darwin
x86_64-apple-ios
x86_64-linux-android
x86_64-pc-windows-gnu
x86_64-pc-windows-msvc
x86_64-rumprun-netbsd
x86_64-unknown-freebsd
x86_64-unknown-fuchsia
x86_64-unknown-linux-gnu (default)
x86_64-unknown-linux-musl
x86_64-unknown-netbsd

$ cargo new --bin web_assembly
    Created binary (application) `web_assembly` project
```

## ビルドしてみる

実際に先程作成したプロジェクトをビルドしてみます。

```bash
$ cargo build --target wasm32-unknown-emscripten
error: could not exec the linker `emcc`: No such file or directory (os error 2)
```

emccが存在しないというエラーが出力されました。
先程、emscriptenはインストールしましたので、「PATHが通っていないのではないか？」、ということで実際にどのディレクトリにインストールされているのか調べてみます。

```bash
$ pacman -Ql emscripten | grep emcc
(標準入力):88:emscripten /usr/lib/emscripten/emcc
```

「/usr/lib/emscripten」は、PATH環境変数に含まれていないので、PATHを指定してビルドしてみます。
（本来は、.zshrcなどにPATH追加すればよいかと思います）

```
$ PATH=$PATH:/usr/lib/emscripten cargo build --target wasm32-unknown-emscripten
   Compiling web_assembly v0.1.0 
    Finished dev [unoptimized + debuginfo] target(s) in 1.73 secs
```

ビルドが完了しました。
WebAssemblyの本体は、「target/wasm32-unknown-emscripten/debug/deps/xxxx.wasm」になります（xxxxは任意）。

## WebAssemblyを使用してみる

ビルドが完了したWebAssemblyファイルを使用してみます。
[こちらの記事](http://qiita.com/_likr/items/daf46d6f66bc31cc4810#webassembly)を参考にし、WebAssemblyの動作確認を行いました（有益な記事があり、ありがたいです！）。

![ブラウザでの動作確認](https://cl.ly/051w330l2D1D/web_assembly_test.png)

確かに開発者ツールのConsoleに、「Hello, World!」が出力されています。

## まとめ
以上の手順で、rustからWebAssemblyにコンパイルすることができました。
最初、cmakeをインストールするのを忘れていないため、ビルドエラーが発生していました。
**ちゃんとマニュアルを読もう！！！**

次回はWebAssemblyにすることによりパフォーマンスが向上すると言われていますが、実際に「どれくらいパフォーマンスが上がるのか？」、等を検証したいと思います。

## 参考
- [Emscripten WikiPedia](https://ja.wikipedia.org/wiki/Emscripten)
- [Emscripten github](https://github.com/kripken/emscripten)
- [Emscripten Manual](http://kripken.github.io/emscripten-site/)
- [ArchLinux Manual](https://wiki.archlinuxjp.org/index.php/Rust)
- [RustでWebフロントエンド開発](http://qiita.com/_likr/items/daf46d6f66bc31cc4810#webassembly)
- [LLVM](https://ja.wikipedia.org/wiki/LLVM)