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 SDK 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-9
sudo ln -s /usr/bin/clang-9 /usr/bin/clang
sudo 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.deb
export PATH=/opt/wasi-sdk/bin:$PATH
export CC=/opt/wasi-sdk/bin/clang
export 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.wasm
wasmtime test.wasm
Porting ZXing C++ for WASI SDK
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 build
cd build
cmake ..
cmake --build .
Run the app under the build folder:
$ 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
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
Related Articles
My First Wasmtime Experience in Windows 10
Reference
https://github.com/CraneStation/wasmtime/blob/master/docs/WASI-tutorial.md