WASI — это системный интерфейс, предназначенный для создания программных модулей .wasm не только для Node.js и веб-браузеров, но и для любой совместимой с WASI среды выполнения. Хотя WASI ещё находится на стадии разработки и не отличается стабильностью, его вполне можно применять для некоторых экспериментальных проектов. 

Нас интересуют две WASI-совместимые среды выполнения: Wasmer и Wasmtime.

Wasmer

Набираем в терминале:

https://get.wasmer.io -sSfL | sh

Wasmtime

Получаем исходный код и собираем wasmtime с помощью компилятора Rust.

Настройка среды сборки WASI

Начнём с wasi-libc. Для компиляции нам понадобится clang 8 или более поздняя версия. Если у вас ещё не установлен clang, не спешите бежать в репозитории: последней версии вы там не найдёте.

Мы пойдём другим путём: добавляем deb http://deb.debian.org/debian/ testing main к /etc/apt/sources.list и обновляем источники:

sudo apt update

И вот перед нами последняя версия — clang 9:

Устанавливаем её и создаём соответствующие символьные ссылки:

sudo apt install clang-9
sudo ln -s /usr/bin/clang-9 /usr/bin/clang
sudo ln -s /usr/bin/clang++-9 /usr/bin/clang++

Теперь можно скомпилировать WASI Libs из исходного кода. Если вам нужны только инструменты, лучше установить wasi-sdk:

sudo dpkg -i wasi-sdk_7.0_amd64.deb
export PATH=/opt/wasi-sdk/bin:$PATH
export CC=/opt/wasi-sdk/bin/clang
export CXX=/opt/wasi-sdk/bin/clang++
#include <stdio.h>
int main()
{
printf("hello wasi libc\n");
return 0;
}

Теперь проверяем простенькой программой:

Компилируем код:

$ clang — target=wasm32-wasi — sysroot=/opt/wasi-sdk/share/wasi-sysroot/ test.c -o test.wasm

И запускаем приложение:

wasmer run test.wasm
wasmtime test.wasm

Портирование ZXing C++ для WASI Libc

Возьмём исходный код zxing-cpp. На данный момент WASI libc ещё не поддерживает исключения C++, поэтому надо добавить -fno-exceptions к CMakeLists.txt:

set (CMAKE_CXX_FLAGS “${CMAKE_CXX_FLAGS} — target=wasm32-wasi -Wall -Wextra -fno-exceptions”)

Далее устанавливаем sysroot:

set (CMAKE_SYSROOT /opt/wasi-sdk/share/wasi-sysroot)

Для успешной сборки я отключил в коде всё, что имеет отношение к исключениям C++, и подкорректировал структуру проекта. Выполняем сборку проекта в wasm-файл:

mkdir build
cd build
cmake ..
cmake --build .

Запускаем приложение в папке сборки:

$ wasmer run zxing_barcode_reader.wasm — dir=$(pwd)/../ $(pwd)/../test.png
Text: MEBKM:URL:http\://en.wikipedia.org/wiki/Main_Page;;
Format: QR_CODE
Position: 190x367 205x162 422x165 405x342
EC Level: M
$ wasmtime zxing_barcode_reader.wasm — dir=$(pwd)/../ $(pwd)/../test.png
Text: MEBKM:URL:http\://en.wikipedia.org/wiki/Main_Page;;
Format: QR_CODE
Position: 190x367 205x162 422x165 405x342
EC Level: M

Использование Wapm для передачи и выполнения Wasm-файла

Генерируем файл wapm.toml командой init:

$ wapm init zxing_barcode_reader

Редактируем этот wapm.toml:

[package]
name = "yushulx/zxing_barcode_reader"
version = "0.1.4"
description = "A barcode reader app built with ZXing C/C++ and wasi-sdk"
readme = "README.md"
repository = "https://github.com/yushulx/wasi-zxing-wasm"
[[module]]
name = "zxing_barcode_reader"
source = "dist/zxing_barcode_reader.wasm"
abi = "wasi"
[[command]]
name = "zxing_barcode_reader"
module = "zxing_barcode_reader"

Передаём пакет на wapm.io:

wapm login
wapm publish

Устанавливаем пакет через wapm и считываем штрих-код в PNG:

wapm install yushulx/zxing_barcode_reader
wapm run zxing_barcode_reader — dir=. test.png

Документация.

Проект на Github.

Читайте также:


Перевод статьи Xiao Ling: How to Build ZXing C++ to Wasm using WASI SDK in Linux