MacOSXでWebAssemblyを触ってみた

  • 10
    Like
  • 0
    Comment

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!

最後に

今すぐ何かに使えるようなモノではないかもしれませんが、
今後、やれる事や対応言語が増えていけば、どんどん楽しくなりそうです。
(流行るといいなあ)