Back to Wasmedge

WasmEdge WASMEDGE-Zlib example

examples/plugin/wasmedge-zlib/README.md

0.16.25.0 KB
Original Source

WasmEdge WASMEDGE-Zlib example

This is an example to demonstrate how to use the wasmedge-zlib plugin of WasmEdge with C++.

Prerequisites

You need four main components:

  1. Emscripten SDK (for compiling to WebAssembly)

  2. WasmEdge Runtime

  3. wasmedge-zlib plugin

  4. wit-bindgen(v0.42.x) (for generating bindings on the fly)

Check missing

The project includes a Makefile that can check for dependencies

bash
make check-all-tools

Install Emscripten SDK (C++ Compiler Toolkit for wasm targets)

bash
cd ~/
mkdir lib; cd lib
git clone https://github.com/emscripten-core/emsdk.git
cd emsdk
./emsdk install latest
./emsdk activate latest
source ./emsdk_env.sh # Only this shell will be able to use emscripten.

Install WasmEdge and WASMEDGE-zlib plugin

Note: If you install WasmEdge using the installation script, you need to download wasmedge-zlib plugin from the release page and put it into $HOME/.wasmedge/plugin/.

Or you can build Wasmedge from scratch with wasmedge-zlib plugin enabled.

bash
git clone https://github.com/WasmEdge/WasmEdge.git --depth 1
cd WasmEdge
export WASMEDGE_PATH=$PWD
# To tell Wasmedge where to find wasmedge-zlib plugin.
export WASMEDGE_PLUGIN_PATH=$WASMEDGE_PATH/build/plugins/wasmedge_zlib
mkdir build; cd build
cmake .. -DWASMEDGE_PLUGIN_WASMEDGE_ZLIB=ON
# In case you don't want `AOT` support, try the variant below
# cmake .. -DWASMEDGE_PLUGIN_ZLIB=ON -DWASMEDGE_USE_LLVM=OFF
cmake --build . -j
# Compiled Wasmedge is located in ./tools/wasmedge/wasmedge

Build and Run the example using Make

bash
cd ./examples/plugin/wasmedge-zlib/
make all # Build both native and WebAssembly versions
make clean # Clean the build directory
make native # Build the native version
make wasm # Build WebAssembly version
make run-native # Run the native version
make run-wasm # Run the WebAssembly version
make help # Show all available targets

Manually Build and Run the example as a WASM Module

First generate the bindings

bash
cd ../examples/plugin/wasmedge-zlib/
mkdir -p bindings
wit-bindgen c wit --out-dir bindings

Sanitize the .c file

NOTE: The bindings/zlib_component.c file generated by wit-bindgen has a lot of #, @, and . characters in the function signatures and that Emscripten doesn't like.

bash
awk -v sanitize_chars_regex='[:/@#%.]' '
{
  line = $0; processed_line = 0;
  prefix_end_marker = "__export_name__(\"";
  start_pos = index(line, prefix_end_marker);
  if (start_pos > 0) {
    name_start_pos = start_pos + length(prefix_end_marker);
    name_and_suffix_part = substr(line, name_start_pos);
    closing_quote_pos_in_suffix = index(name_and_suffix_part, "\"");
    if (closing_quote_pos_in_suffix > 0) {
      name_to_sanitize = substr(name_and_suffix_part, 1, closing_quote_pos_in_suffix - 1);
      prefix = substr(line, 1, name_start_pos - 1);
      suffix = substr(name_and_suffix_part, closing_quote_pos_in_suffix);
      sanitized_name = name_to_sanitize;
      gsub(sanitize_chars_regex, "_", sanitized_name);
      print prefix sanitized_name suffix;
      processed_line = 1;
    }
  }
  if (processed_line == 0) print line;
}' bindings/zlib_component.c > bindings/zlib_component.c.tmp && mv bindings/zlib_component.c.tmp bindings/zlib_component.c

Build and Link the wasm

bash
mkdir -p build/wasm

# Compile C++ source
em++ -O2 -std=c++17 -Wall -Wextra \
  -sWARN_ON_UNDEFINED_SYMBOLS=0 \
  -Ibindings \
  -c main.cpp -o build/wasm/main.o

# Compile generated bindings
emcc -O2 -Wall -Wextra \
  -sWARN_ON_UNDEFINED_SYMBOLS=0 \
  -Ibindings \
  -c bindings/zlib_component.c -o build/wasm/zlib_component_bindings.o

# Link with bindings component_type.o
em++ -O2 -sSTANDALONE_WASM -sWARN_ON_UNDEFINED_SYMBOLS=0 \
  build/wasm/main.o \
  build/wasm/zlib_component_bindings.o \
  bindings/zlib_component_component_type.o \
  -o build/wasm/main.wasm

Then we get build/wasm/main.wasm.

We can run this example with Wasmedge with the following command

bash
wasmedge build/wasm/main.wasm

Manually Build and Run the example as a Native executable

bash
apt install zlib1g-dev # For Ubuntu / Debian distros | Try zlib-devel for fedora | Try `brew install zlib` for macOS
cd ../examples/plugin/wasmedge-zlib/
mkdir -p build/native
g++ -O2 -std=c++17 -Wall -Wextra \
main.cpp -o build/native/zlib_test_native -lz
./build/native/zlib_test_native

Expected Output

The WASM example should run successfully and print out the following messages.

bash
Compressing Buffer of size : 1048576B
Decompressing Buffer of size : 785071B
Success

Difference between Native & WASM Module

  • Since wasmedge-zlib ignores the custom memory allocators provided by the program to the zlib library, any code on the custom allocator function won't run.
  • This will not affect the actual zlib compression, decompression, or any library usage, and will therefore be almost transparent to the program/module using the zlib library (wasmedge-zlib).