LoginSignup
4
6

More than 5 years have passed since last update.

RustでWebアッセンぶる 入門(環境構築)編

Last updated at Posted at 2019-05-02

WEBエンジニア勉強会 #13 (東京都, 渋谷)にて10分LTをさせていただくことにしました。抽選なのでまだ未確定なのですが。

ネタは今考えてます。
というか最近気になっているwebassemblyというやつを触っておいてみようかなと。WEBエンジニア界隈だと認知度どんなもんなのか気になります。
どうやって個性を出すかはこれから。

WebAssemblyとは

wikipedia様によるとこんな感じでごわす

WebAssemblyは、ウェブブラウザのクライアントサイドスクリプトとして動作するプログラミング言語(低水準言語)である。wasmとも称されており、ブラウザ上でバイナリフォーマットの形で実行可能であることを特徴とする[2]。2017年現在開発が進められており、最初の目標としてCとC++からのコンパイルをサポートすることを目指している[3]他、Rustがバージョン1.14以降で[4]、Goがバージョン1.11以降で[5]、Kotlin/Nativeがバージョン0.4以降で[6]で対応するなど、他のプログラミング言語のサポートも進められている。
https://ja.wikipedia.org/wiki/WebAssembly

へー。kotlinも?知らんかった。
簡単に言うと、ブラウザでコンパイル済みのコードを動かす仕組みって事だと思う。
JSだとちょっとしんどいような時に使う想定なのでブラウザゲームとかで活用できるのかも。
Web(JS) + アセンブリ言語って感じ?

用語

Left align Right align
.wat "WebAssembly Text"。読める形式のwasmファイル
.wasm バイナリ形式のwasmファイル。

For reference, here is a factorial function in wat:

(module
  (func $fac (param f64) (result f64)
    get_local 0
    f64.const 1
    f64.lt
    if (result f64)
      f64.const 1
    else
      get_local 0
      get_local 0
      f64.const 1
      f64.sub
      call $fac
      f64.mul
    end)
  (export "fac" (func $fac)))

まずはやる

基本、みんなこれをやるみたいです。
Rust 🦀 and WebAssembly 🕸
https://rustwasm.github.io/docs/book/

setup

You will need the standard Rust toolchain, including rustup, rustc, and cargo.

当然ながらRustが使える環境が必要です。versionは1.3.0以上がいいらしいです。

$ rustc --version
rustc 1.34.1 (fc50f328b 2019-04-24)

ちなみにwin10Proでやります。

wasm-pack インストール

https://rustwasm.github.io/wasm-pack/installer/
からインストールします。
ちなみにrustupにPATHが通ってないと下記のように怒られます。つまりwindowsの場合とcmd上でPATHが通ってないと怒られる。

failed to find an installation of `rustup` in `PATH`, is rustup already installed?
Press enter to close this window...

なんで結局、rustupが通ってるgit-bashにてcurl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh を実行しました。
おまじない的に下記も。

$ cargo install cargo-generate
$ npm install npm@latest -g
$ npm --version
6.9.0

Clone the Project Template

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

チュートリアル通り、wasm-game-of-life っていうプロジェクト名にします。
構造はこんな感じ。

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

src/lib.rsっていうのがスクリプトの本体で、単にjsのalertを実行するだけっぽいです。

src/lib.rs
extern crate cfg_if;
extern crate wasm_bindgen;

mod utils;

use cfg_if::cfg_if;
use wasm_bindgen::prelude::*;

cfg_if! {
    // When the `wee_alloc` feature is enabled, use `wee_alloc` as the global
    // allocator.
    if #[cfg(feature = "wee_alloc")] {
        extern crate wee_alloc;
        #[global_allocator]
        static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
    }
}

#[wasm_bindgen]
extern {
    fn alert(s: &str);
}

#[wasm_bindgen]
pub fn greet() {
    alert("Hello, wasm-game-of-life!");
}

#[wasm_bindgen] ってマクロがwasmでfunction使うための儀式なのかな。

Build the Project

さっきまでのはバックエンド側(・・という言い方もちょっと違うのかな?)。
お次はフロント部分です。nodejsの部分すね。

プロジェクトのディレクトリにて下記を実行

$ wasm-pack build

なんかwarning: function is never used: `set_panic_hook`っていう警告が出たりはしましたが、pkgディレクトリというのが作られました。

wasm-game-of-life/
pkg/
├── package.json
├── README.md
├── wasm_game_of_life_bg.wasm
├── wasm_game_of_life.d.ts
└── wasm_game_of_life.js

Putting it into a Web Page

