First install rustup
:
rustup install stable
rustup default stable
"export PATH=$PATH:~/.cargo/bin" >> ~/.zshrc
First we need to run:
rustup target add wasm32-unknown-unknown # add target
cargo install wasm-gc # to compress .wasm files
cargo new --lib rust-wasm
cd rust-wasm
Update Cargo.toml
:
[package]
name = "rust-wasm"
version = "0.1.0"
authors = ["Your Name <you@example.com>"]
description = "A sample project with wasm-pack"
repository = "https://github.com/myusername/myrepo"
edition = "2021"
[lib]
crate-type = ["cdylib"]
[dependencies]
Update src/lib.rs
:
#[no_mangle]
pub extern "C" fn add_one(x: i32) -> i32 {
x + 1
}
And build:
cargo build --target wasm32-unknown-unknown --release # build
ls -la target/wasm32-unknown-unknown/release/rust_wasm.wasm # checkout the file
wasm-gc target/wasm32-unknown-unknown/release/rust_wasm.wasm # compressing
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>title</title>
<script>
fetch("target/wasm32-unknown-unknown/release/rust_wasm.wasm")
.then((response) => response.arrayBuffer())
.then((bytes) => WebAssembly.instantiate(bytes, {}))
.then((wasm) => {
console.log("The answer is: ", wasm.instance.exports.add_one(13));
});
</script>
</head>
<body>
</body>
</html>
Notes
- All communication between the WebAssembly module and host must happen with extern functions. This means that there's only a limited number of types that can be used, mostly primitive types (integers, floats, booleans and pointers). You won't be able to pass complex types unless you're using an additional layer of abstraction on top (which is what
wasm-bindgen
does). - Large parts of the standard library (including file systems and networking, for instance) is not supported by the
wasm32-unknown-unknown
target. If your WebAssembly host supports WASI (WebAssembly System Interface), you can use thewasm32-wasi
target instead to compile a module with WASI support, which supports much more of the standard library.
Build for WASI
rustup target add wasm32-wasi # install target
cargo build --target wasm32-wasi --release # build for target
Update index.html
:
fetch("target/wasm32-unknown-unknown/release/rust_wasm.wasm")
cargo new --lib rust-wasm-pack
Update 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));
}
Update Cargo.toml
:
[package]
name = "rust-wasm-pack"
version = "0.1.0"
authors = ["Your Name <you@example.com>"]
description = "A sample project with wasm-pack"
repository = "https://github.com/myusername/myrepo"
edition = "2021"
[lib]
crate-type = ["cdylib"]
[dependencies]
wasm-bindgen = "0.2"
And then generate the package
wasm-pack build --target web
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>rust-wasm-pack example</title>
</head>
<body>
<script type="module">
import init, {greet} from "./pkg/rust_wasm_pack.js";
init()
.then(() => {
greet("WebAssembly")
});
</script>
</body>
</html>
Serve the site:
python3 -m http.server
First install clang
.
Create a file called add.cpp
:
#define WASM_EXPORT __attribute__((visibility("default"))) extern "C"
WASM_EXPORT int add(int x, int y) {
return x + y;
}
Compile with clang:
clang++ add.cpp --target=wasm32 --no-standard-libraries -Wl,--export-all -Wl,--no-entry -o add.wasm
And then create a
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>c-clang wasm example</title>
<script>
fetch("add.wasm")
.then((response) => response.arrayBuffer())
.then((bytes) => WebAssembly.instantiate(bytes, {}))
.then((wasm) => {
console.log("The answer is: ", wasm.instance.exports.add(21, 22));
});
</script>
</head>
<body></body>
</html>
<!-- Please take a look at -->
<!-- https://depth-first.com/articles/2019/10/16/compiling-c-to-webassembly-and-running-it-without-emscripten/ -->
(Install Emscripten.)[https://emscripten.org/docs/getting_started/downloads.html]
Create a hello.c
:
#include <stdio.h>
#include <emscripten/emscripten.h>
EMSCRIPTEN_KEEPALIVE void hello(){
printf("Hello Woraald\n");
}
int main() {
hello();
}
Compile!
emcc hello.c -s WASM=1 -o index.html --shell-file html_template/shell_minimal.html