How to Build ZXing C++ to Wasm using WASI SDK in Linux

Xiao Ling
The Startup
Published in
3 min readOct 24, 2019

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.

install debian in linux

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 in linux

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
run wasi zxing barcode wasm file with wapm

Reference

https://github.com/CraneStation/wasmtime/blob/master/docs/WASI-tutorial.md

Source Code

https://github.com/yushulx/wasi-zxing-wasm

--

--

Xiao Ling
The Startup

Manager of Dynamsoft Open Source Projects | Tech Lover