如何使用Rust生成最小的wasm文件?

zak*_*akm 6 rust webassembly

我可以通过运行从以下C代码生成一个相当小的(203字节)wasm文件emcc -O3 -s WASM=1 -s SIDE_MODULE=1 -o sum.wasm sum.c.

#include <emscripten/emscripten.h>

int EMSCRIPTEN_KEEPALIVE sum(int a, int b) {
    return a + b;
}
Run Code Online (Sandbox Code Playgroud)

拆卸输出:

(module
 (type $0 (func (param i32 i32) (result i32)))
 ... trim 9 lines ...
 (export "_sum" (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)
  )   
 )   
 ... trim 17 lines ...
)
Run Code Online (Sandbox Code Playgroud)

但是给出了以下Rust代码

pub fn main() {}

#[no_mangle]
pub extern fn sum(a: i32, b: i32) -> i32 {
    a + b
}
Run Code Online (Sandbox Code Playgroud)

我似乎无法生产任何类似的东西.

rustc -O --target=wasm32-unknown-emscripten sum.rs 但是给了我一个85k的wasm文件和一个128k的js文件.

我尝试过导出,EMMAKEN_CFLAGS='-s WASM=1 -s SIDE_MODULE=1'但这给了我一些警告,比如

输入文件"/tmp/.../rust.metadata.bin"存在,但不是适用于Emscripten的LLVM bitcode文件.也许意外地将本机构建的目标文件与Emscripten混合在一起?

然后无法链接.

我的Rust版本是1.22.0-nightly (c6884b12d 2017-09-30),我的emcc版本是1.37.21.

我究竟做错了什么?

Col*_*inE 6

使用wasm32-unknown-emscripten目标,您使用的是基于Emscripten的编译器工具链.Emscripten在wasm模块中添加了相当多的额外运行时代码,以及用于在运行时与此集成的其他JavaScript代码.正如您所观察到的,Emscripten可以使用一个SIDE_MODULE选项来编译,该选项可以删除绝大多数此运行时代码.这减少了wasm二进制大小,但意味着您必须自己处理诸如绑定复杂类型之类的事情.

最近(2017年11月),一个新的wasm32-unknown-unknown目标被添加到Rust中,它使用LLVM后端(而不是Emscripten及其fastcomp fork),从而产生最小的输出.

可以按照设置指南中的说明使用此目标:

rustup update
rustup target add wasm32-unknown-unknown --toolchain nightly
rustc +nightly --target wasm32-unknown-unknown -O hello.rs
Run Code Online (Sandbox Code Playgroud)