如何减小 WASM 二进制文件的大小?

Aca*_*ane 5 c++ compiler-optimization webassembly wasi

我有一个用 C++ 编写的项目,要部署的平台有 256KB 二进制大小的限制。

工具链是wasi-sdk-16.0 clang++,我们使用这个编译器将源代码编译成WASM格式的二进制文件。在此步骤中,我们使用以下 CXX_FLAGS 编译源代码。

-fstack-protector-strong -Os -D_FORTIFY_SOURCE=2 -fPIC -Wformat -Wformat-security -Wl,-z,relro,-z,now -Wno-psabi
Run Code Online (Sandbox Code Playgroud)

然后我们将strip二进制文件与

strip -s output_binary.wasm
Run Code Online (Sandbox Code Playgroud)

经过上述步骤后,这一步编译出来的二进制文件大小为254KB。

然后我们wamrc在 WAMR 中使用 AOT 运行时编译 WASM 二进制文件,命令如下所示。

wamrc --enable-indirect-mode --disable-llvm-intrinsics -o output.aot output.wasm
Run Code Online (Sandbox Code Playgroud)

输出二进制大小变为 428KB,远大于限制(256KB)。


谷歌搜索后,我用来wasm-opt缩小尺寸,

wasm-opt -Oz output.wasm -o output.wasm
Run Code Online (Sandbox Code Playgroud)

大小变小 4KB。(几乎没用)


我试图确认我的代码对二进制大小的影响有多大,所以我编写了简单的最小示例代码,称为标准 C++ 库,如下所示,

-fstack-protector-strong -Os -D_FORTIFY_SOURCE=2 -fPIC -Wformat -Wformat-security -Wl,-z,relro,-z,now -Wno-psabi
Run Code Online (Sandbox Code Playgroud)

编译后的二进制大小已经变成了205KB。


我还尝试使用二进制大小分析器 ( twiggy) 来跟踪二进制文件每个部分的大小,但该工具无法打开该二进制文件。


所以我想问一下

  1. 虽然仅包含两个标准 C++ 头文件会使二进制大小达到大小限制,但如何使用我真正使用的函数剥离 C++ 标准库(我不能使用剥离未使用的函数标志,因为我的项目是提供给其他人的库),或者C++ 标准库真的影响了二进制大小吗?

  2. 是否有任何其他编译器标志,或剥离标志,或任何其他优化工具可以显着减少二进制大小?

Aca*_*ane 3

我只需将 iostream 和 fstream 替换为 cstdio 即可解决此问题。它将大小从 254KB 减少到 85KB,因为 iostream 中包含太多模板。

使用iostream 函数计数(带readelf -Ws 二进制大小
是的 第685章 254KB
76 85KB

虽然指定编译器标志(例如 -Oz)也可以减少一些大小,但主要因素是从模板生成了太多代码。因此,当存在二进制大小限制时,请勿使用 C++ 流 API(以及任何其他模板密集型通用库)。(C 库总是值得相信的。)