【问题标题】:How do I compile a C++ file to WebAssembly?如何将 C++ 文件编译为 WebAssembly?
【发布时间】:2017-12-22 02:25:13
【问题描述】:

假设我有一个简单的、独立的 C++ 文件 (math.cpp),如下所示:

int add(int x, int y) {
  return x + y;
}

如何将其编译为 WebAssembly (math.wasm)?

注意:我使用的是 Clang 工具链。

【问题讨论】:

    标签: c++ webassembly


    【解决方案1】:

    我发现this gist 很有帮助。

    基本上,步骤如下:

    1. (使用-DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD=WebAssembly构建llvm和clang 5.0.0或更高版本)
    2. 使用 clang 将 .cpp 源编译为 llvm 位代码:

      clang -emit-llvm --target=wasm32 -Oz math.cpp -c -o math.bc

    3. 将位码编译为 s-assembly:

      llc -asm-verbose=false -o math.s math.bc

    4. 使用binaryen的s2wasm工具创建一个.wast文件

      s2wasm math.s > math.wast

    5. 使用WABT的wast2wasm工具将文本.wast文件翻译成二进制.wasm:

      wast2wasm -o math.wasm math.wast

    有些步骤感觉多余,但我还没有找到允许快捷方式的工具。 (如果 llc 可以直接编译为 .wasm,或者 s2wasm 顾名思义实际上创建了二进制 .wasm 文件,那就太好了。)无论如何,一旦你运行了工具链,它就相对轻松了。但是请注意,目前还没有用于 Web 汇编的 C 或 C++ 标准库。

    或者,如果您需要 .wasm 文件只是为了尝试一些东西,您可以摆脱所有工具链的麻烦。浏览至https://mbebenita.github.io/WasmExplorer/paste in your C/C++ code,并下载已编译的 .wasm 文件。


    感谢 @noontz 和 @LB-- 指出这一点

    实际上,正如 gist 中的 cmets 建议的那样,您可以跳过 binaryen 并直接从 Clang/LLVM 编译为 wasm。我目前正在为 C++ 使用以下命令行:

    clang++ test.cpp -ObjC++ --compile --target=wasm32-unknown-unknown-wasm \ 
            --optimize=3 --output test.wasm
    

    【讨论】:

    • 实际上正如 gist 中的 cmets 建议的那样,您可以跳过 binaryen 并直接从 Clang/LLVM 编译为 wasm。我目前正在为 C++ 使用以下命令行:clang++ test.cpp -ObjC++ --compile --target=wasm32-unknown-unknown-wasm --optimize=3 --output test.wasm
    • @noontz 嗯,很好.. 看起来毕竟值得阅读 gist cmets ;) 如果有人可以独立确认这个工作(或者在我设法尝试之后),我会将其编辑为答案它)。
    • 我可以确认 noontz' 命令可以使用 LLVM 7 生成一个 .wasm 文件,但我还没有尝试运行它。
    • 谢谢@LB--。我将您的评论和对 noontz 的赞成票作为验证。不幸的是,我还没有亲自尝试过:)
    【解决方案2】:

    Emscripten 提供了将 C++ 文件编译为 wasm 所需的一切。 Emscripten 还有一个SDK,在安装所有必要的工具时,它让生活变得轻松。

    然而,默认情况下,Emscripten 会在您的 wasm 文件中添加一些框架代码,并生成一些 html 和 javascript。

    可以使用 Emscripten 创建一个不包含任何框架代码、javascript 或 html 的最小 wasm 文件。在使用emccem++ 编译时使用选项-s SIDE_MODULE=1 -Oz -s ONLY_MY_CODE=1 将为您提供最小的wasm 文件。

    以下命令将使用您的示例和 Emscripten 导出一个最小的 wasm 文件:

    em++ math.cpp -o math.wasm -Oz -s SIDE_MODULE=1 -s WASM=1 -s "EXPORTED_FUNCTIONS=['_add']" -s ONLY_MY_CODE=1

    【讨论】:

    • 我在尝试这个时遇到错误:Assigning a non-existent settings attribute "WASM"
    • 我得到“dyncall undefined”。我已经完成了 emscripten,它不再是一个简单的解决方案。
    【解决方案3】:

    截至 2019 年,Clang (8) 支持开箱即用的 webassembly。这是一个存储库,其中包含编译、链接和运行简单 .wasm 文件所需的一切。

    https://github.com/PetterS/clang-wasm

    【讨论】:

    • 需要注意的是这仅适用于小代码。
    • Couldn't run this on macOS (10.15.6) - 与已在 repo 中提交的问题相同。
    【解决方案4】:

    目前编译 C 和 C++ 最简单的方法是使用 emscripten。您提到的组件都是组件,但 emscripten 是一个完整的工具链,支持端到端构建,并且包含您需要的所有部分,包括 libc/libc++ 以及各种其他有用的库。它支持同时定位 asm.js 和 wasm。

    【讨论】:

    • 一般来说这是一个很好的建议 - 使用 emscripten 构建起来要容易得多 - 但对于这个问题根本不是。 Emscripten 将创建比之前的步骤大几个数量级的文件
    • @KarelBílek 发布此答案时可能是这样,但现在不再如此。看看我的回答。
    【解决方案5】:

    根据这个帖子中的答案,我创建了一个小guide

    对我来说,最简单的方法是在我的机器上编译emscripten(该网站也是一个很好的起点!),将代码编译为 wasm,生成适当的绑定并将所有这些隐藏在 JS 的包装器中- 除此之外,我得到了一个不错的界面。

    由于 c++ 的名称修改,我发现 C 入门更容易。

    【讨论】:

    • 当我们在 C++ 项目中使用大量外部库时,emscripten 可以吗?
    【解决方案6】:

    这个答案有点晚了,但是网上有很多漂亮的工具可以编译你的脚本。

    例如,我正在使用这个。那个给你最小的编译选项(C,C++,std99 ...)但有足够的:https://wasdk.github.io/WasmFiddle/

    根据您的使用方式,您可以选择不同的语言,例如 x86、code Buffer。你也可以分享你的代码,当你和其他朋友一起工作时我觉得很酷的功能:https://wasdk.github.io/WasmFiddle/?gus9d :)

    【讨论】:

    • 这很有趣,但在构建整个项目时不是一个现实的选择。我需要可以在本地和 CI 服务器上运行的东西。
    猜你喜欢
    • 2019-08-24
    • 2022-01-25
    • 1970-01-01
    • 1970-01-01
    • 2017-11-29
    • 2018-03-16
    • 1970-01-01
    • 2019-02-14
    • 1970-01-01
    相关资源
    最近更新 更多