DELAEMON BLOG

Live as if you were to die tomorrow. Learn as if you were to live forever.

WebAssembly with Rust

環境

必要物のバージョン確認

$ python --version; node -v; git --version; java -version; gcc --version; g++; cmake
Python 3.6.1
v8.9.1
git version 2.10.1
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF-8
java version "1.8.0_65"
Java(TM) SE Runtime Environment (build 1.8.0_65-b17)
Java HotSpot(TM) 64-Bit Server VM (build 25.65-b01, mixed mode)
Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 9.0.0 (clang-900.0.38)
Target: x86_64-apple-darwin17.3.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
clang: error: no input files
Usage

  cmake [options] <path-to-source>
  cmake [options] <path-to-existing-build>

Specify a source directory to (re-)generate a build system for it in the
current working directory.  Specify an existing build directory to
re-generate its build system.

Run 'cmake --help' for more information.

ecmascriptenインストール

$ git clone https://github.com/juj/emsdk.git
$ cd emsdk
$ source ~/emsdk/emsdk_env.sh
$ ./emsdk install sdk-incoming-64bit binaryen-master-64bit
$ ./emsdk activate sdk-incoming-64bit binaryen-master-64bit
  • emsdkコマンドはどうでもいいところがうまく動かなくてテキトウにいじった。ただのpython

とりあえずRustなしでWebAssemblyをお試し

Hello World
$ cat hello.c 
#include <stdio.h>

int main() {
  printf("Hello world!");
  return 0;
}
コンパイル / Webサーバーを起動して確認
$ emcc -o hello.html -s WASM=1 hello.c -s NO_EXIT_RUNTIME=0

$ ls 
hello.c hello.html hello.js hello.wasm

$ emrun hello.html
cppでフィボナッチ
$ cat fib.cpp
#include <iostream>
#include <iomanip>
using namespace std;

int fib(int n) {
    if (n < 2) return n;
    return fib(n - 1) + fib(n - 2);
}

int main(int argc, const char* argv[]) {
    int n = 10000;
    int i = fib(n);
    std::cout << "n: " << n << " i: " << i << endl;
    return 0;
}

$ emcc -o fib.html -s WASM=1 fib.cpp -s NO_EXIT_RUNTIME=0
$ emrun fib.html
  • n を10000000とか大きくするとコンパイル通るけど、ブラウザで Maximum call stack size exceeded

RustでWebAssembly

古いRustを消す
$ /usr/local/lib/rustlib/uninstall.sh
Rustインストール
$ curl https://sh.rustup.rs -sSf | sh
Rust で Hello World
$ cargo new --bin hello
$ cd hello
$ cat src/main.rs
fn main() {
    println!("Hello, world!");
}

$ cargo run
Hello, world!
Rust で フィボナッチ
$ cargo new --bin fib
$ cat src/main.rs
pub fn fibonacci_reccursive(n: i32) -> u64 {
    if n < 0 {
        panic!("{} is negative!", n);
    }
    match n {
        0     => panic!("zero is not a right argument to fibonacci_reccursive()!"),
        1 | 2 => 1,
        3     => 2,
        /*
         * 50 => 12586269025,
         */
        _     => fibonacci_reccursive(n - 1) + fibonacci_reccursive(n - 2)
    }
}

fn main() {
    let found = fibonacci_reccursive(10);
    println!("{}", found);
}

$ cargo run
55
Rustでasmjsコンパイル
$ rustup target add asmjs-unknown-emscripten
$ cargo build --target asmjs-unknown-emscripten
$ ls fib/target/asmjs-unknown-emscripten/debug/ 
build       deps        examples    fib.d       fib.js      incremental native
ブラウザから確認
$ cat fib_rust.html
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8"/>
        <title>Rust to asm.js example</title>
    </head>
    <body>
        <script src="fib/target/asmjs-unknown-emscripten/debug/fib.js"></script>
    </body>
</html>

$ php -S localhost:8080