How to Build ZXing C++ to Wasm using WASI SDK in Linux
WASI is a modular system interface, which aims to build runnable .wasm modules for any WASI-compliant runtime, not only for Node.js and web browsers. Although WASI is still in development and not stable yet, it is available for some experimental projects. In this article, I will share how to use WASI Libc to build a .wasm barcode reader module by porting ZXing C++.
Installing WASI Runtime
Both Wasmer and Wasmtime support WASI.
Wasmer
curl https://get.wasmer.io -sSfL | sh
Wasmtime
Get the source code and build wasmtime with Rust compiler.
Setting Up WASI Building Environment
Let’s get started with wasi-libc.
To build WASI Libc, you have to use clang 8 or above. If you don’t have clang installed before, you may find the latest clang version is not listed in the apt software repositories.
The workaround is to add “deb http://deb.debian.org/debian/ testing main” to “/etc/apt/sources.list” and update the sources:
sudo apt update
Then the latest clang 9 is visible:
Install clang 9 and create relevant symlinks:
sudo apt install clang-9sudo ln -s /usr/bin/clang-9 /usr/bin/clangsudo ln -s /usr/bin/clang++-9 /usr/bin/clang++
Now we can build WASI Libs from the source code.
If you just want to use the toolchain, a more convenient way is to install wasi-sdk:
sudo dpkg -i wasi-sdk_7.0_amd64.debexport PATH=/opt/wasi-sdk/bin:$PATHexport CC=/opt/wasi-sdk/bin/clangexport CXX=/opt/wasi-sdk/bin/clang++
Create a ‘hello world’ program for the test:
#include <stdio.h>int main(){printf(“hello wasi libc\n”);return 0;}
Build the code:
$ clang — target=wasm32-wasi — sysroot=/opt/wasi-sdk/share/wasi-sysroot/ test.c -o test.wasm
Run the app:
wasmer run test.wasmwasmtime test.wasm
Porting ZXing C++ for WASI Libc
Get the source code of zxing-cpp.
Since the current WASI libc does not yet support C++ exceptions, we need to add -fno-exceptions to CMakeLists.txt:
set (CMAKE_CXX_FLAGS “${CMAKE_CXX_FLAGS} — target=wasm32-wasi -Wall -Wextra -fno-exceptions”)
In addition, set sysroot as follows:
set (CMAKE_SYSROOT /opt/wasi-sdk/share/wasi-sysroot)
To pass the build, I have disabled all C++ exception-relevant code and adjusted the project structure.
Build the project to a wasm file:
mkdir buildcd buildcmake ..cmake --build .
Run the app under the build folder:
$ wasmer run zxing_barcode_reader.wasm — dir=$(pwd)/../ $(pwd)/../test.pngText: MEBKM:URL:http\://en.wikipedia.org/wiki/Main_Page;;Format: QR_CODEPosition: 190x367 205x162 422x165 405x342EC Level: M$ wasmtime zxing_barcode_reader.wasm — dir=$(pwd)/../ $(pwd)/../test.pngText: MEBKM:URL:http\://en.wikipedia.org/wiki/Main_Page;;Format: QR_CODEPosition: 190x367 205x162 422x165 405x342EC Level: M
How to Use Wapm to Publish and Run the Wasm File
Generate a wapm.toml file with init command:
$ wapm init zxing_barcode_reader
Edit 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”
Publish the package to wapm.io:
$ wapm login$ wapm publish
Install the package via wapm and read barcodes from a PNG image:
$ wapm install yushulx/zxing_barcode_reader$ wapm run zxing_barcode_reader — dir=. test.png
Reference
https://github.com/CraneStation/wasmtime/blob/master/docs/WASI-tutorial.md