第 39 期 - WebAssembly 开发语言与工具链概览
摘要
文章先介绍 WebAssembly 的发展情况、应用场景、优点和未来发展方向,接着详细阐述多种开发语言(如 C/C ++、Rust、Go 等)在 WebAssembly 生态中的情况,包括各自的特点、优势与局限性,还介绍了多种工具链(如 Emscripten、Binaryen 等)的功能、特性及局限等内容。
1. WebAssembly 概述
- WebAssembly 发展到 2.0 版本,相比 1.0 版本增加指令支持、对大容量内存更友好且向量指令提升复杂场景性能。
- 其应用场景广泛,涵盖 Web 端的视频渲染等和非 Web 端的 Serverless 等领域。
- 具有跨平台、高效、安全的优点,如可在多种架构运行且性能接近原生代码,代码在沙箱运行保障安全。
- 未来发展方向包括多线程支持、AI 相关应用和区块链智能合约编写执行等。
2. 开发语言生态
- C/C ++
- 拥有庞大用户群体和完备工具链,是 WebAssembly 生态的先行者。
- LLVM 已将 WebAssembly 添加为支持后端,WASI 标准使 WebAssembly 运行环境可获取系统 IO 能力,将能力拓展到非 Web 端。
- 大量使用系统调用的基础库可移植到 WebAssembly,下沉其能力到原生或系统层面。
- Rust
- 与 Emscripten 都由 Mozilla 负责,和 WebAssembly 社区发展关系紧密。
- Rust 编译器借助 LLVM 生成 WebAssembly 产物,兼容 C/C ++内存模型且无 GC,产物体积小性能好,与 C/C ++的 WebAssembly 模块可无缝衔接。
- Rust 生态支持 WASI 标准,在 wasmtime 虚拟机加持下,在服务端应用大有可为。
- Go
- 从 Go 1.11 开始官方支持 WebAssembly,但存在问题。
- 不支持 WASI,导致其 WebAssembly 产物不能脱离 Web 环境,阻碍在服务端发展。
- GC 依赖使 WebAssembly 产物体积膨胀,难以做到 Web 端轻量化。
- AssemblyScript
- 使用部分修改后的 Typescript 语法,专为 WebAssembly 服务,适合前端开发者编写 WebAssembly 程序。
- 不支持 WASI 标准,生成的 WebAssembly 包含 GC,产物比 C/C ++生成的大。
- 底层借用 LLVM 能力,但内置库和生成的 WebAssembly 有待优化,如导入导出部分和 pow 库函数存在问题。
- JavaScript
- 是前端必备语言,WebAssembly 设计之初就考虑与 JavaScript 交互,有 JS - API 标准规范互操作。
- 由于语言特性难以生成完备的 WebAssembly 产物,不过有将 JavaScript 引擎编译到 WebAssembly 在服务端运行的例子,在 Serverless 和容器化场景有一定价值。
- 其他支持的语言
- 如 Lua 社区有将 Lua 引擎编译到 WebAssembly 的项目,可让 Lua 脚本在浏览器运行;C #社区有相关编译实验项目。
- 这些项目大多处于实验性质,存在限制,社区也处于初步发展阶段。
3. 工具生态
- Emscripten
- 概述:源于将 C/C ++编译生成的 LLVM IR 翻译成 JavaScript 的想法,后加入对 WebAssembly 的支持,可将多种基于 LLVM IR 的语言项目编译到 WebAssembly。
- 库支持:在 musl libc 和 LLVM libcxx 库基础上定制化,实现 WASI 标准接口,提供部分适配库,但仍不能完美迁移 C/C ++工程。存在多线程模拟开销大、计时误差大精度低、无法连接第三方静动态库等局限性。
- 编译:底层用 clang + wasm - ld 能力编译,开发 emcc 项目,基于 clang 提供大量编译选项,还引入 Closure Compiler 和 Binaryen 优化代码。
- 调试:能生成 JavaScript 和 HTML 代码,Chrome DevTool 可依据 DWARF 调试信息定位 C/C ++源码调试信息。
- Binaryen
- 目的是让编译到 WebAssembly 的工作简单、快速、有效。
- 简单体现在有简单 C API 和 JavaScript 中可用,接受多种输入;快速在于内部 IR 结构紧凑且完全并行代码生成和优化;有效表现在更关注 WebAssembly 特性相关优化。
- 可作为编译器后端和编译工具链,有自己的 Binaryen IR,可接收多种输入格式,包含多个优化过程,还提供多种工具如 wasm - opt 等,支持 DWARF 格式调试信息并可与 Emscripten 集成调试。
- wasi - sdk
- 可看作魔改后的 LLVM,添加 WASI 支持,使用方式类似 clang 编译 C/C ++项目,libc 实现与 Emscripten 相似,存在多线程、time 能力缺失等局限。
- TinyGo
- 轻量级 Go 编译器,用于嵌入式系统、WebAssembly 和命令行等轻量级环境,复用 Go language tools 和 LLVM,在部分 Go WebAssembly Serverless 函数服务中有应用。
- wabt
- 工具链集合,包含 WebAssembly 反汇编工具、解释器、编译器、验证工具等,如 wasm2wat 和 wat2wasm 用于二进制和文本格式转换,wasm2c 可将二进制文件转换为 C 源文件和头文件。
- wasm - pack
- 由 Rust / WebAssembly 工作组开发维护,可将代码打包成 npm 模块,随附 Webpack 插件,便于与 JavaScript 应用结合。
- wasm - bindgen
- 让 WebAssembly 模块和 JavaScript 交互,主要关注 Rust 生态,功能包括导入 JavaScript 能力到 Rust、导出 Rust 功能到 JavaScript 等。
4. 总结
- 介绍了多种编程语言和工具,如 C/C ++、Go、Rust 等语言及其提供的 WebAssembly 编译和打包功能。
- 不同语言和工具可根据不同场景实现 WebAssembly 相关操作,随着 WebAssembly 受关注程度增加,各主流编程语言和社区都重视它,还有新语言被设计出来,这些语言和工具都是为实际应用开发场景服务的。
扩展阅读
Made by 捣鼓键盘的小麦 / © 2025 Front Talk 版权所有