いよいよ動かしてみる。
まず、webページのテンプレを作る。
プロジェクトのディレクトリで実行します。

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

(カニ+蜘蛛の巣=ハートって何やねん。巣に引っかかっとるがな。)

お次はwwwディレクトリができました。

wasm-game-of-life/
www/
├── bootstrap.js
├── index.html
├── index.js
├── LICENSE-APACHE
├── LICENSE-MIT
├── package.json
├── README.md
└── webpack.config.js

ちなみにindex.jsはこんな感じ。

www/index.js
import * as wasm from "hello-wasm-pack";

wasm.greet();

お次はnpmフォルダでnpm install をして依存モジュールを入れておきます。
その次はpkgフォルダでnpm link 実行しろとあるので実行します。
プロジェクトフォルダ外のモジュールにlinkを張るのかな。

$ npm link
npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN wasm-game-of-life@0.1.0 No repository field.
npm WARN wasm-game-of-life@0.1.0 No license field.

up to date in 0.351s
found 0 vulnerabilities

C:\Users\user\AppData\Roaming\npm\node_modules\wasm-game-of-life -> C:\r\wasm-game-of-life\pkg

さらにはwwwフォルダで以下を。

$ npm link wasm-game-of-life
C:\r\wasm-game-of-life\www\node_modules\wasm-game-of-life -> C:\Users\user\AppData\Roaming\npm\node_modules\wasm-game-of-life -> C:\r\wasm-game-of-life\pkg

最後にwww/index.jsをmodifyします。

www/index.js
import * as wasm from "wasm-game-of-life";

wasm.greet();

Serving Localy

いよいよ実行です。
ただただalert()を実行するだけなのに長旅でした。

$ npm run start

> create-wasm-app@0.1.0 start C:\r\wasm-game-of-life\www
> webpack-dev-server

i 「wds」: Project is running at http://localhost:8080/
i 「wds」: webpack output is served from /
i 「wdm」: Hash: 6571fe1da17c92a46098
Version: webpack 4.30.0
Time: 742ms
Built at: 2019-05-02 19:00:28
                           Asset          Size  Chunks             Chunk Names
                  0.bootstrap.js      3.55 KiB       0  [emitted]
7144487deacc988b3b63.module.wasm  unknown size       0  [emitted]
                    bootstrap.js       355 KiB    main  [emitted]  main
                      index.html     175 bytes          [emitted]
Entrypoint main = bootstrap.js
[0] multi (webpack)-dev-server/client?http://localhost ./bootstrap.js 40 bytes {main} [built]
[../pkg/wasm_game_of_life.js] 981 bytes {0} [built]
[./bootstrap.js] 279 bytes {main} [built]
[./index.js] 58 bytes {0} [built]
[./node_modules/ansi-html/index.js] 4.16 KiB {main} [built]
[./node_modules/events/events.js] 13.3 KiB {main} [built]
[./node_modules/loglevel/lib/loglevel.js] 7.68 KiB {main} [built]
[./node_modules/querystring-es3/index.js] 127 bytes {main} [built]
[./node_modules/url/url.js] 22.8 KiB {main} [built]
[./node_modules/webpack-dev-server/client/index.js?http://localhost] (webpack)-dev-server/client?http://localhost 8.26 KiB {main} [built]
[./node_modules/webpack-dev-server/client/overlay.js] (webpack)-dev-server/client/overlay.js 3.59 KiB {main} [built]
[./node_modules/webpack-dev-server/client/socket.js] (webpack)-dev-server/client/socket.js 1.05 KiB {main} [built]
[./node_modules/webpack-dev-server/node_modules/strip-ansi/index.js] (webpack)-dev-server/node_modules/strip-ansi/index.js 161 bytes {main} [built]
[./node_modules/webpack/hot sync ^\.\/log$] (webpack)/hot sync nonrecursive ^\.\/log$ 170 bytes {main} [built]
[./node_modules/webpack/hot/emitter.js] (webpack)/hot/emitter.js 75 bytes {main} [built]
    + 14 hidden modules
i 「wdm」: Compiled successfully.

http://localhost:8080/を開く...

106.png

でけた!
長くなったのでここでひとまず切ります。
次回は実践編・・か?何しよう。

・・・・・・

チュートリアルすっとばして下記をcloneして実行してみたらこんな感じな奴ができてました。
なんか虫が蠢いてるみたい。。canvasにいろいろ書いてるんすね。
https://github.com/rustwasm/wasm_game_of_life

1.gif

ネタ、思いついたかも。

4
6
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
4
6