Zig 是一种通用编程语言和工具链,用于维护健壮、优化和可重用的软件,Zig 支持开箱即用的 Webassembly 构建,Zig 的实现是通过使用 LLVM 来提供编译目标,对Webassembly System Interface(WASI) 的支持尚处于积极开发中,可以参见官方文档

Zig 从 0.4.0 开始提供对 WebAssembly 的实现

Webassembly

WebAssembly 是一种运行在现代网络浏览器中的新型代码,并且提供新的性能特性和效果。它设计的目的不是为了手写代码而是为诸如 C、C++和 Rust 等低级源语言提供一个高效的编译目标。

Webassembly 1.0 已经在4个主要浏览器引擎中发布Roadmap

为了进一步推动模块化 WebAssembly 生态系统,Mozilla、Fastly、英特尔和红帽公司携手成立了ByteCode Alliance(字节码联盟)。ByteCode Alliance 是一个非营利组织,致力于在 WebAssembly 和 WebAssembly System Interface(WASI) 等标准的基础上创建安全的新软件基础。

Webassembly 的目标

作为 W3C WebAssembly Community Group 中的一项开放标准,WebAssembly 是为下列目标而生的:

  • 快速、高效、可移植——通过利用常见的硬件能力,WebAssembly 代码在不同平台上能够以接近本地速度运行。
  • 可读、可调试——WebAssembly 是一门低阶语言,但是它有确实有一种人类可读的文本格式(其标准即将得到最终版本),这允许通过手工来写代码,看代码以及调试代码。
  • 保持安全——WebAssembly 被限制运行在一个安全的沙箱执行环境中。像其他网络代码一样,它遵循浏览器的同源策略和授权策略。
  • 不破坏网络——WebAssembly 的设计原则是与其他网络技术和谐共处并保持向后兼容。

更多参见: MDN Webassembly概念

Zig 构建 Webassembly

1 life.zig 导出了三个函数

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// Advance the world by strong mutation
export fn advance() u32 {
    ....
    WORLD.cells = cell_buf;
    return num_changed;
}

export fn set_cell(index: u32) void {
    if (index > NUM_CELLS) return;
    WORLD.cells[index] = .Alive;
}

export fn get_char(index: u32) u32 {
    if (index > NUM_CELLS) return '◻';
    return switch (WORLD.cells[index]) {
        .Dead => {
            return '◻';
        },
        .Alive => {
            return '◼';
        },
    };
}

2 在 life.js 中会调用这些 WASM 导出的方法

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
  // Load WebAssembly module `life.wasm`
  // https://developer.mozilla.org/en-US/docs/WebAssembly/JavaScript_interface/instantiateStreaming
  Game = await WebAssembly.instantiateStreaming(
    fetch("life.wasm"), importObject
  )
  set_cell = Game.instance.exports.set_cell;
  advance = Game.instance.exports.advance;
  get_char = Game.instance.exports.get_char;
  wasm_loaed = true
  ...

3 在 index.html 加载life.js

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
<html lang="en">

<head>
  <title>Life Demo</title>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
</head>

<body>
  <input type="button" id="button" label="button" value="BUTTON" />
  <pre id="life_pre"></pre>
</body>
<script src="life.js"></script>

</html>

以上这些就是使用Zig 创建 WebAssemble 程序的代码。(非常感谢sleibrock/zigtoys)

4 构建 life.wasm

1
$ zig build-lib life.zig -target wasm32-freestanding -dynamic -rdynamic -O ReleaseSmall

更多构建说明参见 Ziglang.org

5 运行

启动一个本地web server:

1
$ python3 -m http.server

在浏览器中,浏览:http://localhost:8000 demo

参考

  1. Webassembly
  2. Webassembly developer guide
  3. MDN Webassembly
  4. Zig language Reference
  5. WebAssembly with Zig, Part 1
  6. WebAssembly With Zig, Pt. II
  7. ByteCode Alliance