将protobuf c++程序编译为wasm(WebAssembly)

问题描述 投票:0回答:2

我想将一个 C++ 程序编译为 wasm(webassemble) 并通过 wasmtime(wasm 运行时)运行它,但失败了。

c++ 程序使用 protobuf,它已经使用 Emscripten 从 src 代码编译而来。该程序使用 Emscripten 成功构建,但无法使用 wasmtime 运行,也无法使用 wasm2wat 转换为 .wat 文件。

现在问题是:

  1. 使用wasmtime运行时的错误信息是:
# wasmtime person.wasm
Error: failed to run main module `person.wasm`

Caused by:
    0: if you're trying to run a precompiled module, pass --allow-precompiled
    1: failed to compile wasm function 79 at offset 0x293c
    2: WebAssembly translation error
    3: Invalid input WebAssembly code at offset 10632: threads support is not enabled
  1. 转换为.wat格式时,出现另一个错误:
# wasm2wat person.wasm
000298a: error: unexpected opcode: 0xfe 0x10

这是文件树

protobuf_wasm_test/
  -lib/
    -libprotobuf-lite.a
    -libprotobuf.a
    -libprotoc.a
  -pb/
    -person.pb.cc
    -person.pb.h
  -CMakeLists.txt
  -person.cpp

pb目录包含定义消息格式的proto文件,person.proto文件是:

syntax = "proto3";
message Person {
    string id = 1;
    string name = 2;
}

person.cpp 是:

#include <iostream>
#include "./pb/person.pb.h"

int main()
{
    Person *person = (Person*)malloc(sizeof(Person));
    person->set_id("12345");
    person->set_name("abc");
    std::cout<<"id: "<<person->id()<<", name: "<<person->name()<<std::endl;
    free(person);
    return 0;
}

CMakeList.txt 是:

cmake_minimum_required(VERSION 3.5)
project(protobuf_wasm_test)

add_compile_options(-sSTANDALONE_WASM -Wno-unused-command-line-argument)

include_directories("${CMAKE_CURRENT_BINARY_DIR}/../pb")
include_directories("/home/hzb/protobuf_wasm/protobuf_src/src")

link_directories("${CMAKE_CURRENT_BINARY_DIR}/../lib")


set(proto_srcs "${CMAKE_CURRENT_BINARY_DIR}/../pb/person.pb.cc")
set(proto_hdrs "${CMAKE_CURRENT_BINARY_DIR}/../pb/person.pb.h")

add_library(proto
    ${proto_srcs}
    ${proto_hdrs})


add_executable(person
    person.cpp)

target_link_libraries(person
    proto
    protobuf)

我用 Emcsripten 重建 protobuf 源代码并在 ./lib/ 目录中生成 libprotobuf.a,

构建成功:

emcmake ..
emmake make
configure: cmake .. -DCMAKE_TOOLCHAIN_FILE=/home/hzb/emsdk/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake -DCMAKE_CROSSCOMPILING_EMULATOR=/home/hzb/emsdk/node/14.18.2_64bit/bin/node;--experimental-wasm-bulk-memory;--experimental-wasm-threads
-- Configuring done
-- Generating done
-- Build files have been written to: /home/hzb/protobuf_wasm/protobuf_wasm_test/build
make: make
[ 25%] Building CXX object CMakeFiles/proto.dir/pb/person.pb.cc.o
[ 50%] Linking CXX static library libproto.a
[ 50%] Built target proto
[ 75%] Building CXX object CMakeFiles/person.dir/person.cpp.o
[100%] Linking CXX executable person.js
[100%] Built target person

这是另一个问题:我也想知道如何将复杂的c ++程序(带有第三方库)编译为wasm并使用wasmtime或其他wasm运行时(非Web)运行它?将每个库编译为 wasm(libxxx.a) 并将它们链接到目标是否有效?

webassembly emscripten wasmtime
2个回答
2
投票

注意到错误消息显示“未启用线程支持”,我尝试在运行 wasmtime(

link
) 时添加 --wasm-feature threads,如
wasmtime --wasm-feature threads persom.wasm
。但还是没成功。

此外,由于我想生成一个独立的wasm文件,所以我添加了一个编译参数

-sSTANDALONE_WASM
。从this页面说

emcc ... -o output.wasm 忽略生成 JavaScript 或 HTML 启动器文件,并生成以独立模式构建的单个 Wasm 文件,就像使用了 -sSTANDALONE_WASM 设置一样。

这意味着我应该同时指定

standalone_wasm
-o output.wasm

所以我通过

set(CMAKE_EXECUTABLE_SUFFIX ".wasm")
指定了输出文件的类型。终于可以用了!

但是我不明白为什么我需要为 wasmtime 启用线程,因为 cpp 中没有

thread
代码。

感谢@yeputons的评论,

thread
选项可能是由protobuf原子变量引起的。


0
投票

韩老师,你好!您可以上传这些文件吗:

-libprotobuf-lite.a
-libprotobuf.a
-libprotoc.a

我尝试编译我的文件,但出现错误:

undefined symbol: absl::lts_20240722::log_internal::LogMessageFatal::LogMessageFatal(char const*, int, absl::lts_20240722::string_view)

我认为我的 protobuf 库编译不正确

谢谢!

© www.soinside.com 2019 - 2024. All rights reserved.