5
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Rust で WebAssembly を書いて Deno で実行する

5
Last updated at Posted at 2020-07-02

TL;DR

cargo generate --git https://github.com/rustwasm/wasm-pack-template -n myproject
cd myproject

wasm-pack build --target web --out-name index

echo "import * as pkg from './pkg/index.js'
await pkg.default()
pkg.greet()" >| app.ts
deno run --allow-read app.ts

Hello, myproject! と表示されたら成功です。

プロジェクトの作成

cargo generate --git https://github.com/rustwasm/wasm-pack-template -n myproject
cd myproject

command not found: cargo

cargo は Rust 用の便利なコマンドです。
rustup をインストールするとついてきます。

error: no such subcommand: generate

cargo-generate はテンプレートをもとにプロジェクトを初期化(ファイルを作成)してくれます。
今回の場合は https://github.com/rustwasm/wasm-pack-template から src と Cargo.toml をコピペするだけでも代用できます。

インストールするならこちらを参考に

Rust を書く

追記 2020/11/12

Deno v1.5.0 で alert が追加されたので、このセクションは飛ばしても大丈夫です
https://github.com/denoland/deno/releases/tag/v1.5.0

sed -i -e "s/fn alert(s: &str);/#[wasm_bindgen(js_namespace = console, js_name = log)] fn alert(s: \\&str);/" src/lib.rs

初期化時点で js の alert を呼び出す処理が書かれていますが
deno に alert はないので代わりに console.log を呼ぶように編集しています。

  #[wasm_bindgen]
  extern "C" {
-   fn alert(s: &str);
+   #[wasm_bindgen(js_namespace = console, js_name = log)] fn alert(s: &str);
  }

WebAssembly を作成

wasm-pack build --target web --out-name index
sed -i -e "s#input = import\\.meta\\.url\\.replace(/\\\\\\.js$/, '_bg\\.wasm');#input = import.meta.url.replace(/\\\\.js$/, '_bg.wasm'); if ('undefined' !== typeof Deno) input = new WebAssembly.Module(await Deno.readFile(new URL(input).pathname));#" pkg/index.js

追記 2021/12/20

Deno v1.16.0 でローカルのファイルの fetch が追加されたので、 sed の実行が不要になりました。
https://github.com/denoland/deno/releases/tag/v1.16.0

deno はブラウザとの互換性を重視しています。
将来的には wasm-pack build --target web だけで問題なく動くようになるのではないかと思います。

現状でも wasm-pack で作成したライブラリを web サーバーにおけば動くと思うのですが
ローカルで作成・実行までやろうとすると
ローカルのファイルを fetch で取ろうとして( fetch('file:///user/rithmety/myproject/pkg/index_bg.wasm') )エラーが発生します。
deno が file:// を fetch できるようにする計画はあるようです。

今回はランタイムを直に編集して対応しています。
( Windows だと new URL(input).pathname の部分が期待通りに動かないかもしれません。 )

  async function init(input) {
    if (typeof input === 'undefined') {
-     input = import.meta.url.replace(/\.js$/, '_bg.wasm');
+     input = import.meta.url.replace(/\.js$/, '_bg.wasm'); if ('undefined' !== typeof Deno) input = new WebAssembly.Module(await Deno.readFile(new URL(input).pathname));
    }

command not found: wasm-pack

wasm-pack をインストールしてください。

deno で実行してみる

echo "import * as pkg from './pkg/index.js'
await pkg.default()
pkg.greet()" >| app.ts
deno run --allow-read app.ts

deno はトップレベルの await に対応しているのでシンプルに書けます。

import * as pkg from './pkg/index.js'
await pkg.default()
pkg.greet()

Hello, myproject! と表示されたら成功です。

command not found: deno

deno をインストールしてください。

参考

wasm-pack の公式マニュアル を参考にしました。

5
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?