Скомпилируйте программу protobuf C++ в wasm (Webassembly)

Я хочу скомпилировать программу на С++ в wasm (webassembly) и запустить ее с помощью wasmtime, которая является средой выполнения wasm, но не удалась.

Программа на C++ использует protobuf, который уже скомпилирован из кода src с помощью Emscripten. Программа успешно построена с использованием Emscripten, но не может работать с wasmtime, а также не может быть преобразована в файл .wat с помощью wasm2wat.

Теперь проблема :

  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 содержит протофайлы, которые определяют формат сообщения, файл person.proto:

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

Человек.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)

Я пересобираю исходный код protobuf с помощью Emcsripten и генерирую libprotobuf.a в каталоге ./lib/,

Успешно построить:

      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

Вот еще один вопрос : я также хочу знать, как скомпилировать сложную программу на С++ (со сторонними библиотеками) для wasm и запустить ее с помощью wasmtime или другой среды выполнения wasm (не в Интернете)? Работает ли компиляция каждой библиотеки в wasm(libxxx.a) и связывание их с целью?

1 ответ

Заметил, что в сообщении об ошибке говорится, что «поддержка потоков не включена», и я попытался добавить--wasm-feature threadsпри запуске wasmtime (ссылка ) нравитсяwasmtime --wasm-feature threads persom.wasm. Но все равно не работал.

Кроме того, поскольку я хочу сгенерировать отдельный файл wasm, я добавил параметр компиляции-sSTANDALONE_WASM. С этой страницы сказано, что

emcc ... -o output.wasm пропускает создание файла запуска JavaScript или HTML и создает один файл Wasm, созданный в автономном режиме, как если бы использовался параметр -sSTANDALONE_WASM.

что означает, что я должен указать обаstandalone_wasmи-o output.wasmв то же время.

Поэтому я указал тип выходного файла черезset(CMAKE_EXECUTABLE_SUFFIX ".wasm"). Наконец-то работает!

Но я не понимаю, почему мне нужно включить поток для wasmtime, поскольку в cpp нет кода.

Спасибо за комментарий от @yeputons,threadопция может быть вызвана атомарными переменными protobuf.

Другие вопросы по тегам