rustからWebAssemblyへコンパイル


はじめに

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

Emscriptenなしで、Rust単体でのwasmへのコンパイルが可能になりました。
wasm32-unknown-unknown landed & enabled

環境

  • 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を使用します)。
また、コンパイルの過程でcmakeを使用するので、同時にcmakeもインストールします。

$ yaourt -S rustup
$ yaourt -S emscripten
$ yaourt -S cmake

emscriptenとは?

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

環境設定

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

$ 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

ビルドしてみる

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

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

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

$ 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ファイルを使用してみます。
こちらの記事を参考にし、WebAssemblyの動作確認を行いました(有益な記事があり、ありがたいです!)。

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

まとめ

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

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

参考