我可以以某种方式构建webassembly代码*而不使用emscripten“glue”吗?
我可以以某种方式创建一个wasm文件,它可以自己工作,如描述in MDN here(通过安装对象和调用它们的函数)?我可以以某种方式构建webassembly代码*而不使用emscripten“glue”吗?
我能找到的所有指南(such as this one on MDN)推荐使用emscripten;但是,它也会包含~70kB的“胶水代码”(约50kB可选文件系统仿真),它还有其他逻辑(如检测节点/浏览器环境和自动获取等)以及其他仿真。
如果我不想要那个“胶水代码”并且想直接创建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
(您也可以使用来自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”函数。
wac!我一直试图用wabt解释器来构建类似的东西,但是发现它缺乏我的目的。看起来像你救了我一堆工作:) – kazemakase
我接受你的版本,*但*有这个问题,我不喜欢。希望他们能很快解决它! https://github.com/kripken/emscripten/issues/5419 –
您可以随着时间的推移变得更加轻松!
如果您想完全避免使用C++,可以创建WebAssembly模块,例如在spec tests或WebKit test suite中所做的那样。
即使使用C++,也可以不使用Emscripten。 wasm-stat.us是否适用于例如海合会酷刑测试。看看它的构建输出,或者look at its source。
例如,它会做的编译/链接以下/组合:
# 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
你甚至可以下载所有的瀑布的构建文物,包括完整工具链。只需点击一个绿色框并找到您要找的下载。
如果你感觉大胆你甚至可以write your libc in JavaScript,而不是联用C写的
当你说“在自己的”现有的实现,记得比WebAssembly目前没有链接到什么都做不了其嵌入器(即JavaScript)。模型Emscripten遵循(我希望其他人也这样做)是JavaScript是微内核并提供系统调用。
感谢您的回答!也很有帮助,虽然我接受了另一个(但至少已投票支持你的) –
您可以使用ONLY_MY_CODE标志,这将只生成没有glue.js的wasm模块,例如,
emcc -O1 ./src/foo.cpp -o release/foo.wasm -s WASM=1 -s ONLY_MY_CODE=1
从Settings.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.
谢谢!将尝试 –
好。这与'-s SIDE_MODULE = 1'不同吗? – kazemakase
https://github.com/kripken/emscripten/wiki/Linking 据我所知,两者都消除了用于将模块链接到系统库文件等的胶水代码,但'only_my_code = 1'进一步确保只有你的代码被翻译成wasm –
与答案可能相关的问题 - https://stackoverflow.com/questions/45146099/how-do-i-compile-ac-file-to -webassembly –