我可以以某种方式构建webassembly code*没有*emscripten "glue"吗?



我可以以某种方式创建一个wasm文件,该文件将按照MDN中的描述自行工作(通过初始化对象并调用它们的函数(?

我能找到的所有指南(比如MDN上的这个(都建议使用emscripten;然而,它还将包括~70kB的"胶水代码"(带有~50 kB可选的文件系统仿真(,它具有额外的逻辑(如检测节点/浏览器环境和自动获取等(,可能还有其他一些仿真。

如果我不想要那个"胶水代码"而想直接创建 WASM(可能来自 C 代码,但也许是其他代码(怎么办?现在可能吗?

您可以使用 emscripten 生成相当少的代码输出。

请考虑以下简单的文件adder.c

int adder (int a, int b) {
return a + b;
}

像这样编译它(需要一个相当新的 emscripten(:

emcc -O2 -s WASM=1 -s SIDE_MODULE=1 -o adder.wasm

要查看它生成了什么,请使用binaryen的wasm-dis将其反汇编为wast文本形式(您也可以使用wabt的wasm2wast(:

wasm-dis adder.wasm -o adder.wast

反汇编的源应如下所示:

(module
(type $0 (func (param i32 i32) (result i32)))
(type $1 (func))
(import "env" "memoryBase" (global $import$0 i32))
(import "env" "memory" (memory $0 256))
(import "env" "table" (table 0 anyfunc))
(import "env" "tableBase" (global $import$3 i32))
(global $global$0 (mut i32) (i32.const 0))
(global $global$1 (mut i32) (i32.const 0))
(export "__post_instantiate" (func $2))
(export "runPostSets" (func $1))
(export "_adder" (func $0))
(func $0 (type $0) (param $var$0 i32) (param $var$1 i32) (result i32)
(i32.add
(get_local $var$1)
(get_local $var$0)
)
)
(func $1 (type $1)
(nop)
)
(func $2 (type $1)
(block $label$0
(set_global $global$0
(get_global $import$0)
)
(set_global $global$1
(i32.add
(get_global $global$0)
(i32.const 5242880)
)
)
(call $1)
)
)
;; custom section "dylink", size 5
)

然后,您可以在节点 (v8.X 或更高版本(如下所示:

const WA = WebAssembly,
env = {memoryBase: 0,
tableBase: 0,
memory: new WA.Memory({initial: 256}),
table: new WA.Table({initial: 0, element: 'anyfunc'})},
code = new Uint8Array(require('fs').readFileSync('adder.wasm'))
WA.compile(code).then(m => {
return new WA.Instance(m, {env: env})
}).then(i => {
console.log(i.exports._adder(7, 8))
})

请注意,如果要支持使用堆栈和/或堆内存的代码,事情会变得更加复杂。 也就是说,在调用任何其他导出之前,您至少需要设置 memoryBase 并从主机环境调用__post_instantiate

如果你想在没有JavaScript环境的情况下解释WebAssembly代码,你可以使用wac/wace运行它(完全披露:我创建了这个项目(。请注意,wace假设您定义了"_main"或"main"函数。

LLVM现在支持使用WASI将C直接编译为wasm。不再需要 Emscripten。

如果不需要libc,则可以开箱即用地使用LLVM。例如,文件foo.c可以编译为:

clang --target=wasm32 --no-standard-libraries -Wl,--export-all -Wl,--no-entry -o foo.wasm foo.c

否则,WASI-libc 项目有一个可以使用的独立 libc。

本文提供了使用 LLVM 将 C 编译为 WebAssembly 并在浏览器中运行它的完整过程。

您可以使用ONLY_MY_CODE标志,这将仅生成没有胶水的wasm模块.js例如

emcc -O1 ./src/foo.cpp -o release/foo.wasm -s WASM=1 -s ONLY_MY_CODE=1

从设置.js https://github.com/kripken/emscripten/blob/master/src/settings.js#L583 :

var ONLY_MY_CODE = 0; // This disables linking and other causes of adding extra code
// automatically, and as a result, your output compiled code
// (in the .asm.js file, if you emit with --separate-asm) will
//  contain only the functions you provide.

你可以,而且随着时间的推移,它变得越来越容易!

如果你想完全避免C++可以创建 WebAssembly 模块,例如在规范测试或 WebKit 测试套件中所做的那样。

即使有C++你也可以,没有Emscripten。 wasm-stat.us 这样做是为了例如海湾合作委员会酷刑测试。查看其构建输出,或查看其源代码。

例如,它将执行以下操作进行编译/链接/汇编:

# Get a .o file:
src/work/wasm-install/bin/clang src/work/gcc/gcc/testsuite/gcc.c-torture/execute/20020227-1.c -o src/work/torture-o/20020227-1.c.o --std=gnu89 -DSTACK_SIZE=1044480 -w -Wno-implicit-function-declaration --target=wasm32-unknown-unknown-wasm -c -O2 --sysroot=src/work/wasm-install/sysroot
# Link with libc:
src/work/wasm-install/bin/lld -flavor wasm -entry=main --allow-undefined-file=src/work/wasm-install/sysroot/lib/wasm.syms -o src/work/torture-lld-musl/20020510-1.c.o.wasm src/work/torture-o/20020510-1.c.o src/work/wasm-install/sysroot/lib/libc.a
# Or without a libc (you need to provide one somehow):
src/work/wasm-install/bin/lld -flavor wasm -entry=main --allow-undefined-file=src/work/wasm-install/sysroot/lib/wasm.syms -o src/work/torture-lld/20020510-1.c.o.wasm src/work/torture-o/20020510-1.c.o
# Or, if you want an assembly file instead:
src/work/wasm-install/bin/clang src/work/gcc/gcc/testsuite/gcc.c-torture/execute/20020227-1.c -o src/work/torture-s/20020227-1.c.s --std=gnu89 -DSTACK_SIZE=1044480 -w -Wno-implicit-function-declaration --target=wasm32-unknown-unknown -S -O2 --sysroot=src/work/wasm-install/sysroot
# And get the binary file:
src/work/wasm-install/bin/wast2wasm src/work/torture-s2wasm/loop-6.c.s.wast -o src/work/torture-wast2wasm/loop-6.c.s.wast.wasm

您甚至可以下载瀑布的所有构建工件,包括完整的工具链。只需单击绿色框,然后找到您要查找的下载。

如果你觉得大胆,你甚至可以用JavaScript编写你的libc,而不是链接用C编写的现有实现。

当你说"靠自己"时,请记住,WebAssembly 目前如果不链接到它的嵌入器(即 JavaScript(,就无法做任何事情。Emscripten遵循的模型(我希望其他人也这样做(是JavaScript是微内核并提供系统调用。

2020 年更新

使用Emscripten,您可以使用-o my_file.wasm

这样,您将只有WASM文件,如果您使用标志STANDALONE_WASM它将创建.wasm和可选的.js胶水代码(如果需要(。

相关内容

  • 没有找到相关文章

最新更新