如何使用 emscripten 生成独立的 WebAssembly

Posted

技术标签:

【中文标题】如何使用 emscripten 生成独立的 WebAssembly【英文标题】:How to generate standalone webassembly with emscripten 【发布时间】:2018-08-28 09:10:10 【问题描述】:

documentation 提供两个选项:让优化器去除不必要的代码,然后用您自己的替换 .js 胶水,或者使用 SIDE_MODULE 标志。

这两个选项都会导致 memory 导入(而不是导出),并且在 SIDE_MODULE 的情况下,还定义了大量额外的导入/导出。

将其与Webassembly Studio 提供的干净输出进行比较:

(module
  (type $t0 (func))
  (type $t1 (func (result i32)))
  (func $__wasm_call_ctors (type $t0))
  (func $main (export "main") (type $t1) (result i32)
    i32.const 42)
  (table $T0 1 1 anyfunc)
  (memory $memory (export "memory") 2)
  (global $g0 (mut i32) (i32.const 66560))
  (global $__heap_base (export "__heap_base") i32 (i32.const 66560))
  (global $__data_end (export "__data_end") i32 (i32.const 1024)))

这里导出了内存,并提供了__heap_base,方便我们自己编写分配器。 Emscripten 输出不会导出任何此类值,因此我们不知道从哪里开始分配内存。

是否可以使用emcc 获得类似的输出?

更新:似乎静态/堆栈大小由 emcc 内部确定,检索它们的唯一方法是解析生成的 .js 文件。侧模块是另一种野兽,如果我实际上不需要可重定位模块,我可能应该避免使用它们。

【问题讨论】:

【参考方案1】:

您可以简单地将输出选项 (-o) 设置为带有 .wasm 扩展名的文件名。 Emscripten 将只输出 wasm 文件。

所以如果你有以下test.c 文件:

#include "emscripten.h"

EMSCRIPTEN_KEEPALIVE
int add(int a, int b) 
    return a + b;

然后你像这样用 emscripten 编译它:

emcc -O3 test.c -o test.wasm

您只会获得文件test.wasm,而不会获得额外的.js 文件。此外,如果您使用例如反汇编 test.wasm wasm2wat 你会得到这个 WebAssembly 文本:

(module
  (type (;0;) (func))
  (type (;1;) (func (param i32 i32) (result i32)))
  (func (;0;) (type 0)
    nop)
  (func (;1;) (type 1) (param i32 i32) (result i32)
    local.get 0
    local.get 1
    i32.add)
  (memory (;0;) 256 256)
  (export "memory" (memory 0))
  (export "add" (func 1))
  (export "_start" (func 0))
  (data (;0;) (i32.const 1536) "\a0\06P"))

如您所见,这正是您对最小 WebAssembly 二进制文件的期望。

【讨论】:

以上是关于如何使用 emscripten 生成独立的 WebAssembly的主要内容,如果未能解决你的问题,请参考以下文章

是否可以使用 Emscripten 从 JavaScript 调用 C++ 函数?

如何使用 Socket.io 和 emscripten 使用 javascript 库?

将命令行参数传递给 emscripten 生成的应用程序

Emscripten:提供下载/保存生成的 MEMFS 文件

使用 emscripten 生成 python.cc.js

如何直接从原生 JavaScript 前端与 Emscripten Web Worker 交互