Posted on

Rust+WebAssembly で Hello, World!

以前 Rust をはじめてみよう!という記事を書いた。今回は Rust + WebAssembly を使って Hello, World!の出力をやってみた。

WebAssembly について

まず WebAssembly とは何か。本家サイトの Overview をみてみる。ここにある通り、WebAssembly(WASM)は C/C++/Rust などの高級言語を使って開発をしバイナリ形式で動かすことができる。その為 Web 上で高速に動かすことができる。とりわけゲームなどの実行速度が求められるような分野で有効になる。Chrome、Firefox、Safari、Edgeで利用が可能。

WebAssembly (abbreviated Wasm) is a binary instruction format for a stack-based virtual machine. Wasm is designed as a portable target for compilation of high-level languages like C/C++/Rust, enabling deployment on the web for client and server applications.
https://webassembly.org/

よくデモに出てくる Unity を使った動画
https://webassembly.org/demo/Tanks/

Youtube動画

再生回数が一番多い動画をあげておく。2018年2月の動画ですごく分かりやすく説明されている。

Rust+WebAssembly のドキュメント

ここからは以下の記事を実際にやってみる。実際にほぼそのまま実行しているだけなので以下についてはリンクをチェックするだけでも良いです。
https://rustwasm.github.io/book/game-of-life/hello-world.html

事前準備

参考URL:https://rustwasm.github.io/book/game-of-life/setup.html

rustup を使って rust をインストールする

curl https://sh.rustup.rs -sSf | sh
source $HOME/.cargo/env

source $HOME/.cargo/envは .zshrc などに記述しておくとよい

wasm-pack インストール

wasm-pack を使うとビルド・テスト・公開などが簡単にできる

curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh

cargo-generate インストール

cargo-generate を入れるとcargo generateコマンドが使えるようになり、この後の Git リポジトリからのソース取得ができる

cargo install cargo-generate

npm インストール

最新の npm を入れておく

npm install npm@latest -g

サンプルプロジェクトのテンプレート

Hello, World!のサンプルプロジェクトを取得する

cargo generate --git https://github.com/rustwasm/wasm-pack-template
// プロジェクト名を聞かれるのでここはドキュメントの通り`wasm-game-of-life`とする

ドキュメントツリーは以下のようになる。ドキュメントにはないtestsが追加されていた。ここでsrc/lib.rsgreet関数の文字列が、Hello, wasm-game-of-life!となっているので一応Hello, World!と変えておく。

wasm-game-of-life
├── Cargo.toml
├── LICENSE_APACHE
├── LICENSE_MIT
├── README.md
├── src
│   ├── lib.rs
│   └── utils.rs
└── tests
    └── web.rs

wasm-packコマンドでビルドしてみる。rustcのバージョンが1.30以上でないとエラーが発生するけどrustup updateコマンドでアップデートすれば問題なく進められる。

wasm-pack build
| [1/9]   Checking `rustc` version...
Your version of Rust, '1.29', is not supported. Please install Rust version 1.30.0 or higher.

rustupを使ってrustcをアップデートする

rustup update

ビルドが完了するとpkgディレクトリができる

wasm-pack build
pkg
├── README.md
├── package.json
├── wasm_game_of_life.d.ts
├── wasm_game_of_life.js
└── wasm_game_of_life_bg.wasm

Webページを作成する為に以下のコマンドを実行する。するとあらたにwwwディレクトリができる。

npm init wasm-app www
npx: 1個のパッケージを3.137秒でインストールしました。
 Rust +  Wasm = ❤

wwwのドキュメントツリー

www
├── LICENSE-APACHE
├── LICENSE-MIT
├── README.md
├── bootstrap.js
├── index.html
├── index.js
├── package-lock.json
├── package.json
└── webpack.config.js

wwwディレクトリへ移動し依存関係をインストールする

npm install

pkgディレクトリへ移動し以下のコマンドを実行する

npm link
/usr/local/lib/node_modules/wasm-game-of-life -> /Users/satomasaki/Dev/taisa/wasm-game-of-life/pkg

更にwwwディレクトリへ移動して以下のコマンドを実行する

npm link wasm-game-of-life
/Users/satomasaki/Dev/taisa/wasm-game-of-life/www/node_modules/wasm-game-of-life -> /usr/local/lib/node_modules/wasm-game-of-life -> /Users/satomasaki/Dev/taisa/wasm-game-of-life/pkg

index.jsimport箇所のhello-wasm-packwasm-game-of-lifeに更新する

import * as wasm from "wasm-game-of-life";
wasm.greet();

実行しページを開いてみるとHello, World!が表示される。

npm run start

ソースを少し変更してみる

wasm-game-of-life/src/lib.rsgreet関数を以下のように少し変更しwasm-game-of-life/www/index.jsgreet関数の引数に文字列を入れてみると渡した文字列が出力される

#[wasm_bindgen]
pub fn greet(name: &str) {
    alert(&format!("Hello, {}!", name));
}
wasm.greet("wasm!");

Webサーバを立ち上げたままでもwasm-pack buildと実行するだけでソースが更新され動作確認をすることができる。

まとめ

本当に少し触っただけながら、便利なツールがちゃんとあって、ある程度形ができて慣れてくればそれほどストレスなく開発が進められそう。