Posted at
ClassiDay 19

MacOSXでWebAssemblyを触ってみた

More than 1 year has passed since last update.

Classi Advent Calendar 2016 19日目です。

2日続けて翌日に投稿です。ぐへぇ。


書いてあること

下記ページなどを参考にWebAssemblyに少し触ってみました。

WebAssemblyを試してみた

sexpr-wasmがwast2wasmになっていたりと、所々変更されているようです。

現時点で、手元の環境(MacOSX 10.10.5)で試した結果を書き記しておきます。


WebAssemblyについて

WebAssembly自体については、本家ドキュメントなど。

本家ドキュメント

こちらも大変勉強になりました。

ゼロからはじめるWebAssembly入門

高速化の観点など諸々ありますが、

個人的には色々な言語でブラウザ上で動作するアプリケーションを書けるようになる世界にワクワクしております。

(移植は大変そうだけど...)


環境の用意


Google Chrome Canary

こちらからダウンロードしてインストール

ブラウザを開いたらアドレスバーからchrome://flags/#enable-webassemblyへアクセスしてWebAssemblyの機能を有効にする。


llvm

$ brew edit llvm #cmakeのオプションに"-DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD=WebAssembly"を追加

$ brew install llvm --HEAD
$ export PATH=/usr/local/opt/llvm/bin:$PATH


clang

上記のインストールで/usr/local/opt/llvm/bin内に展開されているはず

$ clang -v

clang version 4.0.0 (http://llvm.org/git/clang.git b917c327ed880036a94aeb325aee20297a33702f) (http://llvm.org/git/llvm.git d6878955b884c7965b40208836e96bfa22cac580)
Target: x86_64-apple-darwin14.5.0
Thread model: posix
InstalledDir: /usr/local/opt/llvm/bin


binaryen

$ cd /usr/local/src

$ git clone https://github.com/WebAssembly/binaryen.git
$ cd binaryen/
$ cmake . && make
$ export PATH=/usr/local/src/binaryen/bin:$PATH


wabt(旧称sexpr-wasm-prototype)

$ cd /usr/local/src

$ git clone --recursive https://github.com/WebAssembly/wabt
$ cd wabt/
$ make
$ export PATH=/usr/local/src/wabt/out:$PATH


触ってみる


1.Cのコードを用意

# sample.c

int fact(int n) {
if (n == 0) {
return 1;
} else {
return n * fact(n - 1);
}
}


2.CのコードをWebAssemblyのバイトコードへ変換

$ clang -emit-llvm --target=wasm32 -S sample.c        # Cのコード→LLVM IR(sample.ll)

$ llc sample.ll -march=wasm32 # LLVM IR → アセンブリ(sample.s)
$ s2wasm --allocate-stack 1000 sample.s > sample.wast # アセンブリ → S式(sample.wast)
$ wast2wasm sample.wast -o sample.wasm # S式 → WebAssemblyバイトコード


3.HTMLソースの用意

JavaScriptからのバイトコードの解析のため、

以前はWasm.instantiateModule()というようなWebAssembly用のメソッドを利用していたようだけど、

手元で利用するとReferenceError: WASM is not definedと怒られてしまいました。

こちらのページによるとWebAssembly.Instance()を代わりに使えとのこと。

#sample.html

<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>WebAssembly</title>
<script>
fetch('sample.wasm')
.then(response => response.arrayBuffer())
.then(buffer => WebAssembly.compile(buffer))
.then(module => {
const instance = new WebAssembly.Instance(module);
//0から10までの階乗計算結果をログ出力
for (var i = 0; i <= 10; i++) {
console.log(instance.exports.fact(i));
}
});
</script>
</head>
<body>
</body>
</html>


4.適当にHTTP鯖立てて動作確認する

2f3eb76a29186923163f616f0640a0f4.png

OK!


最後に

今すぐ何かに使えるようなモノではないかもしれませんが、

今後、やれる事や対応言語が増えていけば、どんどん楽しくなりそうです。

(流行るといいなあ)