k41531

Rust 🦀 と Wasm の "Hello, World!"

本記事は、筆者がRustとWasmを学ぶために以下のドキュメントを読み進めた過程を記すものです。 最終的にライフゲームの完成を目指しますが、とりあえず今回はHello,World!までです。 https://rustwasm.github.io/docs/book/introduction.html#rust--and-webassembly-

RustとWasm

Rust

2022年現在とても人気のある言語。あらゆるLinuxコマンドのオルタナティヴの多くがRustで書かれている印象を受けます。いろいろ良い点があるが本筋ではないので省略、というより詳しくは知りません。

Wasm

WebAssembly。ウェブブラウザを含むあらゆる環境内で実行できるプログラミング言語。とても注目されています。よく見るサンプルがRustで書かれたプログラムをWasmにコンパイルしてブラウザで実行する。この記事でもそれをします。

セットアップ

用意するもの

Rustの基本的なツールチェイン

rustup,rustc,cargo

wasm-pack

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

ここで早速問題が発生。
使用しているのがM1のMacであるため以下のようなエラーが出てインストールできない。

wasm-pack-init: no precompiled binaries available for CPU architecture: arm64

Cargo installですれば良いらしい。

cargo install wasm-pack

参考記事
https://github.com/rustwasm/wasm-pack/issues/952#issuecomment-792838226

`cargo-generate

cargo install cargo-generate

nightllyじゃないと動かないっぽい
以下のコマンドを実行してから再度インストール。

rustup default nightly && rustup update

参考 https://stackoverflow.com/questions/69848319/unable-to-specify-edition2021-in-order-to-use-unstable-packages-in-rust

npm

パッケージマネージャ等を使ってインストール。もし既にインストールされている場合は最新版にアップデートする。

npm install npm@latest -g

私はバージョンマネージャーをnを使っているので、それでバージョンを切り替えました。

n install latest

Hello, World!

Rust&Wasmのプロジェクトテンプレートが用意されているので活用します。プロジェクト名が聞かれるので好きな名前を入力する。今回はチュートリアルに従ってwasm-game-of-life

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

構成ファイル

Cargo.toml

依存関係やメタデータを指定するファイル。

lib.rs

WebAssemblyにコンパイルするRustクレートのルートファイル。

utils.rs

wasmにコンパイルされたRustを使いやすくするためのユーティリティを提供するファイル。

プロジェクトをビルドする

wasm-pack build

ビルドで出力されたファイル。

wasm_game_of_life_bg.wasm

.wasmは、RustソースからコンパイルされてたWebAssemblyのバイナリファイル。

wasm_game_of_life.js

.jsは、wasm-bindgenによって生成され、DOMとJS関数をRustにインポートし、Wasm関数のAPIをJSに公開するためのJSグルーが含まれているファイル。

wasm_game_of_life.d.ts

.d.tsは、JSのグルーのためのTSの方宣言が含まれているファイル。

package.json

生成されてJSとWasmパッケージに関するメタデータが含まれている。npmを使ったプロジェクトで生成されるpackage.jsonと同じ。

Webページに落とし込む

npm init wasm-app www

🦀 Rust + 🕸 Wasm = ❤

www/package.json

webpackとwebpack-dev-serverとの依存関係、npmに公開されているhello-wasm-packの依存関係が事前に設定されている。

www/webpack.config.js

webpackとローカル開発サーバの設定ファイル。特にいじる必要はない。

www/index.html

Webページのルートとなるhtmlファイル。

www/index.html

Webページで使うJSのエントリーポイント。

依存関係のインストール

cd www
npm install

ローカルのwasmパッケージ(wasm-game-of-life)を使うように、package.jsonに依存関係を追加する。

 "dependencies": { "wasm-game-of-life": "file:../pkg" },

index.jsを編集して、wasm-game-of-lifeをインポートするようにさせる。

import * as wasm from "wasm-game-of-life";

wasm.greet();

新しい依存関係をインストール

npm install

ローカルで動かす

npm run start

エラーが発生

ERR_OSSL_EVP_UNSUPPORTED

nodeのv17で発生するエラーの模様。v16に落とすことでうまく動きました。
https://github.com/nodejs/node/blob/master/doc/changelogs/CHANGELOG_V17.md#openssl-30

n install 16

練習問題

greet関数が引数を受け取れるように変更し、自分の名前が表示されるように変更する。

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