WebAssembly 入门教程 / 02 - 安装与工具链
02 - 安装与工具链
工欲善其事,必先利其器。选择合适的工具链是 Wasm 开发的第一步。
2.1 工具链概览
不同源语言对应不同的编译工具链:
| 源语言 | 工具链 | 包管理 | 适用场景 |
|---|---|---|---|
| C/C++ | Emscripten (emcc) | emsdk | 移植现有 C/C++ 库 |
| Rust | wasm-pack / cargo | Cargo | 高性能、内存安全模块 |
| AssemblyScript | asc | npm | TypeScript 风格、Web 前端 |
| Go | Go 编译器 | go | 服务端应用(体积较大) |
| C#/.NET | Blazor | dotnet | .NET 生态迁移 |
| Zig | Zig 编译器 | zig | 系统编程新选择 |
| C/C++ (通用) | WASI SDK | — | 非浏览器 Wasm 应用 |
工具链选型流程图
你要编译什么语言?
│
├── C/C++
│ ├── 目标是浏览器? → Emscripten
│ └── 目标是服务器/WASI? → WASI SDK + Clang
│
├── Rust
│ ├── 需要 JS 绑定? → wasm-pack
│ └── 纯 WASI 模块? → cargo + wasm32-wasi target
│
├── 类 TypeScript → AssemblyScript
│
└── Go → Go 原生编译器(GOOS=wasip1 或 js/wasm)
2.2 Emscripten(C/C++)
Emscripten 是将 C/C++ 编译为 WebAssembly 的最成熟工具链,底层使用 LLVM。
安装步骤
# 1. 克隆 emsdk 仓库
git clone https://github.com/emscripten-core/emsdk.git
cd emsdk
# 2. 安装最新版本
./emsdk install latest
./emsdk activate latest
# 3. 配置环境变量(每开新终端需执行,或加入 shell 配置)
source ./emsdk_env.sh
# 4. 验证安装
emcc --version
验证输出
emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 3.x.x
将 Emscripten 加入 PATH(永久生效)
# 在 ~/.bashrc 或 ~/.zshrc 中添加
source /path/to/emsdk/emsdk_env.sh > /dev/null 2>&1
快速测试
// hello.c
#include <stdio.h>
int main() {
printf("Hello, WebAssembly!\n");
return 0;
}
# 编译为 Wasm
emcc hello.c -o hello.html
# 在浏览器中打开
# hello.html — 完整 HTML 页面
# hello.js — JS 胶水代码
# hello.wasm — Wasm 二进制
# 仅生成 .wasm + .js(无 HTML)
emcc hello.c -o hello.js
# 生成独立 Wasm(无 JS 胶水)
emcc hello.c -o hello.wasm -s STANDALONE_WASM
Emscripten 常用编译选项
| 选项 | 说明 | 示例 |
|---|---|---|
-O0 ~ -O3 | 优化级别 | -O3 |
-s WASM=1 | 输出 Wasm(默认) | -s WASM=1 |
-s EXPORTED_FUNCTIONS | 导出函数列表 | -s EXPORTED_FUNCTIONS='["_add"]' |
-s EXPORTED_RUNTIME_METHODS | 导出运行时方法 | -s EXPORTED_RUNTIME_METHODS='["ccall","cwrap"]' |
-s MODULARIZE | 生成模块化 JS | -s MODULARIZE |
-s ALLOW_MEMORY_GROWTH | 允许内存增长 | -s ALLOW_MEMORY_GROWTH=1 |
--preload-file | 预加载文件到虚拟文件系统 | --preload-file assets/ |
-s STANDALONE_WASM | 仅输出 Wasm(无 JS) | -s STANDALONE_WASM |
2.3 Wasmtime(通用 Wasm 运行时)
Wasmtime 是 Bytecode Alliance 开发的高性能 Wasm 运行时,支持 WASI 和 Component Model。
安装
# Linux / macOS(一键安装脚本)
curl https://wasmtime.dev/install.sh -sSf | bash
# macOS (Homebrew)
brew install wasmtime
# 验证
wasmtime --version
快速测试
# 运行一个简单的 .wasm 文件
wasmtime hello.wasm
# 传入命令行参数
wasmtime run --dir . hello.wasm -- arg1 arg2
# 预览 WASI 模块
echo '(module)' > empty.wat
wasmtime empty.wat
Wasmtime 配置文件
# wasmtime.toml
[module]
name = "my-module"
path = "target/wasm32-wasi/release/my_module.wasm"
[wasi]
args = ["arg1", "arg2"]
env = [["KEY", "VALUE"]]
2.4 wasm-pack(Rust)
wasm-pack 是 Rust 生态中最流行的 Wasm 构建工具,自动生成 JS 绑定和 npm 包。
安装
# 安装 wasm-pack
curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
# 验证
wasm-pack --version
添加 Rust Wasm 编译目标
# 添加 wasm32-unknown-unknown 目标(浏览器)
rustup target add wasm32-unknown-unknown
# 添加 wasm32-wasi 目标(WASI)
rustup target add wasm32-wasi
快速创建项目
# 使用 cargo-generate 模板
cargo install cargo-generate
cargo generate --git https://github.com/rustwasm/wasm-pack-template
# 或手动创建
mkdir my-wasm-lib && cd my-wasm-lib
cargo init --lib
wasm-pack 构建命令
# 构建(输出到 pkg/ 目录)
wasm-pack build
# 指定构建目标
wasm-pack build --target web # 浏览器 ESM
wasm-pack build --target nodejs # Node.js
wasm-pack build --target bundler # Webpack/Vite 等
wasm-pack build --target no-modules # 无模块系统
# 指定优化级别
wasm-pack build --release
wasm-pack 输出结构
pkg/
├── my_wasm_lib_bg.wasm # Wasm 二进制
├── my_wasm_lib_bg.wasm.d.ts # Wasm 类型声明
├── my_wasm_lib.js # JS 绑定
├── my_wasm_lib.d.ts # TypeScript 类型声明
├── package.json # npm 包信息
└── README.md
2.5 AssemblyScript
AssemblyScript 是 TypeScript 的一个子集变体,专门设计用于编译到 WebAssembly。
安装
# 使用 npm 安装
npm install -g assemblyscript
# 或在项目中安装
npm init wasm-app
cd wasm-app
npm install --save-dev assemblyscript
# 验证
npx asc --version
快速创建项目
# 使用脚手架
npx create-assemblyscript my-project
# 手动创建
mkdir my-project && cd my-project
npm init -y
npm install --save-dev assemblyscript
项目配置
// package.json
{
"scripts": {
"build": "asc assembly/index.ts --outFile build/module.wasm --optimize",
"build:debug": "asc assembly/index.ts --outFile build/module.wasm --debug"
}
}
// asconfig.json
{
"extends": "assemblyscript/std/assembly.json",
"entries": ["assembly/index.ts"],
"options": {
"optimizeLevel": 3,
"shrinkLevel": 1,
"noAssert": false
}
}
快速测试
// assembly/index.ts
export function add(a: i32, b: i32): i32 {
return a + b;
}
export function fibonacci(n: i32): i32 {
if (n <= 1) return n;
return fibonacci(n - 1) + fibonacci(n - 2);
}
npx asc assembly/index.ts --outFile build/module.wasm --optimize
2.6 WASI SDK
WASI SDK 提供了一套标准的 sysroot 和工具链(基于 Clang),用于将 C/C++ 编译为 WASI 兼容的 Wasm 模块。
安装
# 下载最新版本(以 wasi-sdk-24 为例)
export WASI_VERSION=24
export WASI_VERSION_FULL=${WASI_VERSION}.0
wget https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-${WASI_VERSION}/wasi-sdk-${WASI_VERSION_FULL}-linux.tar.gz
# 解压
tar xvf wasi-sdk-${WASI_VERSION_FULL}-linux.tar.gz
# 设置环境变量
export WASI_SDK_PATH=$(pwd)/wasi-sdk-${WASI_VERSION_FULL}
# 验证
${WASI_SDK_PATH}/bin/clang --version
使用 WASI SDK 编译
# 编译 C 程序
${WASI_SDK_PATH}/bin/clang \
--target=wasm32-wasi \
--sysroot=${WASI_SDK_PATH}/share/wasi-sysroot \
-o hello.wasm \
hello.c
# 使用 wasmtime 运行
wasmtime hello.wasm
与 Emscripten 对比
| 特性 | Emscripten | WASI SDK |
|---|---|---|
| 目标环境 | 浏览器 + Node.js | WASI 运行时(Wasmtime 等) |
| 虚拟文件系统 | 完整支持 | POSIX 兼容 |
| 网络支持 | 有限 | WASI Socket |
| JS 互操作 | 内建支持 | 需额外处理 |
| 输出体积 | 通常较大(含 JS 胶水) | 较小 |
| 适用场景 | Web 前端 | 服务端/CLI/边缘计算 |
2.7 其他工具链
Wasmer
# 安装 Wasmer(另一个流行的 Wasm 运行时)
curl https://get.wasmer.io -sSfL | sh
# 运行 Wasm 模块
wasmer run hello.wasm
# 使用 Wasmer 包管理器
wasmer run python/python # 直接运行 Wasm 版 Python
WABT(WebAssembly Binary Toolkit)
# 提供 wabt 工具集:wat2wasm, wasm2wat, wasm-interp 等
# Ubuntu/Debian
sudo apt install wabt
# macOS
brew install wabt
# 验证
wat2wasm --version
Binaryen
# WebAssembly 优化工具集
# Ubuntu/Debian
sudo apt install binaryen
# macOS
brew install binaryen
# 优化 Wasm 文件
wasm-opt -O3 input.wasm -o output.wasm
Wasm-tools
# Rust 生态的 Wasm 工具集
cargo install wasm-tools
# 转换 WAT ↔ Wasm
wasm-tools parse hello.wat -o hello.wasm
wasm-tools print hello.wasm -o hello.wat
# 验证 Wasm 文件
wasm-tools validate hello.wasm
2.8 工具链一览表
| 工具 | 用途 | 语言/平台 | 安装方式 |
|---|---|---|---|
| Emscripten | C/C++ → Wasm | C/C++ | emsdk |
| wasm-pack | Rust → Wasm + JS 绑定 | Rust | cargo / curl |
| AssemblyScript | TypeScript 风格 → Wasm | AS | npm |
| WASI SDK | C/C++ → WASI Wasm | C/C++ | 下载 tarball |
| Wasmtime | Wasm 运行时 | — | curl / brew |
| Wasmer | Wasm 运行时 | — | curl |
| WABT | Wasm 二进制工具 | — | apt / brew |
| Binaryen | Wasm 优化器 | — | apt / brew |
| wasm-tools | Wasm 工具集 | — | cargo |
2.9 IDE 配置推荐
VS Code 插件
| 插件 | 用途 |
|---|---|
| WebAssembly | WAT 语法高亮 |
| rust-analyzer | Rust 智能提示 |
| AssemblyScript | AS 语法支持 |
| WASM Language Support | Wasm 文件预览 |
| CodeLLDB | Rust 调试器 |
调试工具
# 使用 Chrome DevTools 调试 Wasm
# 1. 打开 chrome://flags/#enable-webassembly-debug
# 2. 在 Sources 面板中可以直接查看 WAT 源码并设断点
# 使用 Wasmtime 调试
wasmtime -g hello.wasm # 启用 DWARF 调试信息
# 使用 wasm-objdump 查看 Wasm 结构
wasm-objdump -x hello.wasm # 查看段信息
2.10 环境验证脚本
保存为 check-env.sh,运行即可检查所有工具是否安装:
#!/bin/bash
echo "=== WebAssembly 工具链检查 ==="
check() {
if command -v $1 &> /dev/null; then
echo "✅ $1: $(${@:2})"
else
echo "❌ $1: 未安装"
fi
}
check emcc --version | head -1
check wasm-pack --version
check wasmtime --version
check wasmer --version
check wat2wasm --version
check wasm-opt --version
check wasm-tools --version
check rustc --version
check node --version
check npm --version
2.11 注意事项
⚠️ 版本兼容性:Wasm 规范在持续演进,不同工具链版本可能输出不同版本的 Wasm 二进制。遇到兼容性问题时,优先检查工具链版本。
⚠️ 环境变量:Emscripten 和 WASI SDK 需要在每次新开终端时设置环境变量,建议加入
~/.bashrc或~/.zshrc。
⚠️ 编译缓存:Emscripten 首次编译较慢(需要预编译 libc 等),后续会使用缓存。
2.12 扩展阅读
下一章:03 - 基础概念 — 理解 Wasm 的模块、内存、表等核心抽象。