若干周回遅れ感ありますが、
Firefox,Chromeのstableにwasmがきたということで、
休日を使ってトライしてみました。
パッケージ管理やCI/CDを考えればcargo build一択だと思いますが、
一応rustcとcargoそれぞれでビルドする方法を確認しました。
なお、動作環境はmacOSです。
Setup
Rustとcmakeをインストール。
curl https://sh.rustup.rs -sSf | sh
rustup install stable
rustup default stable
rustup target add wasm32-unknown-emscripten
rustc --version
brew install cmake
cmake --version
Emscriptenをインストール。
3,40分かかるので注意。
cd /usr/local/share
git clone https://github.com/juj/emsdk.git
emsdk/emsdk install sdk-incoming-64bit binaryen-master-64bit
emsdk/emsdk activate sdk-incoming-64bit binaryen-master-64bit
sudo ln -s $(pwd)/emsdk/emscripten/incoming/emcc /usr/local/bin/emcc
emcc -v
Build by cargo
cargo new --bin hello
cd hello/
cargo build --target=wasm32-unknown-emscripten
cd target/wasm32-unknown-emscripten/debug
python -m SimpleHTTPServer 8000
HTTPサーバーはなんでもお好きなものを。
cargo new
で新規プロジェクトの作成。
cargo build --target
ではtarget以下にアーキテクチャごとのディレクトリが作られ、
その中にhtml,js,wasmなどが生成されます。
今回はwasm32-unknown-emscripten
をaddしてるので同名のディレクトリが作られます。
ビルド時に--release
オプションを付けるとtarget/wasm32-unknown-emscripten/debug
でなく
target/wasm32-unknown-emscripten/release
にコードが配置されます。
ビルド後のファイル/ディレクトリ構成は以下。
.
├── Cargo.lock
├── Cargo.toml
├── src
│ └── main.rs
└── target
├── debug
│ │
│ (略)
│ │
└── wasm32-unknown-emscripten
└── debug
├── build
├── deps
│ ├── hello-e0a7964fe7e29b5e.asm.js
│ ├── hello-e0a7964fe7e29b5e.js
│ ├── hello-e0a7964fe7e29b5e.wasm
│ ├── liblibc-5dc7b85e748840b4.rlib
│ └── librand-c9d9fbdab2355ee4.rlib
├── examples
├── hello.d
├── hello.js
├── hello.wasm
├── incremental
├── index.html
└── native
Build by rustc
事前にファイルをいくつか用意しておきます。
fn main() {
println!("Hello world");
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<script>
var Module = {}
fetch('./main.wasm')
.then((response) => response.arrayBuffer())
.then((buffer) => {
Module.wasmBinary = buffer
var script = document.createElement('script')
script.src = "main.js"
document.body.appendChild(script)
})
</script>
</body>
</html>
インラインにfetch.thenを書いていますがこれはほぼイディオムで、
.wasm
はscriptタグではなくfetch経由でないと動作しないようです。
直接的なHTMLファイルOpenではなくSimpleHTTPServerなどでサーバを立てるのは、
このfetch(ネットワーク経由での.wasm
のロード)が必要なためです。
話を戻して、rustcでsrc/main.rs
をBuild、その後Webサーバを起動します。
rustc --target=wasm32-unknown-emscripten src/main.rs -o dist/main.js
cd dist/
python -m SimpleHTTPServer 8000
ビルド後のファイル/ディレクトリ構成はこんな感じ。
.
├── dist
│ ├── index.html
│ ├── main.0.o
│ ├── main.asm.js
│ ├── main.js
│ ├── main.metadata.o
│ └── main.wasm
└── src
└── main.rs
所感
ちょっとした動作テストや小さなモジュール程度ならrustcを使うのもアリかなと思いました。
少し前にトライしたときはどっかしらのセットアップに躓いてしまい頓挫していたのですが、
今回リベンジしたところemsdkを入れるのに時間がかかった以外はスムーズに作業を進められて幸せでした。