强曰为道

与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

02 - 安装与工具链

02 - 安装与工具链

工欲善其事,必先利其器。选择合适的工具链是 Wasm 开发的第一步。


2.1 工具链概览

不同源语言对应不同的编译工具链:

源语言工具链包管理适用场景
C/C++Emscripten (emcc)emsdk移植现有 C/C++ 库
Rustwasm-pack / cargoCargo高性能、内存安全模块
AssemblyScriptascnpmTypeScript 风格、Web 前端
GoGo 编译器go服务端应用(体积较大)
C#/.NETBlazordotnet.NET 生态迁移
ZigZig 编译器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 对比

特性EmscriptenWASI SDK
目标环境浏览器 + Node.jsWASI 运行时(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 工具链一览表

工具用途语言/平台安装方式
EmscriptenC/C++ → WasmC/C++emsdk
wasm-packRust → Wasm + JS 绑定Rustcargo / curl
AssemblyScriptTypeScript 风格 → WasmASnpm
WASI SDKC/C++ → WASI WasmC/C++下载 tarball
WasmtimeWasm 运行时curl / brew
WasmerWasm 运行时curl
WABTWasm 二进制工具apt / brew
BinaryenWasm 优化器apt / brew
wasm-toolsWasm 工具集cargo

2.9 IDE 配置推荐

VS Code 插件

插件用途
WebAssemblyWAT 语法高亮
rust-analyzerRust 智能提示
AssemblyScriptAS 语法支持
WASM Language SupportWasm 文件预览
CodeLLDBRust 调试器

调试工具

# 使用 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 的模块、内存、表等核心抽象。