将 Zig 编译为 wasm32-freestanding 时出错

问题描述

我正在尝试使用 wasm32-freestanding 目标将 Zig 函数编译为独立的 WebAssembly 模块。 official documentation 中有一个部分解释了如何执行此操作,但使用最新版本的 Zig (0.8.0) 时,我在尝试使用 JavaScript 实例化生成的模块时出错。

// file: main.zig
export fn add(a: i32,b: i32) i32 {
    return a +% b;
}
// file: test.js
WebAssembly.instantiate((function() {
    const source = require("fs").readFileSync("main.o");
    return new Uint8Array(source);
})(),{ env: {} }).then(wasm => {
    const add = wasm.instance.exports.add;
    console.log(add(1,2));
});
$ zig version
0.8.0
$ node --version
14.17.3
$ zig build-obj main.zig -target wasm32-freestanding -dynamic -OReleaseFast
$ wc -c main.o # the generated code has extension `.o` instead of `.wasm`
135
$ node test.js
(node:2449) UnhandledPromiseRejectionWarning: LinkError: WebAssembly.instantiate(): Import #0 module="env" function="__linear_memory" error: memory import must be a WebAssembly.Memory object
(Use `node --trace-warnings ...` to show where the warning was created)
(node:2449) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block,or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection,use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:2449) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future,promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

检查生成的 wasm 模块表明它尝试从范围 __linear_memory 导入名为 env 的值。这自然会失败,因为我没有提供这样的导入。但是,示例项目 zig-wasm-test 包含一个不包含这些导入的 WASM 模块(使用旧版本的 Zig 编译)。

在这里做错了什么?即使没有使用,我是否应该只向模块提供 __linear_memory 导出?

解决方法

您应该尝试使用 build-lib 而不是 build-obj