在 emscripten 中禁用链接 libc

Posted

技术标签:

【中文标题】在 emscripten 中禁用链接 libc【英文标题】:Disable linking libc in emscripten 【发布时间】:2017-01-14 19:00:07 【问题描述】:

我很好奇 emscripten 是否可以在没有 libc 的情况下构建二进制文件。

如果我有 simple.c:

int add1(int x) 
    return x + 1;

而且我不想包含任何 libc,这可能吗?

到目前为止,我最好的尝试是:

emcc simple.c -s NO_FILESYSTEM=1 -s DISABLE_EXCEPTION_CATCHING=1 -s DEFAULT_LIBRARY_FUNCS_TO_INCLUDE='[]' -s LIBRARY_DEPS_TO_AUTOEXPORT='[]' -s EXPORTED_FUNCTIONS='["add1"]' -s USE_SDL=0 -o simple.js -nostdlib

但生成的输出仍然包含 malloc 的符号、字符串转换例程等。

我也对生成 WebAssembly 的相同过程感兴趣;也就是说,我的真正目标是生成一个只包含一个函数的 webassembly 模块。这可以用 emscripten 实现吗?

【问题讨论】:

【参考方案1】:

Emscripten 目前并不适合这个用例。目标文件是位码,任何时候使用链接,它都想包含一些库和JS模块代码。

对于 WebAssembly,可以使用来自上游 LLVM 主干的 clang 以及来自 Binaryen 的 s2wasm 工具。 Clang(可选地与 LLVM 的 llc 工具结合使用)可以生成 .s 程序集文件,s2wasm 可以将其转换为 wast(WebAssembly 的文本格式)。可以使用 Binaryen 的 wasm-as 工具或来自 WABT 的 wast2wasm 工具将此文件转换为 wasm 二进制文件。此管道会将 C 文件中对函数的任何未定义引用转换为 wasm 导入,您需要手动连接到 javascript 函数。 互联网上有一些这样的例子(我通过谷歌搜索“webassembly clang s2wasm”找到了一些)。另请注意,s2wasm 完成了链接器布置 wasm 线性内存的工作,它有几个您需要注意的选项;查看它的帮助输出及其来源,例如tool 和 linker 代码。

【讨论】:

这可能有点复杂,但效果很好。我找到了一个对我很有帮助的 GitHub Gist:gist.github.com/yurydelendik/4eeff8248aeb14ce763e【参考方案2】:

您可以使用选项-s ONLY_MY_CODE=1 来获取仅包含您已编译代码的文件。

请参阅the possible options,您可以将其传递给 emscripten。

【讨论】:

【参考方案3】:

您有 2 个选项来构建独立的 wasm 模块。通过emsdk 或通过llvm。请注意,现在 emsdk 通过 asm.js 后端生成代码,并且本身不支持某些 i64 操作,例如乘法。

emsdk

emcc your_module.c -v -O3 -s WASM=1 -s SIDE_MODULE=1 -o your_module.wasm

本机 llvm + 二进制

注意,现在你需要来自trunk的最新llvm,编译时支持wasm。

clang -emit-llvm --target=wasm32 -O3 -c -o your_module.bc your_module.c
llc -asm-verbose=false -o your_module.s your_module.bc
s2wasm --emscripten-glue your_module.s > your_module.wast
wasm-opt -O3 your_module.wast -o your_module.wasm

【讨论】:

【参考方案4】:

见WebAssembly Standalone,本页也有示例链接。

emcc simple.c -Os -s WASM=1 -s SIDE_MODULE=1 -o simple.wasm

要在 html/js 中运行它,您必须提供带有 imports.env=memoryBase, tableBase, memory, tableimports 对象。但是,如果您通过 wabt 将 wasm 文件转换为 wat 格式,则可以剥离导入部分,因为您既不需要内存也不需要表,然后将其编译回 wasm。 这是exemple

【讨论】:

链接可能会损坏,请考虑在您的回答中提及关键点/示例。

以上是关于在 emscripten 中禁用链接 libc的主要内容,如果未能解决你的问题,请参考以下文章

Emscripten:如何禁用警告:显式专业化不能有存储类

emscripten链接全局命名符号多重定义

Emscripten: emmake 生成 .js 文件

如何设置基本的 C++/C 编译,然后为 emscripten 构建链接脚本

如何使用 Emscripten 编译的程序中的 wasm-bindgen?

Emscripten教程之优化你的代码