🙆
RustからWebAssemblyをコンパイルしてDenoで動かす
某ゲーム開発入門の参考書を買ったのでまずは環境をセットアップしました。基本的には公式チュートリアルの通りですが、Denoを使用するにあたり一部修正した部分をまとめました。
ビルドにはwasm-packを使用しています。
インストール
それぞれ公式サイトにある方法を記載します。ディストリビューションによってはリポジトリに存在する場合があるので、そちらからインストールしてもOkです。
Rust
$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
$ rustup toolchain install stable
wasm-pack
$ cargo install wasm-pack
Deno
$ curl -fsSL https://deno.land/x/install/install.sh | sh
プロジェクトの作成&ビルド
Rustのライブラリプロジェクトを作成し、コードと依存関係を編集します。中身の説明については公式のチュートリアルを参照ください。とりあえずは#[wasm_bindgen]
がついている関数が使えるようになるという雑な理解で大丈夫です。
$ cargo new --lib hello-wasm
Created library `hello-wasm` project
$ cd hello-wasm
$ tree
├── Cargo.toml
└── src
└── lib.rs
src/lib.rs
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
extern {
pub fn alert(s: &str);
}
#[wasm_bindgen]
pub fn greet(name: &str) {
alert(&format!("Hello, {}!", name));
}
#[wasm_bindgen]
pub fn square(x: u32) -> u32 {
x * x
}
Cargo.toml
[package]
name = "hello-wasm"
version = "0.1.0"
authors = ["Your Name <you@example.com>"]
description = "A sample project with wasm-pack"
license = "MIT/Apache-2.0"
repository = "https://github.com/yourgithubusername/hello-wasm"
edition = "2018"
[lib]
crate-type = ["cdylib"]
[dependencies]
wasm-bindgen = "0.2"
その後、wasm-pack
コマンドでビルドします。
この時、--target
オプションでビルドターゲットを設定します。今回はDenoで実行するためdeno
に設定してください。web
やbundler
の場合でも、*.rs
やCargo.toml
ファイルの中身は共通で使用できます。
オプション | 内容 |
---|---|
bundler |
デフォルト。Webpackハンドラーとしてロードする |
web |
Webブラウザで直接ロードする |
nodejs |
Nodejsのモジュールとしてロードする |
deno |
Denoモジュールとしてロードする |
no-module |
web に近いがESモジュールを使用しない |
--out-dir
, --out-name
オプションはなくても動きますが、覚えておくとDenoプロジェクト内で使用するのに便利です。詳しくはwasm-pack build --help
を確認ください。
$ wasm-pack build --target deno --out-dir pkg --out-name wasm
[INFO]: 🎯 Checking for the Wasm target...
[INFO]: 🌀 Compiling to Wasm...
Compiling proc-macro2 v1.0.66
...
Compiling hello-wasm v0.1.0 (/home/user/Deno/hello-wasm)
Finished release [optimized] target(s) in 3.22s
[INFO]: ⬇️ Installing wasm-bindgen...
[INFO]: Optimizing wasm binaries with `wasm-opt`...
[INFO]: ✨ Done in 3.48s
[INFO]: 📦 Your wasm pkg is ready to publish at /home/user/Deno/hello-wasm/pkg.
$ tree
├── Cargo.lock
├── Cargo.toml
├── pkg
│ ├── wasm.d.ts
│ ├── wasm.js
│ ├── wasm_bg.wasm
│ └── wasm_bg.wasm.d.ts
├── src
│ └── lib.rs
└── target
├── CACHEDIR.TAG
├── debug
├── release
└── wasm32-unknown-unknown
Denoで実行
出力されたjsファイルを呼び出して実行します。
main.ts
import { greet, square } from "./pkg/wasm.js";
greet("John");
const x = 4;
console.log(`square ${x} is ` + square(x));
$ deno run -A hello-wasm.ts
Hello, John! [Enter]
square 4 is 16
参考
Discussion