# 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](https://github.com/WasmEdge/WasmEdge/releases/) 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`).
