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と実行するだけでソースが更新され動作確認をすることができる。

まとめ

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

Posted on

Rust をはじめてみよう!

Rust をはじめてみよう!ということで Rust をはじめてみました。

Rust ってなに?

Rust言語は速度、並行性、安全性を言語仕様として保証するC言語、C++に代わるシステムプログラミング(英語版)に適したプログラミング言語を目指している[4]。2006年の開発初期はグレイドン・ホアレの個人プロジェクトだったが、2009年にMozillaが開発に関わり始めてMozilla Researchの公式プロジェクトとなった
参考 : Rust (プログラミング言語) – Wikipedia

また、公式ドキュメントが充実しているのでそちらをみれば大体分かるようになっています。

特徴

  • ゼロコスト抽象化
  • ムーブセマンティクス
  • 保証されたメモリ安全性
  • データ競合のないスレッド
  • トレイトによるジェネリクス
  • パターンマッチング
  • 型推論
  • 最小限のランタイム
  • 効率的なCバインディング

インストール

rustup を使ってインストールします。

$ curl https://sh.rustup.rs -sSf | sh

実行すると以下のように言われるので設定を反映させます。

To get started you need Cargo's bin directory ($HOME/.cargo/bin) in your PATH
environment variable. Next time you log in this will be done automatically.
To configure your current shell run source $HOME/.cargo/env
$ cargo
command not found: cargo
$ source $HOME/.cargo/env
$ cargo --version
cargo 1.29.0 (524a578d7 2018-08-05)

rustc というのコンパイラもインストールされます。

$ rustc --version
rustc 1.29.1 (b801ae664 2018-09-20

rustc を使って Hello, World!

まずは rustc を使って Hello, World! を実行してみます。


$ mkdir hello_rust
$ cd hello_rust
$ vi hello.rs
fn main() {
    println!("Hello, world!)
}

ファイルを作成したら rustc を使ってコンパイルし実行すると 「Hello, world!」 が出力されます。

$ rustc hello.rs
$ ./hello
Hello, world!

Cargo を使って Hello, world!

実際のプロジェクトでは Cargo というパッケージマネージャーを使っていくことになると思います。Cargo を使って新しくプロジェクトを作成してみます。

$ cargo new hello_cargo
Created binary (application) `hello_cargo` project

ディレクトリツリーは以下のようになっています。

hello_cargo
├── Cargo.toml
└── src
    └── main.rs

Cargo.toml ファイルがパッケージを管理するファイルです。

[package]
name = "hello_cargo"
version = "0.1.0"
authors = ["taisa "]
[dependencies]

デフォルトでは main.rs に 「Hello, world!」 を出力する実装がされているのでそのまま実行してみます。build コマンドはコンパイルのみで、run コマンドはコンパイルと実行が行われます。

# コンパイル
$ cargo build
   Compiling hello_cargo v0.1.0 (file:///Users/satomasaki/Dev/taisa/hello_cargo)
    Finished dev [unoptimized + debuginfo] target(s) in 1.99s
# コンパイルと実行
$ cargo run
   Compiling hello_cargo v0.1.0 (file:///Users/satomasaki/Dev/taisa/hello_cargo)
    Finished dev [unoptimized + debuginfo] target(s) in 1.33s
     Running `target/debug/hello_cargo`
Hello, world!

cargo は test コマンドも備えていて、test を実行することができます。(test 自体が存在しないのですべて0)

$ cargo test
   Compiling hello_cargo v0.1.0 (file:///Users/satomasaki/Dev/taisa/hello_cargo)
    Finished dev [unoptimized + debuginfo] target(s) in 1.51s
     Running target/debug/deps/hello_cargo-666fd07beeac7bb5
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

サンプル集

Rust は公式ドキュメントが充実していてサンプル集などもあるので今後はそれらを参考にしてみます。
https://doc.rust-lang.org/rust-by-example/