Enable AoT and wamr-sdk, and change arguments of call wasm API (#157)
* Implement memory profiler, optimize memory usage, modify code indent * Implement memory.grow and limit heap space base offset to 1G; modify iwasm build type to Release and 64 bit by default * Add a new extension library: connection * Fix bug of reading magic number and version in big endian platform * Re-org platform APIs: move most platform APIs from iwasm to shared-lib * Enhance wasm loader to fix some security issues * Fix issue about illegal load of EXC_RETURN into PC on stm32 board * Updates that let a restricted version of the interpreter run in SGX * Enable native/app address validation and conversion for wasm app * Remove wasm_application_exectue_* APIs from wasm_export.h which makes confused * Refine binary size and fix several minor issues Optimize interpreter LOAD/STORE opcodes to decrease the binary size Fix issues when using iwasm library: _bh_log undefined, bh_memory.h not found Remove unused _stdin/_stdout/_stderr global variables resolve in libc wrapper Add macros of global heap size, stack size, heap size for Zephyr main.c Clear compile warning of wasm_application.c * Add more strict security checks for libc wrapper API's * Use one libc wrapper copy for sgx and other platforms; remove bh_printf macro for other platform header files * Enhance security of libc strcpy/sprintf wrapper function * Fix issue of call native for x86_64/arm/mips, add module inst parameter for native wrapper functions * Remove get_module_inst() and fix issue of call native * Refine wgl lib: remove module_inst parameter from widget functions; move function index check to runtime instantiate * Refine interpreter call native process, refine memory boudary check * Fix issues of invokeNative function of arm/mips/general version * Add a switch to build simple sample without gui support * Add BUILD_TARGET setting in makefile to replace cpu compiler flags in source code * Re-org shared lib header files, remove unused info; fix compile issues of vxworks * Add build target general * Remove unused files * Update license header * test push * Restore file * Sync up with internal/feature * Sync up with internal/feature * Rename build_wamr_app to build_wasm_app * Fix small issues of README * Enhance malformed wasm file checking Fix issue of print hex int and implement utf8 string check Fix wasi file read/write right issue Fix minor issue of build wasm app doc * Sync up with internal/feature * Sync up with internal/feature: fix interpreter arm issue, fix read leb issue * Sync up with internal/feature * Fix bug of config.h and rename wasi config.h to ssp_config.h * Sync up with internal/feature * Import wamr aot * update document * update document * Update document, disable WASI in 32bit * update document * remove files * update document * Update document * update document * update document * update samples * Sync up with internal repo
This commit is contained in:
@ -1,14 +1,18 @@
|
||||
|
||||
Build WAMR Core
|
||||
Build WAMR core (iwasm)
|
||||
=========================
|
||||
Please follow the instructions below to build the WAMR core on different platforms.
|
||||
Please follow the instructions below to build the WAMR VM core on different platforms.
|
||||
|
||||
Linux
|
||||
-------------------------
|
||||
First of all please install library dependencies of lib gcc.
|
||||
Use installation commands below for Ubuntu Linux:
|
||||
First of all please install the dependent packages.
|
||||
Run command below in Ubuntu-18.04:
|
||||
``` Bash
|
||||
sudo apt install lib32gcc-5-dev g++-multilib
|
||||
sudo apt install build-essential cmake g++-multilib libgcc-8-dev lib32gcc-8-dev
|
||||
```
|
||||
Or in Ubuntu-16.04:
|
||||
``` Bash
|
||||
sudo apt install build-essential cmake g++-multilib libgcc-5-dev lib32gcc-5-dev
|
||||
```
|
||||
Or in Fedora:
|
||||
``` Bash
|
||||
@ -17,32 +21,60 @@ sudo dnf install glibc-devel.i686
|
||||
|
||||
After installing dependencies, build the source code:
|
||||
``` Bash
|
||||
cd core/iwasm/products/linux/
|
||||
cd product-mini/platforms/linux/
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
make
|
||||
```
|
||||
The binary file iwasm will be generated under build folder.
|
||||
|
||||
Note:
|
||||
The WASI feature is enabled by default, if we want to disable it, please run:
|
||||
WAMR provides some features which can be easily configured by passing options to cmake:
|
||||
``` Bash
|
||||
cmake .. -DWASM_ENABLE_WASI=0
|
||||
cmake -DWAMR_BUILD_INTERP=1/0 to enable or disable WASM intepreter
|
||||
cmake -DWAMR_BUILD_AOT=1/0 to enable or disable WASM AOT
|
||||
cmake -DWAMR_BUILD_JIT=1/0 to enable or disable WASM JIT
|
||||
cmake -DWAMR_BUILD_LIBC_BUILTIN=1/0 enable or disable Libc builtin API's
|
||||
cmake -DWAMR_BUILD_LIBC_WASI=1/0 enable or disable Libc WASI API's
|
||||
cmake -DWAMR_BUILD_TARGET=<arch><sub> to set the building target, including:
|
||||
X86_64, X86_32, ARM, THUMB, XTENSA and MIPS
|
||||
for ARM and THUMB, we can specify the <sub> info, e.g. ARMV4, ARMV4T, ARMV5, ARMV5T, THUMBV4T, THUMBV5T and so on.
|
||||
```
|
||||
|
||||
For example, if we want to disable interpreter, enable AOT and WASI, we can:
|
||||
``` Bash
|
||||
cmake .. -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_AOT=1 -DWAMR_BUILD_LIBC_WASI=0
|
||||
```
|
||||
Or if we want to enable inerpreter, disable AOT and WASI, and build as X86_32, we can:
|
||||
``` Bash
|
||||
cmake .. -DWAMR_BUILD_INTERP=1 -DWAMR_BUILD_AOT=0 -DWAMR_BUILD_LIBC_WASI=0 -DWAMR_BUILD_TARGET=X86_32
|
||||
```
|
||||
|
||||
By default in Linux, the interpreter, AOT and WASI are enabled, and JIT is disabled. And the build target is
|
||||
set to X86_64 or X86_32 depending on the platform's bitwidth.
|
||||
|
||||
To enable WASM JIT, firstly we should build LLVM:
|
||||
``` Bash
|
||||
cd product-mini/platforms/linux/
|
||||
./build_llvm.sh (The llvm source code is cloned under <wamr_root_dir>/core/deps/llvm and auto built)
|
||||
```
|
||||
Then pass option -DWAMR_BUILD_JIT=1 to cmake to enable WASM JIT:
|
||||
``` Bash
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DWAMR_BUILD_JIT=1
|
||||
make
|
||||
```
|
||||
|
||||
Linux SGX (Intel Software Guard Extention)
|
||||
-------------------------
|
||||
First of all please install library dependencies of lib gcc.
|
||||
Use installation commands below for Ubuntu Linux:
|
||||
``` Bash
|
||||
sudo apt install lib32gcc-5-dev g++-multilib
|
||||
```
|
||||
|
||||
And then install the [Intel SGX SDK](https://software.intel.com/en-us/sgx/sdk).
|
||||
First of all please install the [Intel SGX SDK](https://software.intel.com/en-us/sgx/sdk).
|
||||
|
||||
After installing dependencies, build the source code:
|
||||
``` Bash
|
||||
source <SGX_SDK dir>/environment
|
||||
cd core/iwasm/products/linux-sgx/
|
||||
cd product-mini/platforms/linux-sgx/
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
@ -64,7 +96,7 @@ source <SGX_SDK dir>/environment
|
||||
./app
|
||||
```
|
||||
|
||||
Mac
|
||||
MacOS
|
||||
-------------------------
|
||||
Make sure to install Xcode from App Store firstly, and install cmake.
|
||||
|
||||
@ -75,12 +107,14 @@ brew install cmake
|
||||
|
||||
Then build the source codes:
|
||||
```
|
||||
cd core/iwasm/products/darwin/
|
||||
cd product-mini/platforms/darwin/
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
make
|
||||
```
|
||||
Note:
|
||||
WAMR provides some features which can be easily configured by passing options to cmake, please see [Linux platform](./build_wamr.md#linux) for details. Currently in MacOS, interpreter, AoT, and builtin libc are enabled by default.
|
||||
|
||||
VxWorks
|
||||
-------------------------
|
||||
@ -93,7 +127,7 @@ export <vsb_dir_path>/host/vx-compiler/bin:$PATH
|
||||
```
|
||||
Now switch to iwasm source tree to build the source code:
|
||||
```
|
||||
cd core/iwasm/products/vxworks/
|
||||
cd product-mini/platforms/vxworks/
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
@ -109,13 +143,8 @@ Copy the generated iwasm executable, the test WASM binary as well as the needed
|
||||
shared libraries (libc.so.1, libllvm.so.1 or libgnu.so.1 depending on the VSB,
|
||||
libunix.so.1) to a supported file system (eg: romfs).
|
||||
|
||||
WASI
|
||||
-------------------------
|
||||
On Linux, WASI is enabled by default. To build iwasm without wasi support, pass an option when you run cmake:
|
||||
```
|
||||
cmake .. -DWASM_ENABLE_WASI=0
|
||||
make
|
||||
```
|
||||
Note:
|
||||
WAMR provides some features which can be easily configured by passing options to cmake, please see [Linux platform](./build_wamr.md#linux) for details. Currently in VxWorks, interpreter and builtin libc are enabled by default.
|
||||
|
||||
Zephyr
|
||||
-------------------------
|
||||
@ -123,15 +152,17 @@ You need to download the Zephyr source code first and embed WAMR into it.
|
||||
``` Bash
|
||||
git clone https://github.com/zephyrproject-rtos/zephyr.git
|
||||
cd zephyr/samples/
|
||||
cp -a <iwasm_dir>/products/zephyr/simple .
|
||||
cp -a <wamr_root_dir>/product-mini/platforms/zephyr/simple .
|
||||
cd simple
|
||||
ln -s <iwam_dir> iwasm
|
||||
ln -s <shared_lib_dir> shared-lib
|
||||
ln -s <wamr_root_dir> wamr
|
||||
mkdir build && cd build
|
||||
source ../../../zephyr-env.sh
|
||||
cmake -GNinja -DBOARD=qemu_x86 ..
|
||||
cmake -GNinja -DBOARD=qemu_x86_nommu ..
|
||||
ninja
|
||||
```
|
||||
Note:
|
||||
WAMR provides some features which can be easily configured by passing options to cmake, please see [Linux platform](./build_wamr.md#linux) for details. Currently in Zephyr, interpreter, AoT and builtin libc are enabled by default.
|
||||
|
||||
|
||||
AliOS-Things
|
||||
-------------------------
|
||||
@ -140,19 +171,15 @@ AliOS-Things
|
||||
``` Bash
|
||||
git clone https://github.com/alibaba/AliOS-Things.git
|
||||
```
|
||||
3. copy <iwasm_root_dir>/products/alios-things directory to AliOS-Things/middleware, and rename it as iwasm
|
||||
3. copy <wamr_root_dir>/product-mini/platforms/alios-things directory to AliOS-Things/middleware, and rename it as iwasm
|
||||
``` Bash
|
||||
cp -a <iwasm_root_dir>/products/alios-things middleware/iwasm
|
||||
cp -a <wamr_root_dir>/product-mini/platforms/alios-things middleware/iwasm
|
||||
```
|
||||
4. create a link to <iwasm_root_dir> in middleware/iwasm/ and rename it to iwasm
|
||||
4. create a link to <wamr_root_dir> in middleware/iwasm/ and rename it to wamr
|
||||
``` Bash
|
||||
ln -s <iwasm_root_dir> middleware/iwasm/iwasm
|
||||
ln -s <wamr_root_dir> middleware/iwasm/wamr
|
||||
```
|
||||
5. create a link to <shared-lib_root_dir> in middleware/iwasm/ and rename it to shared-lib
|
||||
``` Bash
|
||||
ln -s <shared-lib_root_dir> middleware/iwasm/shared-lib
|
||||
```
|
||||
6. modify file app/example/helloworld/helloworld.c, patch as:
|
||||
5. modify file app/example/helloworld/helloworld.c, patch as:
|
||||
``` C
|
||||
#include <stdbool.h>
|
||||
#include <aos/kernel.h>
|
||||
@ -164,11 +191,11 @@ AliOS-Things
|
||||
...
|
||||
}
|
||||
```
|
||||
7. modify file app/example/helloworld/aos.mk
|
||||
6. modify file app/example/helloworld/aos.mk
|
||||
``` C
|
||||
$(NAME)_COMPONENTS := osal_aos iwasm
|
||||
```
|
||||
8. build source code and run
|
||||
7. build source code and run
|
||||
For linuxhost:
|
||||
``` Bash
|
||||
aos make helloworld@linuxhost -c config
|
||||
@ -179,7 +206,7 @@ AliOS-Things
|
||||
For developerkit:
|
||||
Modify file middleware/iwasm/aos.mk, patch as:
|
||||
``` C
|
||||
BUILD_TARGET := THUMBV7M
|
||||
WAMR_BUILD_TARGET := THUMBV7M
|
||||
```
|
||||
|
||||
``` Bash
|
||||
|
||||
@ -1,10 +1,18 @@
|
||||
|
||||
|
||||
Build WASM app
|
||||
# Prepare WASM building environments
|
||||
|
||||
WASI-SDK version 7.0+ is the major tool supported by WAMR for building WASM applications. There are some other WASM compilers such as the standard clang compiler and Emscripten might also work [here](./other_wasm_compilers.md).
|
||||
|
||||
Install WASI SDK: Download the [wasi-sdk](https://github.com/CraneStation/wasi-sdk/releases) and extract the archive to default path `/opt/wasi-sdk`
|
||||
|
||||
|
||||
Build WASM applications
|
||||
=========================
|
||||
|
||||
You can write a simple ```test.c``` as the first sample.
|
||||
|
||||
```C
|
||||
``` C
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
@ -30,146 +38,89 @@ int main(int argc, char **argv)
|
||||
}
|
||||
```
|
||||
|
||||
There are several methods to build a WASM binary. They are the clang compiler, Docker, Emscripten and so on.
|
||||
|
||||
## Use clang compiler
|
||||
|
||||
The recommended method to build a WASM binary is to use clang compiler ```clang-8```. You can refer to [apt.llvm.org](https://apt.llvm.org) for the detailed instructions. Here are referenced steps to install clang-8 in Ubuntu 16.04 and Ubuntu 18.04.
|
||||
To build the source file to WASM bytecode, input following command:
|
||||
|
||||
(1) Add source to your system source list from llvm website
|
||||
|
||||
For Ubuntu 16.04, add the following lines to /etc/apt/sources.list:
|
||||
|
||||
```Bash
|
||||
deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial main
|
||||
deb-src http://apt.llvm.org/xenial/ llvm-toolchain-xenial main
|
||||
# 8
|
||||
deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-8 main
|
||||
deb-src http://apt.llvm.org/xenial/ llvm-toolchain-xenial-8 main
|
||||
# 9
|
||||
deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-9 main
|
||||
deb-src http://apt.llvm.org/xenial/ llvm-toolchain-xenial-9 main
|
||||
``` Bash
|
||||
/opt/wasi-sdk/bin/clang test.c -o test.wasm
|
||||
```
|
||||
|
||||
For Ubuntu 18.04, add the following lines to /etc/apt/sources.list:
|
||||
|
||||
```Bash
|
||||
# i386 not available
|
||||
deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic main
|
||||
deb-src http://apt.llvm.org/bionic/ llvm-toolchain-bionic main
|
||||
# 8
|
||||
deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-8 main
|
||||
deb-src http://apt.llvm.org/bionic/ llvm-toolchain-bionic-8 main
|
||||
# 9
|
||||
deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-9 main
|
||||
deb-src http://apt.llvm.org/bionic/ llvm-toolchain-bionic-9 main
|
||||
```
|
||||
# Build a project with cmake
|
||||
|
||||
(2) Download and install clang-8 tool-chain using following commands:
|
||||
If you have complex WASM application project which contains dozens of source files, you can consider using cmake for project building.
|
||||
|
||||
```Bash
|
||||
sudo wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key|sudo apt-key add -
|
||||
# Fingerprint: 6084 F3CF 814B 57C1 CF12 EFD5 15CF 4D18 AF4F 7421
|
||||
sudo apt-get update
|
||||
sudo apt-get install llvm-8 lld-8 clang-8
|
||||
```
|
||||
|
||||
(3) Create a soft link under /usr/bin:
|
||||
|
||||
```Bash
|
||||
cd /usr/bin
|
||||
sudo ln -s wasm-ld-8 wasm-ld
|
||||
```
|
||||
|
||||
(4) Use the clang-8 command below to build the WASM C source code into the WASM binary.
|
||||
|
||||
```Bash
|
||||
clang-8 --target=wasm32 -O3 \
|
||||
-z stack-size=4096 -Wl,--initial-memory=65536 \
|
||||
-Wl,--allow-undefined,--export=main \
|
||||
-Wl,--strip-all,--no-entry -nostdlib \
|
||||
-o test.wasm test.c
|
||||
```
|
||||
|
||||
You will get ```test.wasm``` which is the WASM app binary.
|
||||
|
||||
## Use cmake
|
||||
|
||||
If you have a cmake project, you can cross compile your project by using the toolchain provided by WAMR, the compiler used by WAMR toolchain is `clang-8`.
|
||||
You can cross compile your project by using the toolchain provided by WAMR.
|
||||
|
||||
We can generate a `CMakeLists.txt` file for `test.c`:
|
||||
```cmake
|
||||
|
||||
``` cmake
|
||||
cmake_minimum_required (VERSION 3.5)
|
||||
project(hello_world)
|
||||
|
||||
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS},--export=main")
|
||||
add_executable(hello_world test.c)
|
||||
```
|
||||
It is quite simple to build this project by cmake:
|
||||
```Bash
|
||||
|
||||
It is simple to build this project by cmake:
|
||||
|
||||
``` Bash
|
||||
mkdir build && cd build
|
||||
cmake .. -DCMAKE_TOOLCHAIN_FILE=$WAMR_ROOT/test-tools/toolchain/wamr_toolchain.cmake
|
||||
cmake .. -DCMAKE_TOOLCHAIN_FILE=$WAMR_ROOT/wamr-sdk/app/wamr_toolchain.cmake
|
||||
make
|
||||
```
|
||||
|
||||
You will get ```hello_world``` which is the WASM app binary.
|
||||
|
||||
For more details about wamr toolchain, please refer to [test-tools/toolchain](../test-tools/toolchain/README.md).
|
||||
> Note: If you have already built a SDK profile, then the **DCMAKE_TOOLCHAIN_FILE** should be changed into `$WAMR_ROOT/wamr-sdk/out/${PROFILE}/app-sdk/wamr_toolchain.cmake`
|
||||
|
||||
## Use wasi-sdk
|
||||
|
||||
To build a wasm application with wasi support, wasi-sdk is required. Download the [wasi-sdk](https://github.com/CraneStation/wasi-sdk/releases) and extract the archive, then you can use it to build your application:
|
||||
```Bash
|
||||
/path/to/wasi-sdk/bin/clang test.c -o test.wasm
|
||||
```
|
||||
# Compile WASM to AoT module
|
||||
|
||||
You will get ```test.wasm``` which is the WASM app binary.
|
||||
Please ensure the wamrc was already generated and available in your shell PATH. Then we can use wamrc to compile WASM app binary to WAMR AoT binary.
|
||||
|
||||
## Using Docker
|
||||
|
||||
Another method availble is using [Docker](https://www.docker.com/). We assume you've already configured Docker (see Platform section above) and have a running interactive shell. Currently the Dockerfile only supports compiling apps with clang, with Emscripten planned for the future.
|
||||
|
||||
Use the clang-8 command below to build the WASM C source code into the WASM binary.
|
||||
|
||||
```Bash
|
||||
clang-8 --target=wasm32 -O3 \
|
||||
-z stack-size=4096 -Wl,--initial-memory=65536 \
|
||||
-Wl,--allow-undefined,--export=main \
|
||||
-Wl,--strip-all,--no-entry -nostdlib \
|
||||
-o test.wasm test.c
|
||||
```
|
||||
|
||||
You will get ```test.wasm``` which is the WASM app binary.
|
||||
|
||||
## Use Emscripten tool
|
||||
|
||||
The last method to build a WASM binary is to use Emscripten tool ```emcc```.
|
||||
Assuming you are using Linux, you may install emcc from Emscripten EMSDK following the steps below:
|
||||
|
||||
```
|
||||
git clone https://github.com/emscripten-core/emsdk.git
|
||||
cd emsdk
|
||||
./emsdk install latest-fastcomp
|
||||
./emsdk activate latest-fastcomp
|
||||
```
|
||||
The Emscripten website provides other installation methods beyond Linux.
|
||||
|
||||
Use the emcc command below to build the WASM C source code into the WASM binary.
|
||||
``` Bash
|
||||
cd emsdk
|
||||
source emsdk_env.sh (or add it to ~/.bashrc if you don't want to run it each time)
|
||||
cd <dir of test.c>
|
||||
EMCC_ONLY_FORCED_STDLIBS=1 emcc -g -O3 -s WASM=1 -s ERROR_ON_UNDEFINED_SYMBOLS=0 \
|
||||
-s TOTAL_MEMORY=65536 -s TOTAL_STACK=4096 \
|
||||
-s ASSERTIONS=1 -s STACK_OVERFLOW_CHECK=2 \
|
||||
-s "EXPORTED_FUNCTIONS=['_main']" -o test.wasm test.c
|
||||
wamrc -o test.aot test.wasm
|
||||
```
|
||||
You will get ```test.wasm``` which is the WASM app binary.
|
||||
|
||||
Run WASM app
|
||||
wamrc supports a number of compilation options through the command line arguments:
|
||||
|
||||
``` Bash
|
||||
wamrc --help
|
||||
Usage: wamrc [options] -o output_file wasm_file
|
||||
--target=<arch-name> Set the target arch, which has the general format: <arch><sub>
|
||||
<arch> = x86_64, i386, arm, thumb, mips.
|
||||
Default is host arch, e.g. x86_64
|
||||
<sub> = for ex. on arm or thumb: v5, v6m, v7a, v7m, etc.
|
||||
Use --target=help to list supported targets
|
||||
--cpu=<cpu> Set the target CPU (default: host CPU, e.g. skylake)
|
||||
Use --target=help to list all the CPU supported
|
||||
--cpu-features=<features> Enable or disable the CPU features
|
||||
Use +feature to enable a feature, or -feature to disable it
|
||||
For example, --cpu-features=+feature1,-feature2
|
||||
Use --cpu-features=+help to list all the features supported
|
||||
--opt-level=n Set the optimization level (0 to 3, default: 3)
|
||||
--format=<format> Specifies the format of the output file
|
||||
The format supported:
|
||||
aot (default) AoT file
|
||||
object Native object file
|
||||
llvmir-unopt Unoptimized LLVM IR
|
||||
llvmir-opt Optimized LLVM IR
|
||||
Examples: wamrc -o test.aot test.wasm
|
||||
wamrc --target=i386 -o test.aot test.wasm
|
||||
wamrc --target=i386 --format=object -o test.o test.wasm
|
||||
|
||||
```
|
||||
|
||||
|
||||
Run WASM app in WAMR mini product build
|
||||
========================
|
||||
|
||||
Assume you are using Linux, the command to run the test.wasm is:
|
||||
Run the test.wasm or test.aot with WAMR mini product build:
|
||||
``` Bash
|
||||
cd iwasm/products/linux/build
|
||||
./iwasm test.wasm
|
||||
./iwasm test.wasm or
|
||||
./iwasm test.aot
|
||||
```
|
||||
You will get the following output:
|
||||
```
|
||||
|
||||
@ -8,31 +8,34 @@ A typical WAMR API usage is shown below (some return value checks are ignored):
|
||||
``` C
|
||||
static char global_heap_buf[512 * 1024];
|
||||
|
||||
char *buffer;
|
||||
char *buffer, error_buf[128];
|
||||
wasm_module_t module;
|
||||
wasm_module_inst_t inst;
|
||||
wasm_module_inst_t module_inst;
|
||||
wasm_function_inst_t func;
|
||||
wasm_exec_env_t env;
|
||||
uint32 argv[2];
|
||||
wasm_exec_env_t exec_env;
|
||||
uint32 argv[2], size, stack_size = 8092, heap_size = 8092;
|
||||
|
||||
bh_memory_init_with_pool(global_heap_buf, sizeof(global_heap_buf));
|
||||
wasm_runtime_init();
|
||||
|
||||
buffer = read_wasm_binary_to_buffer(…);
|
||||
module = wasm_runtime_load(buffer, size, err, err_size);
|
||||
inst = wasm_runtime_instantiate(module, 0, 0, err, err_size);
|
||||
func = wasm_runtime_lookup_function(inst, "fib", "(i32)i32");
|
||||
env = wasm_runtime_create_exec_env(stack_size);
|
||||
buffer = read_wasm_binary_to_buffer(…, &size);
|
||||
module = wasm_runtime_load(buffer, size, error_buf, sizeof(error_buf));
|
||||
module_inst = wasm_runtime_instantiate(module, stack_size, heap_size,
|
||||
error_buf, sizeof(error_buf));
|
||||
func = wasm_runtime_lookup_function(module_inst, "fib", "(i32)i32");
|
||||
exec_env = wasm_runtime_create_exec_env(module_inst, stack_size);
|
||||
|
||||
argv[0] = 8;
|
||||
if (!wasm_runtime_call_wasm(inst, env, func, 1, argv_buf) ) {
|
||||
wasm_runtime_clear_exception(inst);
|
||||
if (wasm_runtime_call_wasm(exec_env, func, 1, argv_buf) ) {
|
||||
/* the return value is stored in argv[0] */
|
||||
printf("fib function return: %d\n", argv[0]);
|
||||
}
|
||||
else {
|
||||
printf("%s\n", wasm_runtime_get_exception(module_inst));
|
||||
}
|
||||
/* the return value is stored in argv[0] */
|
||||
printf("fib function return: %d\n", argv[0]);
|
||||
|
||||
wasm_runtime_destroy_exec_env(env);
|
||||
wasm_runtime_deinstantiate(inst);
|
||||
wasm_runtime_destroy_exec_env(exec_env);
|
||||
wasm_runtime_deinstantiate(module_inst);
|
||||
wasm_runtime_unload(module);
|
||||
wasm_runtime_destroy();
|
||||
bh_memory_destroy();
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
|
||||
The mechanism of exporting native API to WASM application
|
||||
Export native API to WASM application
|
||||
=======================================================
|
||||
|
||||
The basic working flow for WASM application calling into the native API is shown in the following diagram:
|
||||
@ -21,16 +21,105 @@ static NativeSymbol extended_native_symbol_defs[] = {
|
||||
};
|
||||
```
|
||||
|
||||
 **Security attention:** A WebAssembly application should only have access to its own memory space. As a result, the integrator should carefully design the native function to ensure that the memory accesses are safe. The native API to be exported to the WASM application must:
|
||||
**Security attention:** A WebAssembly application should only have access to its own memory space. As a result, the integrator should carefully design the native function to ensure that the memory accesses are safe. The native API to be exported to the WASM application must:
|
||||
|
||||
- Only use 32 bits number for parameters
|
||||
- Should not pass data to the structure pointer (do data serialization instead)
|
||||
- Should do the pointer address conversion in the native API
|
||||
- Should not pass function pointer as callback
|
||||
|
||||
|
||||
|
||||
Below is a sample of a library extension. All code invoked across WASM and native world must be serialized and de-serialized, and the native world must do a boundary check for every incoming address from the WASM world.
|
||||
|
||||
In wasm world:
|
||||
``` C
|
||||
void api_send_request(request_t * request, response_handler_f response_handler,
|
||||
void * user_data)
|
||||
{
|
||||
int size;
|
||||
char *buffer;
|
||||
transaction_t *trans;
|
||||
|
||||
if ((trans = (transaction_t *) malloc(sizeof(transaction_t))) == NULL) {
|
||||
printf(
|
||||
"send request: allocate memory for request transaction failed!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
memset(trans, 0, sizeof(transaction_t));
|
||||
trans->handler = response_handler;
|
||||
trans->mid = request->mid;
|
||||
trans->time = wasm_get_sys_tick_ms();
|
||||
trans->user_data = user_data;
|
||||
|
||||
// pack request
|
||||
if ((buffer = pack_request(request, &size)) == NULL) {
|
||||
printf("send request: pack request failed!\n");
|
||||
free(trans);
|
||||
return;
|
||||
}
|
||||
|
||||
transaction_add(trans);
|
||||
|
||||
/* if the trans is the 1st one, start the timer */
|
||||
if (trans == g_transactions) {
|
||||
/* assert(g_trans_timer == NULL); */
|
||||
if (g_trans_timer == NULL) {
|
||||
g_trans_timer = api_timer_create(TRANSACTION_TIMEOUT_MS,
|
||||
false,
|
||||
true, transaction_timeout_handler);
|
||||
}
|
||||
}
|
||||
|
||||
// call native API
|
||||
wasm_post_request(buffer, size);
|
||||
|
||||
free_req_resp_packet(buffer);
|
||||
}
|
||||
```
|
||||
|
||||
In native world:
|
||||
``` C
|
||||
void
|
||||
wasm_post_request(wasm_exec_env_t exec_env,
|
||||
int32 buffer_offset, int size)
|
||||
{
|
||||
wasm_module_inst_t module_inst = get_module_inst(exec_env);
|
||||
char *buffer = NULL;
|
||||
|
||||
// do boundary check
|
||||
if (!validate_app_addr(buffer_offset, size))
|
||||
return;
|
||||
|
||||
// do address conversion
|
||||
buffer = addr_app_to_native(buffer_offset);
|
||||
|
||||
if (buffer != NULL) {
|
||||
request_t req[1];
|
||||
|
||||
// De-serialize data
|
||||
if (!unpack_request(buffer, size, req))
|
||||
return;
|
||||
|
||||
// set sender to help dispatch the response to the sender app later
|
||||
unsigned int mod_id = app_manager_get_module_id(Module_WASM_App,
|
||||
module_inst);
|
||||
bh_assert(mod_id != ID_NONE);
|
||||
req->sender = mod_id;
|
||||
|
||||
if (req->action == COAP_EVENT) {
|
||||
am_publish_event(req);
|
||||
return;
|
||||
}
|
||||
|
||||
am_dispatch_request(req);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
<img src="./pics/safe.PNG" width="90%">
|
||||
|
||||
|
||||
Steps for exporting native API
|
||||
@ -38,79 +127,77 @@ Steps for exporting native API
|
||||
|
||||
WAMR implemented a framework for developers to export API's. Below is the procedure to expose the platform API's in three steps:
|
||||
|
||||
**Step 1. Create a header file**<br/>
|
||||
Declare the API's for your WASM application source project to include.
|
||||
|
||||
**Step 2. Create a source file**<br/>
|
||||
Export the platform API's, for example in ``` products/linux/ext_lib_export.c ```
|
||||
## Step 1: Define the native API for exporting
|
||||
|
||||
Define the function **example_native_func** in your source file, namely `example.c` here:
|
||||
``` C
|
||||
#include "lib_export.h"
|
||||
|
||||
static NativeSymbol extended_native_symbol_defs[] =
|
||||
int example_native_func(wasm_exec_env_t exec_env,
|
||||
int arg1, int arg2)
|
||||
{
|
||||
};
|
||||
|
||||
#include "ext_lib_export.h"
|
||||
```
|
||||
|
||||
**Step 3. Register new API's**<br/>
|
||||
Use the macro `EXPORT_WASM_API` and `EXPORT_WASM_API2` to add exported API's into the array of ```extended_native_symbol_defs```.
|
||||
The pre-defined MACRO `EXPORT_WASM_API` should be used to declare a function export:
|
||||
``` c
|
||||
#define EXPORT_WASM_API(symbol) {#symbol, symbol}
|
||||
```
|
||||
|
||||
Below code example shows how to extend the library to support `customized()`:
|
||||
|
||||
```
|
||||
//lib_export_impl.c
|
||||
void customized()
|
||||
{
|
||||
// your code
|
||||
// Your implementation here
|
||||
}
|
||||
```
|
||||
The first function argument must be defined using type **wasm_exec_env_t** which is the WAMR calling convention for native API exporting.
|
||||
|
||||
|
||||
// lib_export_dec.h
|
||||
#ifndef _LIB_EXPORT_DEC_H_
|
||||
#define _LIB_EXPORT_DEC_H_
|
||||
The function prototype should also be declared in a header file so the wasm application can include it.
|
||||
``` C
|
||||
#ifndef _EXAMPLE_H_
|
||||
#define _EXAMPLE_H_
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void customized();
|
||||
void example_native_func(int arg1, int arg2);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
```
|
||||
|
||||
## Step 2: Declare the native API exporting
|
||||
|
||||
// ext_lib_export.c
|
||||
#include "lib_export.h"
|
||||
#include "lib_export_dec.h"
|
||||
Declare the function **example_native_func** with macro **EXPORT_WASM_API** in your **.inl** file, namely `example.inl` in this sample.
|
||||
``` C
|
||||
EXPORT_WASM_API(example_native_func),
|
||||
```
|
||||
|
||||
static NativeSymbol extended_native_symbol_defs[] =
|
||||
{
|
||||
EXPORT_WASM_API(customized)
|
||||
Then include the file **example.inl** in definition of array **extended_native_symbol_defs** in the `ext_lib_export.c`.
|
||||
``` C
|
||||
static NativeSymbol extended_native_symbol_defs[] = {
|
||||
#include "example.inl"
|
||||
};
|
||||
|
||||
#include "ext_lib_export.h"
|
||||
```
|
||||
|
||||
Use extended library
|
||||
------------------------
|
||||
In the application source project, it will include the WAMR built-in API's header file and platform extension header files. Assuming the board vendor extends the library which added an API called customized(), the WASM application would be like this:
|
||||
|
||||
## Step 3: Compile the runtime product
|
||||
Add the source file **example.c** and **ext_lib_export.c** into the CMakeList.txt for building runtime with the exported API's:
|
||||
``` cmake
|
||||
set (EXT_API_SOURCE example.c)
|
||||
|
||||
add_executable (sample
|
||||
# other source files
|
||||
# ......
|
||||
${EXT_API_SOURCE}
|
||||
ext_lib_export.c
|
||||
)
|
||||
```
|
||||
|
||||
# Use exported API in wasm application
|
||||
|
||||
We can call the exported native API **example_native_func** in wasm application like this:
|
||||
``` C
|
||||
#include <stdio.h>
|
||||
#include "lib_export_dec.h" // provided by the platform vendor
|
||||
#include "example.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int I;
|
||||
char *buf = “abcd”;
|
||||
customized(); // customized API provided by the platform vendor
|
||||
return i;
|
||||
int a = 0, b = 1;
|
||||
|
||||
example_native_func(a, b);
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
@ -1,13 +0,0 @@
|
||||
Current memory usage, take samples/littlevgl in Zephyr for example:
|
||||
(1) WASM app binary: 142K for littlevgl ui_app.wasm
|
||||
(2) WASM app memory space: 64K for littlevgl ui_app.wasm
|
||||
(3) WASM app heap space: 8K by default
|
||||
(4) WASM app thread native stack: 4K by default
|
||||
(5) WASM interpreter stack: 8K by default
|
||||
(6) WASM block address hash cache: 3K
|
||||
(7) timer thread stack: 4K
|
||||
(8) sensor thread stack: 4K
|
||||
(9) touch screen thread stack: 4K
|
||||
(10) others: vm, app mgr, queue, native lib: ~22K
|
||||
|
||||
Total memory usage: ~263K
|
||||
115
doc/other_wasm_compilers.md
Normal file
115
doc/other_wasm_compilers.md
Normal file
@ -0,0 +1,115 @@
|
||||
|
||||
|
||||
## Use clang compiler
|
||||
|
||||
The recommended method to build a WASM binary is to use clang compiler ```clang-8```. You can refer to [apt.llvm.org](https://apt.llvm.org) for the detailed instructions. Here are referenced steps to install clang-8 in Ubuntu 16.04 and Ubuntu 18.04.
|
||||
|
||||
(1) Add source to your system source list from llvm website
|
||||
|
||||
For Ubuntu 16.04, add the following lines to /etc/apt/sources.list:
|
||||
|
||||
``` Bash
|
||||
deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial main
|
||||
deb-src http://apt.llvm.org/xenial/ llvm-toolchain-xenial main
|
||||
# 8
|
||||
deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-8 main
|
||||
deb-src http://apt.llvm.org/xenial/ llvm-toolchain-xenial-8 main
|
||||
# 9
|
||||
deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-9 main
|
||||
deb-src http://apt.llvm.org/xenial/ llvm-toolchain-xenial-9 main
|
||||
```
|
||||
|
||||
For Ubuntu 18.04, add the following lines to /etc/apt/sources.list:
|
||||
|
||||
``` Bash
|
||||
# i386 not available
|
||||
deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic main
|
||||
deb-src http://apt.llvm.org/bionic/ llvm-toolchain-bionic main
|
||||
# 8
|
||||
deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-8 main
|
||||
deb-src http://apt.llvm.org/bionic/ llvm-toolchain-bionic-8 main
|
||||
# 9
|
||||
deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-9 main
|
||||
deb-src http://apt.llvm.org/bionic/ llvm-toolchain-bionic-9 main
|
||||
```
|
||||
|
||||
(2) Download and install clang-8 tool-chain using following commands:
|
||||
|
||||
``` Bash
|
||||
sudo wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key|sudo apt-key add -
|
||||
# Fingerprint: 6084 F3CF 814B 57C1 CF12 EFD5 15CF 4D18 AF4F 7421
|
||||
sudo apt-get update
|
||||
sudo apt-get install llvm-8 lld-8 clang-8
|
||||
```
|
||||
|
||||
(3) Create a soft link under /usr/bin:
|
||||
|
||||
``` Bash
|
||||
cd /usr/bin
|
||||
sudo ln -s wasm-ld-8 wasm-ld
|
||||
```
|
||||
|
||||
(4) Use the clang-8 command below to build the WASM C source code into the WASM binary.
|
||||
|
||||
``` Bash
|
||||
clang-8 --target=wasm32 -O3 \
|
||||
-z stack-size=4096 -Wl,--initial-memory=65536 \
|
||||
-Wl,--allow-undefined,--export=main \
|
||||
-Wl,--strip-all,--no-entry -nostdlib \
|
||||
-o test.wasm test.c
|
||||
```
|
||||
|
||||
You will get ```test.wasm``` which is the WASM app binary.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## Use Emscripten tool
|
||||
|
||||
The last method to build a WASM binary is to use Emscripten tool ```emcc```.
|
||||
Assuming you are using Linux, you may install emcc from Emscripten EMSDK following the steps below:
|
||||
|
||||
```
|
||||
git clone https://github.com/emscripten-core/emsdk.git
|
||||
cd emsdk
|
||||
./emsdk install latest-fastcomp
|
||||
./emsdk activate latest-fastcomp
|
||||
```
|
||||
|
||||
The Emscripten website provides other installation methods beyond Linux.
|
||||
|
||||
Use the emcc command below to build the WASM C source code into the WASM binary.
|
||||
|
||||
``` Bash
|
||||
cd emsdk
|
||||
source emsdk_env.sh (or add it to ~/.bashrc if you don't want to run it each time)
|
||||
cd <dir of test.c>
|
||||
EMCC_ONLY_FORCED_STDLIBS=1 emcc -g -O3 -s WASM=1 -s ERROR_ON_UNDEFINED_SYMBOLS=0 \
|
||||
-s TOTAL_MEMORY=65536 -s TOTAL_STACK=4096 \
|
||||
-s ASSERTIONS=1 -s STACK_OVERFLOW_CHECK=2 \
|
||||
-s "EXPORTED_FUNCTIONS=['_main']" -o test.wasm test.c
|
||||
```
|
||||
|
||||
You will get ```test.wasm``` which is the WASM app binary.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## Using Docker
|
||||
|
||||
Another method availble is using [Docker](https://www.docker.com/). We assume you've already configured Docker (see Platform section above) and have a running interactive shell. Currently the Dockerfile only supports compiling apps with clang, with Emscripten planned for the future.
|
||||
|
||||
Use the clang-8 command below to build the WASM C source code into the WASM binary.
|
||||
|
||||
``` Bash
|
||||
clang-8 --target=wasm32 -O3 \
|
||||
-z stack-size=4096 -Wl,--initial-memory=65536 \
|
||||
-Wl,--allow-undefined,--export=main \
|
||||
-Wl,--strip-all,--no-entry -nostdlib \
|
||||
-o test.wasm test.c
|
||||
```
|
||||
|
||||
You will get ```test.wasm``` which is the WASM app binary.
|
||||
|
||||
BIN
doc/pics/wamr_menu_config.png
Normal file
BIN
doc/pics/wamr_menu_config.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 58 KiB |
48
doc/port_wamr.md
Normal file
48
doc/port_wamr.md
Normal file
@ -0,0 +1,48 @@
|
||||
|
||||
WAMR porting guide
|
||||
=========================
|
||||
|
||||
|
||||
This document describes how to port WAMR to a new platform "**super-os**"
|
||||
|
||||
|
||||
|
||||
# Step 1: Create folders for the new platform
|
||||
|
||||
-------------------------
|
||||
Create folders:
|
||||
- **core/shared/platform/super-os**: for platform API layer implementations
|
||||
- **product-mini/platforms/super-os**: for the platform mini product build
|
||||
|
||||
# Step 2: Implement platform API layer
|
||||
|
||||
-------------------------
|
||||
Implement folder core/shared/platform/super-os. Normally in this folder you should implement the following files:
|
||||
- bh_platform.h and bh_platform.c: define the platform related macros, data types and APIs.
|
||||
- bh_assert.c: implement function bh_assert_internal() and bh_debug_internal().
|
||||
- bh_definition.c: implement function b_memcpy_s, b_strcat_s and b_strcpy_s. And implement fopen_s
|
||||
if we need to read wasm file from file system.
|
||||
- bh_platform_log.c: implement function bh_log_emit, bh_fprintf and bh_fflush.
|
||||
- bh_time.c: implement several time related functions.
|
||||
- bh_thread.c: implement thread, mutex, condition related functions.
|
||||
- bh_math.c: implement some math functions if the platform doesn't support them, e.g. sqrt,
|
||||
fabs and isnan. We may use the open source fdlibm implementation, for example,
|
||||
ref to platform/zephyr/bh_math.c.
|
||||
|
||||
Please ref to implementation of other platform for more details, e.g. platform/zephyr, platform/linux.
|
||||
|
||||
# Step 3: Create the mini product build for the platform
|
||||
|
||||
-------------------------
|
||||
Implement folder product-mini/platforms/super-os. Normally this folder is to implement the C main function, and generate a WAMR VM core binary named iwasm which can load and run wasm apps. We should implement following files:
|
||||
- main.c: implement the C main function, which reads wasm file to buffer, loads the wasm file to wasm module, instantiate the module, lookup wasm app main function, and then execute the function.
|
||||
- ext_lib_export.c: implement the native APIs if you want, and if no native API is to be implemented, just keep array extended_native_symbol_defs empty.
|
||||
- CMakeLists.txt: there are some settings which can be passed from cmake variables:
|
||||
- set (WAMR_BUILD_PLATFORM "platform_name"): set the name of the platform
|
||||
- set (WAMR_BUILD_TARGET <arch><sub>): set the build target, currently the value supported: X86_64, X86_32, ARM[sub], THUMB[sub], MIPS and XTENSA. For ARM and THUMB, you can specify the sub version, e.g. ARMV4, ARMV7, THUMBV4T, THUMBV7T.
|
||||
- set (WAMR_BUILD_INTERP 1 or 0): whether to interpreter or not
|
||||
- set (WAMR_BUILD_AOT 1 or 0): whether to build AOT or not
|
||||
- set (WAMR_BUILD_JIT 1 or 0): whether to build JIT or not
|
||||
- set (WAMR_BUILD_LIBC_BUILTIN 1 or 0): whether to build Libc builtin or not
|
||||
- set (WAMR_BUILD_LIBC_WASI 1 or 0): whether to build Libc WASI or not
|
||||
|
||||
@ -15,8 +15,6 @@ Major feature releases and contributors
|
||||
|
||||
- Contributor: JinZhou Zhu (Alibaba)
|
||||
|
||||
|
||||
|
||||
**May 24, 2019: Support memory usage profiler**
|
||||
|
||||
- Contributors Wenyong Huang (Intel)
|
||||
@ -57,4 +55,7 @@ Major feature releases and contributors
|
||||
|
||||
- Contributor: Jonathan Dong (Alibaba)
|
||||
|
||||
**Nov 2019: WASI support** (Intel)
|
||||
|
||||
**Jan 2020: Ahead of time and Just-in-Time compilation support** (Intel)
|
||||
|
||||
|
||||
@ -2,15 +2,22 @@
|
||||
# WebAssembly Micro Runtime Roadmap
|
||||
|
||||
|
||||
## Ahead of time compilation
|
||||
Status: under development. The first release is targetted to the end of 2019.
|
||||
|
||||
## WASI support
|
||||
Evaluated solution.
|
||||
|
||||
## Data serialization
|
||||
Evauating using cbor as the default data serialization
|
||||
Evaluating using cbor as the default data serialization
|
||||
|
||||
No plan yet.
|
||||
|
||||
|
||||
|
||||
## Threading
|
||||
Not started yet
|
||||
Plan: 2020 Q1
|
||||
|
||||
|
||||
|
||||
## AssemblyScript Support and API
|
||||
|
||||
Currently under evaluation
|
||||
|
||||
|
||||
|
||||
|
||||
337
doc/wamr_api.md
337
doc/wamr_api.md
@ -1,104 +1,66 @@
|
||||
|
||||
WAMR application library
|
||||
WAMR application framework
|
||||
========================
|
||||
|
||||
WAMR APP API includes built-in Libc API's, Base library and Extension library reference.
|
||||
|
||||
|
||||
**Libc API's**<br/>
|
||||
This is a minimal set of Libc API's for memory allocation, string manipulation and printing. The header file is located at ```lib/app-libs/libc/lib_base.h```. The current supported API set is listed here:
|
||||
## Application system callbacks
|
||||
The `on_init` and `on_destroy` functions are wamr application system callbacks which must be implemented in the wasm application if you want to use the APP framework.
|
||||
``` C
|
||||
void *malloc(size_t size);
|
||||
void *calloc(size_t n, size_t size);
|
||||
void free(void *ptr);
|
||||
int memcmp(const void *s1, const void *s2, size_t n);
|
||||
void *memcpy(void *dest, const void *src, size_t n);
|
||||
void *memmove(void *dest, const void *src, size_t n);
|
||||
void *memset(void *s, int c, size_t n);
|
||||
int putchar(int c);
|
||||
int snprintf(char *str, size_t size, const char *format, ...);
|
||||
int sprintf(char *str, const char *format, ...);
|
||||
char *strchr(const char *s, int c);
|
||||
int strcmp(const char *s1, const char *s2);
|
||||
char *strcpy(char *dest, const char *src);
|
||||
size_t strlen(const char *s);
|
||||
int strncmp(const char * str1, const char * str2, size_t n);
|
||||
char *strncpy(char *dest, const char *src, unsigned long n);
|
||||
void on_init()
|
||||
{
|
||||
/*
|
||||
Your init functions here, for example:
|
||||
* platform initialization
|
||||
* timer registration
|
||||
* service / event registration
|
||||
* ......
|
||||
*/
|
||||
}
|
||||
|
||||
void on_destroy()
|
||||
{
|
||||
/*
|
||||
your destroy functions here
|
||||
*/
|
||||
}
|
||||
```
|
||||
|
||||
**Base library**<br/>
|
||||
Basic support for communication, timers, etc is available. You can refer to the header file ```lib/app-libs/base/wasm_app.h``` which contains the definitions for request and response API's, event pub/sub API's and timer API's. Please note that these API's require the native implementations.
|
||||
The API set is listed below:
|
||||
## Base App library
|
||||
|
||||
The base library of application framework supports the essential API for WASM applications, such as inter-app communication, timers, etc. Other application framework components rely on the base library.
|
||||
|
||||
When building the WAMR SDK, once application framework is enabled, the base library will automatically enabled.
|
||||
|
||||
### Timer
|
||||
The *timer* API's can be used to create some `soft timers` with single-shot mode or periodic mode. Here is a reference of how to use timer API's to execute a function every one second.
|
||||
``` C
|
||||
typedef void(*request_handler_f)(request_t *) ;
|
||||
typedef void(*response_handler_f)(response_t *, void *) ;
|
||||
/* User global variable */
|
||||
static int num = 0;
|
||||
|
||||
// Request API's
|
||||
bool api_register_resource_handler(const char *url, request_handler_f);
|
||||
void api_send_request(request_t * request, response_handler_f response_handler, void * user_data);
|
||||
void api_response_send(response_t *response);
|
||||
/* Timer callback */
|
||||
void timer1_update(user_timer_t timer)
|
||||
{
|
||||
printf("Timer update %d\n", num++);
|
||||
}
|
||||
|
||||
// Event API's
|
||||
bool api_publish_event(const char *url, int fmt, void *payload, int payload_len);
|
||||
bool api_subscribe_event(const char * url, request_handler_f handler);
|
||||
void on_init()
|
||||
{
|
||||
user_timer_t timer;
|
||||
|
||||
struct user_timer;
|
||||
typedef struct user_timer * user_timer_t;
|
||||
/* set up a timer */
|
||||
timer = api_timer_create(1000, true, false, timer1_update);
|
||||
api_timer_restart(timer, 1000);
|
||||
}
|
||||
|
||||
// Timer API's
|
||||
user_timer_t api_timer_create(int interval, bool is_period, bool auto_start, void(*on_user_timer_update)(user_timer_t
|
||||
));
|
||||
void api_timer_cancel(user_timer_t timer);
|
||||
void api_timer_restart(user_timer_t timer, int interval);
|
||||
void on_destroy()
|
||||
{
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
**Library extension reference**<br/>
|
||||
Currently we provide several kinds of extension library for reference including sensor, connection and GUI.
|
||||
|
||||
Sensor API: In the header file ```lib/app-libs/extension/sensor/sensor.h```, the API set is defined as below:
|
||||
``` C
|
||||
sensor_t sensor_open(const char* name, int index,
|
||||
void(*on_sensor_event)(sensor_t, attr_container_t *, void *),
|
||||
void *user_data);
|
||||
bool sensor_config(sensor_t sensor, int interval, int bit_cfg, int delay);
|
||||
bool sensor_config_with_attr_container(sensor_t sensor, attr_container_t *cfg);
|
||||
bool sensor_close(sensor_t sensor);
|
||||
```
|
||||
Connection API: In the header file `lib/app-libs/extension/connection/connection.h.`, the API set is defined as below:
|
||||
``` C
|
||||
/* Connection event type */
|
||||
typedef enum {
|
||||
/* Data is received */
|
||||
CONN_EVENT_TYPE_DATA = 1,
|
||||
/* Connection is disconnected */
|
||||
CONN_EVENT_TYPE_DISCONNECT
|
||||
} conn_event_type_t;
|
||||
|
||||
typedef void (*on_connection_event_f)(connection_t *conn,
|
||||
conn_event_type_t type,
|
||||
const char *data,
|
||||
uint32 len,
|
||||
void *user_data);
|
||||
connection_t *api_open_connection(const char *name,
|
||||
attr_container_t *args,
|
||||
on_connection_event_f on_event,
|
||||
void *user_data);
|
||||
void api_close_connection(connection_t *conn);
|
||||
int api_send_on_connection(connection_t *conn, const char *data, uint32 len);
|
||||
bool api_config_connection(connection_t *conn, attr_container_t *cfg);
|
||||
```
|
||||
GUI API: The API's is list in header file ```lib/app-libs/extension/gui/wgl.h``` which is implemented based open soure 2D graphic library [LittlevGL](https://docs.littlevgl.com/en/html/index.html). Currently supported widgets include button, label, list and check box and more wigdet would be provided in future.
|
||||
|
||||
|
||||
Communication programming models
|
||||
=========================
|
||||
WAMR supports two typical communication programming models, the microservice model and the pub/sub model.
|
||||
|
||||
|
||||
Microservice model
|
||||
-------------------------
|
||||
### Micro-service model (request/response)
|
||||
The microservice model is also known as request and response model. One WASM application acts as the server which provides a specific service. Other WASM applications or host/cloud applications request that service and get the response.
|
||||
<img src="./pics/request.PNG" width="60%" height="60%">
|
||||
|
||||
<center><img src="./pics/request.PNG" width="60%" height="60%"></center>
|
||||
|
||||
Below is the reference implementation of the server application. It provides room temperature measurement service.
|
||||
|
||||
@ -136,11 +98,10 @@ void room_temp_handler(request_t *request)
|
||||
```
|
||||
|
||||
|
||||
Pub/sub model
|
||||
-------------------------
|
||||
### Pub/sub model
|
||||
One WASM application acts as the event publisher. It publishes events to notify WASM applications or host/cloud applications which subscribe to the events.
|
||||
|
||||
<img src="./pics/sub.PNG" width="60%" height="60%">
|
||||
<center><img src="./pics/sub.PNG" width="60%" height="60%"></center>
|
||||
|
||||
Below is the reference implementation of the pub application. It utilizes a timer to repeatedly publish an overheat alert event to the subscriber applications. Then the subscriber applications receive the events immediately.
|
||||
|
||||
@ -193,4 +154,198 @@ void on_destroy()
|
||||
{
|
||||
}
|
||||
```
|
||||
**Note:** You can also subscribe this event from host side by using host tool. Please refer `samples/simple` project for deail usage.
|
||||
**Note:** You can also subscribe this event from host side by using host tool. Please refer `samples/simple` project for detail usage.
|
||||
|
||||
|
||||
## Sensor API
|
||||
|
||||
The API set is defined in the header file ```core/app-framework/sensor/app/wa-inc/sensor.h```.
|
||||
|
||||
Here is a reference of how to use sensor API's:
|
||||
|
||||
``` C
|
||||
static sensor_t sensor = NULL;
|
||||
|
||||
/* Sensor event callback*/
|
||||
void sensor_event_handler(sensor_t sensor, attr_container_t *event,
|
||||
void *user_data)
|
||||
{
|
||||
printf("### app get sensor event\n");
|
||||
attr_container_dump(event);
|
||||
}
|
||||
|
||||
void on_init()
|
||||
{
|
||||
char *user_data;
|
||||
attr_container_t *config;
|
||||
|
||||
printf("### app on_init 1\n");
|
||||
/* open a sensor */
|
||||
user_data = malloc(100);
|
||||
printf("### app on_init 2\n");
|
||||
sensor = sensor_open("sensor_test", 0, sensor_event_handler, user_data);
|
||||
printf("### app on_init 3\n");
|
||||
|
||||
/* config the sensor */
|
||||
sensor_config(sensor, 1000, 0, 0);
|
||||
printf("### app on_init 4\n");
|
||||
}
|
||||
|
||||
void on_destroy()
|
||||
{
|
||||
if (NULL != sensor) {
|
||||
sensor_config(sensor, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Connection API:
|
||||
|
||||
The API set is defined in the header file `core/app-framework/connection/app/wa-inc/connection.h`
|
||||
|
||||
Here is a reference of how to use connection API's:
|
||||
``` C
|
||||
/* User global variable */
|
||||
static int num = 0;
|
||||
static user_timer_t g_timer;
|
||||
static connection_t *g_conn = NULL;
|
||||
|
||||
void on_data1(connection_t *conn,
|
||||
conn_event_type_t type,
|
||||
const char *data,
|
||||
uint32 len,
|
||||
void *user_data)
|
||||
{
|
||||
if (type == CONN_EVENT_TYPE_DATA) {
|
||||
char message[64] = {0};
|
||||
memcpy(message, data, len);
|
||||
printf("Client got a message from server -> %s\n", message);
|
||||
} else if (type == CONN_EVENT_TYPE_DISCONNECT) {
|
||||
printf("connection is close by server!\n");
|
||||
} else {
|
||||
printf("error: got unknown event type!!!\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* Timer callback */
|
||||
void timer1_update(user_timer_t timer)
|
||||
{
|
||||
char message[64] = {0};
|
||||
/* Reply to server */
|
||||
snprintf(message, sizeof(message), "Hello %d", num++);
|
||||
api_send_on_connection(g_conn, message, strlen(message));
|
||||
}
|
||||
|
||||
void my_close_handler(request_t * request)
|
||||
{
|
||||
response_t response[1];
|
||||
|
||||
if (g_conn != NULL) {
|
||||
api_timer_cancel(g_timer);
|
||||
api_close_connection(g_conn);
|
||||
}
|
||||
|
||||
make_response_for_request(request, response);
|
||||
set_response(response, DELETED_2_02, 0, NULL, 0);
|
||||
api_response_send(response);
|
||||
}
|
||||
|
||||
void on_init()
|
||||
{
|
||||
user_timer_t timer;
|
||||
attr_container_t *args;
|
||||
char *str = "this is client!";
|
||||
|
||||
api_register_resource_handler("/close", my_close_handler);
|
||||
|
||||
args = attr_container_create("");
|
||||
attr_container_set_string(&args, "address", "127.0.0.1");
|
||||
attr_container_set_uint16(&args, "port", 7777);
|
||||
|
||||
g_conn = api_open_connection("TCP", args, on_data1, NULL);
|
||||
if (g_conn == NULL) {
|
||||
printf("connect to server fail!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
printf("connect to server success! handle: %p\n", g_conn);
|
||||
|
||||
/* set up a timer */
|
||||
timer = api_timer_create(1000, true, false, timer1_update);
|
||||
api_timer_restart(timer, 1000);
|
||||
}
|
||||
|
||||
void on_destroy()
|
||||
{
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
## GUI API
|
||||
|
||||
The API's is listed in header file ```core/app-framework/wgl/app/wa-inc/wgl.h``` which is implemented based on open soure 2D graphic library [LittlevGL](https://docs.littlevgl.com/en/html/index.html).
|
||||
|
||||
``` C
|
||||
static void btn_event_cb(wgl_obj_t btn, wgl_event_t event);
|
||||
|
||||
uint32_t count = 0;
|
||||
char count_str[11] = { 0 };
|
||||
wgl_obj_t hello_world_label;
|
||||
wgl_obj_t count_label;
|
||||
wgl_obj_t btn1;
|
||||
wgl_obj_t label_count1;
|
||||
int label_count1_value = 0;
|
||||
char label_count1_str[11] = { 0 };
|
||||
|
||||
void timer1_update(user_timer_t timer1)
|
||||
{
|
||||
if ((count % 100) == 0) {
|
||||
snprintf(count_str, sizeof(count_str), "%d", count / 100);
|
||||
wgl_label_set_text(count_label, count_str);
|
||||
}
|
||||
++count;
|
||||
}
|
||||
|
||||
void on_init()
|
||||
{
|
||||
hello_world_label = wgl_label_create((wgl_obj_t)NULL, (wgl_obj_t)NULL);
|
||||
wgl_label_set_text(hello_world_label, "Hello world!");
|
||||
wgl_obj_align(hello_world_label, (wgl_obj_t)NULL, WGL_ALIGN_IN_TOP_LEFT, 0, 0);
|
||||
|
||||
count_label = wgl_label_create((wgl_obj_t)NULL, (wgl_obj_t)NULL);
|
||||
wgl_obj_align(count_label, (wgl_obj_t)NULL, WGL_ALIGN_IN_TOP_MID, 0, 0);
|
||||
|
||||
btn1 = wgl_btn_create((wgl_obj_t)NULL, (wgl_obj_t)NULL); /*Create a button on the currently loaded screen*/
|
||||
wgl_obj_set_event_cb(btn1, btn_event_cb); /*Set function to be called when the button is released*/
|
||||
wgl_obj_align(btn1, (wgl_obj_t)NULL, WGL_ALIGN_CENTER, 0, 0); /*Align below the label*/
|
||||
|
||||
/*Create a label on the button*/
|
||||
wgl_obj_t btn_label = wgl_label_create(btn1, (wgl_obj_t)NULL);
|
||||
wgl_label_set_text(btn_label, "Click ++");
|
||||
|
||||
label_count1 = wgl_label_create((wgl_obj_t)NULL, (wgl_obj_t)NULL);
|
||||
wgl_label_set_text(label_count1, "0");
|
||||
wgl_obj_align(label_count1, (wgl_obj_t)NULL, WGL_ALIGN_IN_BOTTOM_MID, 0, 0);
|
||||
|
||||
/* set up a timer */
|
||||
user_timer_t timer;
|
||||
timer = api_timer_create(10, true, false, timer1_update);
|
||||
if (timer)
|
||||
api_timer_restart(timer, 10);
|
||||
else
|
||||
printf("Fail to create timer.\n");
|
||||
}
|
||||
|
||||
static void btn_event_cb(wgl_obj_t btn, wgl_event_t event)
|
||||
{
|
||||
if(event == WGL_EVENT_RELEASED) {
|
||||
label_count1_value++;
|
||||
snprintf(label_count1_str, sizeof(label_count1_str),
|
||||
"%d", label_count1_value);
|
||||
wgl_label_set_text(label_count1, label_count1_str);
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Currently supported widgets include button, label, list and check box and more wigdet would be provided in future.
|
||||
Reference in New Issue
Block a user