Скомпилируйте программу protobuf C++ в wasm (Webassembly)
Я хочу скомпилировать программу на С++ в wasm (webassembly) и запустить ее с помощью wasmtime, которая является средой выполнения wasm, но не удалась.
Программа на C++ использует protobuf, который уже скомпилирован из кода src с помощью Emscripten. Программа успешно построена с использованием Emscripten, но не может работать с wasmtime, а также не может быть преобразована в файл .wat с помощью wasm2wat.
Теперь проблема :
- Сообщение об ошибке при работе с 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
- При конвертации в формат .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.