如何使用 Rust 生成最小的 wasm 文件?
How do I generate a minimal wasm file with Rust?
我可以通过 运行 emcc -O3 -s WASM=1 -s SIDE_MODULE=1 -o sum.wasm sum.c
.
从以下 C 代码生成一个相当小的(203 字节)wasm 文件
#include <emscripten/emscripten.h>
int EMSCRIPTEN_KEEPALIVE sum(int a, int b) {
return a + b;
}
反汇编输出:
(module
(type [=11=] (func (param i32 i32) (result i32)))
... trim 9 lines ...
(export "_sum" (func [=11=]))
(func [=11=] (type [=11=]) (param $var[=11=] i32) (param $var i32) (result i32)
(i32.add
(get_local $var)
(get_local $var[=11=])
)
)
... trim 17 lines ...
)
但给定以下 Rust 代码
pub fn main() {}
#[no_mangle]
pub extern fn sum(a: i32, b: i32) -> i32 {
a + b
}
我似乎无法制作任何类似的东西。
rustc -O --target=wasm32-unknown-emscripten sum.rs
有效,但给了我一个 85k 的 wasm 文件和一个 128k 的 js 文件。
我试过导出 EMMAKEN_CFLAGS='-s WASM=1 -s SIDE_MODULE=1'
但这给了我很多警告,比如
Input file "/tmp/.../rust.metadata.bin" exists but was not an LLVM bitcode file suitable for Emscripten. Perhaps accidentally mixing native built object files with Emscripten?
然后无法 link。
我的 Rust 版本是 1.22.0-nightly (c6884b12d 2017-09-30)
,我的 emcc 版本是 1.37.21
。
我做错了什么?
对于 wasm32-unknown-emscripten
目标,您使用的是基于 Emscripten 的编译器工具链。 Emscripten 在 wasm 模块中添加了大量额外的运行时代码,以及额外的 JavaScript 代码用于在运行时与之集成。正如您还观察到的,Emscripten 可以使用 SIDE_MODULE
选项进行编译,该选项删除了绝大部分运行时代码。这减少了 wasm 二进制大小,但意味着您必须自己处理诸如绑定复杂类型之类的事情。
最近(2017 年 11 月)一个新的 wasm32-unknown-unknown target was added to Rust,它使用 LLVM 后端(而不是 Emscripten 及其 fastcomp 分支),从而产生最小的输出。
此目标可以按照 setup guide:
中的描述使用
rustup update
rustup target add wasm32-unknown-unknown --toolchain nightly
rustc +nightly --target wasm32-unknown-unknown -O hello.rs
我可以通过 运行 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;
}
反汇编输出:
(module
(type [=11=] (func (param i32 i32) (result i32)))
... trim 9 lines ...
(export "_sum" (func [=11=]))
(func [=11=] (type [=11=]) (param $var[=11=] i32) (param $var i32) (result i32)
(i32.add
(get_local $var)
(get_local $var[=11=])
)
)
... trim 17 lines ...
)
但给定以下 Rust 代码
pub fn main() {}
#[no_mangle]
pub extern fn sum(a: i32, b: i32) -> i32 {
a + b
}
我似乎无法制作任何类似的东西。
rustc -O --target=wasm32-unknown-emscripten sum.rs
有效,但给了我一个 85k 的 wasm 文件和一个 128k 的 js 文件。
我试过导出 EMMAKEN_CFLAGS='-s WASM=1 -s SIDE_MODULE=1'
但这给了我很多警告,比如
Input file "/tmp/.../rust.metadata.bin" exists but was not an LLVM bitcode file suitable for Emscripten. Perhaps accidentally mixing native built object files with Emscripten?
然后无法 link。
我的 Rust 版本是 1.22.0-nightly (c6884b12d 2017-09-30)
,我的 emcc 版本是 1.37.21
。
我做错了什么?
对于 wasm32-unknown-emscripten
目标,您使用的是基于 Emscripten 的编译器工具链。 Emscripten 在 wasm 模块中添加了大量额外的运行时代码,以及额外的 JavaScript 代码用于在运行时与之集成。正如您还观察到的,Emscripten 可以使用 SIDE_MODULE
选项进行编译,该选项删除了绝大部分运行时代码。这减少了 wasm 二进制大小,但意味着您必须自己处理诸如绑定复杂类型之类的事情。
最近(2017 年 11 月)一个新的 wasm32-unknown-unknown target was added to Rust,它使用 LLVM 后端(而不是 Emscripten 及其 fastcomp 分支),从而产生最小的输出。
此目标可以按照 setup guide:
中的描述使用rustup update
rustup target add wasm32-unknown-unknown --toolchain nightly
rustc +nightly --target wasm32-unknown-unknown -O hello.rs