Sync up with internal/feature

This commit is contained in:
wenyongh 2019-11-25 22:26:51 +08:00
parent 68dd935651
commit 2aaa42569e
36 changed files with 1947 additions and 174 deletions

113
README.md
View File

@ -14,79 +14,114 @@ WebAssembly Micro Runtime (WAMR) is a standalone WebAssembly (WASM) runtime with
Current Features of WAMR
=========================
- WASM interpreter (AOT is planned)
- Supports for a subset of Libc API.
- Supports for [WASI API](https://github.com/WebAssembly/WASI)
- Provides embedding C API
- Provides a mechanism for exporting native API's to WASM applications
- Supports the programming of firmware apps in a large range of languages (C/C++/Java/Rust/Go/TypeScript etc.)
- App sandbox execution environment on embedded OS
- The purely asynchronized programming model
- Menu configuration for easy platform integration
- Supports micro-service and pub-sub event inter-app communication models
- Easy to extend to support remote FW application management from host or cloud
- Supports libc for WASM applications in two modes: the built-in libc subset for embedded environment and [WASI](https://github.com/WebAssembly/WASI) for standard libc
- The WASM application framework and asynchronized app programming model
- Supports for micro-service and pub-sub event inter-app communication models
- Supports remote WASM application management from either host or cloud
- Menu configuration for easy integration of application libraries
Application framework architecture
===================================
By using the iwasm VM core, we are flexible to build different application frameworks for the specific domains.
By using the iwasm VM core, we are flexible to build different application frameworks for the specific domains.
The WAMR has offered a comprehensive application framework for device and IoT usages. The framework solves many common requirements for building a real project:
- Modular design for more language runtimes support
- Inter application communication
- Remote application management
- WASM APP programming model and API extension mechanism
- WASM APP programming model and API extension mechanism
<img src="./doc/pics/wamr-arch.JPG" width="80%">
Build WAMR Core and run WASM applications
================================================
Build WAMR
==========
WAMR VM core (iwasm) can support building on different platforms:
## Build WAMR VM core
WAMR VM core (iwasm) can support building for different target platforms:
- Linux
- Zephyr
- Mac
- VxWorks
- AliOS-Things
- Docker
- Intel Software Guard Extention (SGX)
After building the iwasm, we can compile some basic WASM applications and run it from the WAMR core. As the WAMR core doesn't include the extended application library, your WASM applications can only use the [WAMR built-in APIs](./doc/wamr_api.md).
See [Build WAMR VM core](./doc/build_wamr.md) for the detailed instructions.
See the [doc/building.md](./doc/building.md) for the detailed instructions.
## Libc building options
WAMR supports WASI for standard libc library as well as a [built-in libc subset](./doc/wamr_api.md) for tiny footprint.
WASI is supported for following platforms and enabled by default building:
- Linux
Embed WAMR
===========
WAMR can be built into a standalone executable which takes the WASM application file name as input, and then executes it. In some other situations, the WAMR source code is embedded the product code and built into the final product.
## Embed WAMR VM core
WAMR provides a set of C API for loading the WASM module, instantiating the module and invoking a WASM function from a native call.
WAMR can be built into a standalone executable which takes the WASM application file name as input, and then executes it. In some other situations, the WAMR source code is embedded the product code and built into the final product.
See the [doc/embed_wamr.md](./doc/embed_wamr.md) for the details.
WAMR provides a set of C API for loading the WASM module, instantiating the module and invoking a WASM function from a native call. See [Embed WAMR VM core](./doc/embed_wamr.md) for the details.
WAMR application programming library
===================================
The WAMR application framework supports dynamically installing WASM application remotely by embedding the WAMR VM core. It can be used as reference for how to use the embedding APIs.
## Integrate WAMR application library
The WAMR provides an application framework which supports event driven programming model as below:
WAMR defined event driven programming model:
- Single thread per WASM app instance
- App must implement system callbacks: on_init, on_destroy
Application programming API sets are available as below:
In general there are a few API classes for the WASM application programming:
- WAMR Built-in API: WAMR core provides a minimal libc API set for WASM APP
- WAMR application libraries:
- Timer
- Micro service (Request/Response)
- Pub/Sub
- Sensor
- Connection and data transmission
- 2D graphic UI (based on littlevgl)
- User extended native API: extend the native API to the WASM applications
- 3rd party libraries: Programmers can download any 3rd party C/C++ source code and build it together with the WASM APP code
- Timer
- Micro service (Request/Response) and Pub/Sub inter-app communication
- Sensor
- Connectivity and data transmission
- 2D graphic UI (based on littlevgl)
See the [doc/wamr_api.md](./doc/wamr_api.md) for the details.
See [WAMR application library](./doc/wamr_api.md) for the details.
One WAMR runtime version can also select a subsets from the WAMR application library. Refer to the sample "simple" for how to integrate API sets into WAMR building.
## Build WAMR with customized application library
In general when you build a WAMR version for a specific project, you probably will create additional APIs for the applications. The APIs can be expansion or modification to the standard WAMR application library.
The extended application library should be created in the folder {repo-root}/core/iwasm/lib/app-lib. See the [doc/export_native_api.md](./doc/export_native_api.md) for the details.
# Create WASM application SDK
When you ship your WAMR runtime with the products, you will need to distribute the associated WASM application SDK for the application developers to develop WASM applications for your products. At the most time, the WASM application SDK should have a version match with the runtime distribution.
Typically there are a few components in a WASM APP SDK package:
* **WASI-SDK**: only needed when WASI is enabled in the runtime. It can be a link to the WASI-SDK GitHub or the full offline copy.
* **sysroot** folder: only needed when WASI is not enabled in the runtime. copied from `{repo-root}/test-tools/toolchain/sysroot`
* **app-lib** folder: copied from `{repo-root}/core/iwasm/lib/app-lib`
* **cmake toolchain** file: copied from `{repo-root}/test-tools/toolchain/wamr_toolchain.cmake`
* optionally with some guide documents and samples
Build WASM applications
===================================
WebAssembly as a new binary instruction can be viewed as a virtual architecture. If the WASM application is developed in C/C++ language, developers can use conventional cross-compilation procedure to build the WASM application. cmake is the recommended building tool and Clang is the preferred compiler. While emcc may still work but it is not guaranteed.
Refer to [Build WASM applications](doc/build_wasm_app.md) for details.
Samples and demos
@ -94,7 +129,7 @@ Samples and demos
The WAMR samples are located in folder [./samples](./samples). A sample usually contains the WAMR runtime build, WASM applications and test tools. The WARM provides following samples:
- [Simple](./samples/simple/README.md): The runtime is integrated with most of the WAMR APP libaries and multiple WASM applications are provided for using different WASM API set.
- [littlevgl](./samples/littlevgl/README.md): Demostrating the graphic user interface application usage on WAMR. The whole [LittlevGL](https://github.com/littlevgl/) 2D user graphic library and the UI application is built into WASM application.
- [littlevgl](./samples/littlevgl/README.md): Demostrating the graphic user interface application usage on WAMR. The whole [LittlevGL](https://github.com/littlevgl/) 2D user graphic library and the UI application is built into WASM application.
- [gui](./samples/gui/README.md): Moved the [LittlevGL](https://github.com/littlevgl/) library into the runtime and defined a WASM application interface by wrapping the littlevgl API.
- [IoT-APP-Store-Demo](./test-tools/IoT-APP-Store-Demo/README.md): A web site for demostrating a WASM APP store usage where we can remotely install and uninstall WASM application on remote devices.
@ -109,9 +144,9 @@ The graphic user interface demo photo:
Releases and acknowledgments
============================
WAMR is a community efforts. Since Intel Corp contributed the first release of this open source project, this project has received many good contributions from the community.
WAMR is a community efforts. Since Intel Corp contributed the first release of this open source project, this project has received many good contributions from the community.
See the [major features releasing history and contributor names](./doc/release_ack.md)
See the [major features releasing history and contributor names](./doc/release_ack.md)
Roadmap

File diff suppressed because it is too large Load Diff

View File

@ -6,7 +6,7 @@ set (WASM_LIBC_DIR ${CMAKE_CURRENT_LIST_DIR})
include_directories(${WASM_LIBC_DIR})
file (GLOB_RECURSE source_all ${WASM_LIBC_DIR}/*.c)
file (GLOB source_all ${WASM_LIBC_DIR}/*.c)
set (WASM_LIBC_SOURCE ${source_all})

View File

@ -61,8 +61,8 @@ if (CMAKE_SIZEOF_VOID_P EQUAL 8)
endif ()
if (NOT DEFINED WASM_ENABLE_WASI)
# Enable wasi support by default
set (WASM_ENABLE_WASI 1)
# Disable wasi support by default
set (WASM_ENABLE_WASI 0)
endif ()
if (WASM_ENABLE_WASI EQUAL 1)
@ -95,7 +95,7 @@ enable_language (ASM)
include (../../runtime/platform/${PLATFORM}/platform.cmake)
include (../../runtime/utils/utils.cmake)
include (../../runtime/vmcore-wasm/vmcore.cmake)
include (../../runtime/wasmtime-wasi-c/wasi.cmake)
include (../../lib/native/libc/wasmtime-wasi-c/wasi.cmake)
include (../../lib/native/base/wasm_lib_base.cmake)
include (../../lib/native/libc/wasm_libc.cmake)
include (${SHARED_LIB_DIR}/platform/${PLATFORM}/shared_platform.cmake)

View File

@ -129,6 +129,7 @@ app_instance_repl(wasm_module_inst_t module_inst)
return NULL;
}
#if WASM_ENABLE_WASI != 0
static bool
validate_env_str(char *env)
{
@ -145,6 +146,7 @@ validate_env_str(char *env)
return true;
}
#endif
#define USE_GLOBAL_HEAP_BUF 0

View File

@ -96,7 +96,7 @@ enable_language (ASM)
include (../../runtime/platform/${PLATFORM}/platform.cmake)
include (../../runtime/utils/utils.cmake)
include (../../runtime/vmcore-wasm/vmcore.cmake)
include (../../runtime/wasmtime-wasi-c/wasi.cmake)
include (../../lib/native/libc/wasmtime-wasi-c/wasi.cmake)
include (../../lib/native/base/wasm_lib_base.cmake)
include (../../lib/native/libc/wasm_libc.cmake)
include (${SHARED_LIB_DIR}/platform/${PLATFORM}/shared_platform.cmake)

View File

@ -92,7 +92,7 @@ enable_language (ASM)
include (../../runtime/platform/${PLATFORM}/platform.cmake)
include (../../runtime/utils/utils.cmake)
include (../../runtime/vmcore-wasm/vmcore.cmake)
include (../../runtime/wasmtime-wasi-c/wasi.cmake)
include (../../lib/native/libc/wasmtime-wasi-c/wasi.cmake)
include (../../lib/native/base/wasm_lib_base.cmake)
include (../../lib/native/libc/wasm_libc.cmake)
include (${SHARED_LIB_DIR}/platform/${PLATFORM}/shared_platform.cmake)

View File

@ -156,6 +156,7 @@ app_instance_repl(wasm_module_inst_t module_inst)
return NULL;
}
#if WASM_ENABLE_WASI != 0
static bool
validate_env_str(char *env)
{
@ -172,6 +173,7 @@ validate_env_str(char *env)
return true;
}
#endif
#define USE_GLOBAL_HEAP_BUF 0

View File

@ -78,8 +78,8 @@ if (CMAKE_SIZEOF_VOID_P EQUAL 8)
endif ()
if (NOT DEFINED WASM_ENABLE_WASI)
# Enable wasi support by default
set (WASM_ENABLE_WASI 1)
# Disable wasi support by default
set (WASM_ENABLE_WASI 0)
endif ()
if (WASM_ENABLE_WASI EQUAL 1)
@ -110,7 +110,7 @@ enable_language (ASM)
include (../../runtime/platform/${PLATFORM}/platform.cmake)
include (../../runtime/utils/utils.cmake)
include (../../runtime/vmcore-wasm/vmcore.cmake)
include (../../runtime/wasmtime-wasi-c/wasi.cmake)
include (../../lib/native/libc/wasmtime-wasi-c/wasi.cmake)
include (../../lib/native/base/wasm_lib_base.cmake)
include (../../lib/native/libc/wasm_libc.cmake)
include (${SHARED_LIB_DIR}/platform/${PLATFORM}/shared_platform.cmake)

View File

@ -156,6 +156,7 @@ app_instance_repl(wasm_module_inst_t module_inst)
return NULL;
}
#if WASM_ENABLE_WASI != 0
static bool
validate_env_str(char *env)
{
@ -172,6 +173,7 @@ validate_env_str(char *env)
return true;
}
#endif
static char global_heap_buf[512 * 1024] = { 0 };

View File

@ -105,11 +105,17 @@ wasm_application_execute_main(WASMModuleInstance *module_inst,
#endif
func = resolve_main_function(module_inst);
if (!func || func->is_import_func)
if (!func || func->is_import_func) {
wasm_runtime_set_exception(module_inst,
"lookup main function failed.");
return false;
}
if (!check_main_func_type(func->u.func->func_type))
if (!check_main_func_type(func->u.func->func_type)) {
wasm_runtime_set_exception(module_inst,
"invalid function type of main function.");
return false;
}
if (func->u.func->func_type->param_count) {
for (i = 0; i < argc; i++)
@ -120,8 +126,11 @@ wasm_application_execute_main(WASMModuleInstance *module_inst,
if (total_size >= UINT32_MAX
|| !(argv_buf_offset =
wasm_runtime_module_malloc(module_inst, (uint32)total_size)))
wasm_runtime_module_malloc(module_inst, (uint32)total_size))) {
wasm_runtime_set_exception(module_inst,
"allocate memory failed.");
return false;
}
argv_buf = p = wasm_runtime_addr_app_to_native(module_inst, argv_buf_offset);
argv_offsets = (int32*)(p + total_argv_size);
@ -209,17 +218,20 @@ wasm_application_execute_func(WASMModuleInstance *module_inst,
int32 i, p;
uint64 total_size;
const char *exception;
char buf[128];
wasm_assert(argc >= 0);
func = resolve_function(module_inst, name);
if (!func || func->is_import_func) {
LOG_ERROR("Wasm lookup function %s failed.\n", name);
snprintf(buf, sizeof(buf), "lookup function %s failed.", name);
wasm_runtime_set_exception(module_inst, buf);
return false;
}
type = func->u.func->func_type;
if (type->param_count != (uint32)argc) {
LOG_ERROR("Wasm prepare param failed: invalid param count.\n");
wasm_runtime_set_exception(module_inst,
"invalid input argument count.");
return false;
}
@ -227,7 +239,7 @@ wasm_application_execute_func(WASMModuleInstance *module_inst,
total_size = sizeof(uint32) * (uint64)(argc1 > 2 ? argc1 : 2);
if (total_size >= UINT32_MAX
|| (!(argv1 = wasm_malloc((uint32)total_size)))) {
LOG_ERROR("Wasm prepare param failed: malloc failed.\n");
wasm_runtime_set_exception(module_inst, "allocate memory failed.");
return false;
}
@ -236,7 +248,8 @@ wasm_application_execute_func(WASMModuleInstance *module_inst,
char *endptr = NULL;
wasm_assert(argv[i] != NULL);
if (argv[i][0] == '\0') {
LOG_ERROR("Wasm prepare param failed: invalid num (%s).\n", argv[i]);
snprintf(buf, sizeof(buf), "invalid input argument %d.", i);
wasm_runtime_set_exception(module_inst, buf);
goto fail;
}
switch (type->types[i]) {
@ -303,11 +316,15 @@ wasm_application_execute_func(WASMModuleInstance *module_inst,
}
}
if (endptr && *endptr != '\0' && *endptr != '_') {
LOG_ERROR("Wasm prepare param failed: invalid num (%s).\n", argv[i]);
snprintf(buf, sizeof(buf), "invalid input argument %d: %s.",
i, argv[i]);
wasm_runtime_set_exception(module_inst, buf);
goto fail;
}
if (errno != 0) {
LOG_ERROR("Wasm prepare param failed: errno %d.\n", errno);
snprintf(buf, sizeof(buf),
"prepare function argument error, errno: %d.", errno);
wasm_runtime_set_exception(module_inst, buf);
goto fail;
}
}

198
doc/build_wamr.md Normal file
View File

@ -0,0 +1,198 @@
Build WAMR Core
=========================
Please follow the instructions below to build the WAMR core on different platforms.
Linux
-------------------------
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
```
Or in Fedora:
``` Bash
sudo dnf install glibc-devel.i686
```
After installing dependencies, build the source code:
``` Bash
cd core/iwasm/products/linux/
mkdir build
cd build
cmake ..
make
```
Note:
The WASI feature is enabled by default, if we want to disable it, please run:
``` Bash
cmake .. -DWASM_ENALBE_WASI=0
```
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
```
Or in Fedora:
``` Bash
sudo dnf install glibc-devel.i686
```
And then 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/
mkdir build
cd build
cmake ..
make
```
This builds the libraries used by SGX enclave sample, the generated file libvmlib.a and libextlib.a will be copied to enclave-sample folder.
Then build the enclave sample:
``` Bash
source <SGX_SDK dir>/environment
cd enclave-sample
make
```
The binary file app will be generated.
To run the sample:
``` Bash
source <SGX_SDK dir>/environment
./app
```
Mac
-------------------------
Make sure to install Xcode from App Store firstly, and install cmake.
If you use Homebrew, install cmake from the command line:
``` Bash
brew install cmake
```
Then build the source codes:
```
cd core/iwasm/products/darwin/
mkdir build
cd build
cmake ..
make
```
VxWorks
-------------------------
VxWorks 7 SR0620 release is validated.
First you need to build a VSB. Make sure *UTILS_UNIX* layer is added in the VSB.
After the VSB is built, export the VxWorks toolchain path by:
```
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/
mkdir build
cd build
cmake ..
make
```
Create a VIP based on the VSB. Make sure the following components are added:
* INCLUDE_POSIX_PTHREADS
* INCLUDE_POSIX_PTHREAD_SCHEDULER
* INCLUDE_SHARED_DATA
* INCLUDE_SHL
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
```
Zephyr
-------------------------
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 .
cd simple
ln -s <iwam_dir> iwasm
ln -s <shared_lib_dir> shared-lib
mkdir build && cd build
source ../../../zephyr-env.sh
cmake -GNinja -DBOARD=qemu_x86 ..
ninja
```
AliOS-Things
-------------------------
1. a developerkit board id needed for testing
2. download the AliOS-Things code
``` 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
``` Bash
cp -a <iwasm_root_dir>/products/alios-things middleware/iwasm
```
4. create a link to <iwasm_root_dir> in middleware/iwasm/ and rename it to iwasm
``` Bash
ln -s <iwasm_root_dir> middleware/iwasm/iwasm
```
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> middle/iwasm/shared-lib
```
6. modify file app/example/helloworld/helloworld.c, patch as:
``` C
#include <stdbool.h>
#include <aos/kernel.h>
extern bool iwasm_init();
int application_start(int argc, char *argv[])
{
int count = 0;
iwasm_init();
...
}
```
7. modify file app/example/helloworld/aos.mk
``` C
$(NAME)_COMPONENTS := osal_aos iwasm
```
8. build source code
``` Bash
aos make helloworld@developerkit -c config
aos make
```
9. download the binary to developerkit board, check the output from serial port
Docker
-------------------------
[Docker](https://www.docker.com/) will download all the dependencies and build WAMR Core on your behalf.
Make sure you have Docker installed on your machine: [macOS](https://docs.docker.com/docker-for-mac/install/), [Windows](https://docs.docker.com/docker-for-windows/install/) or [Linux](https://docs.docker.com/install/linux/docker-ce/ubuntu/).
Build the Docker image:
``` Bash
docker build --rm -f "Dockerfile" -t wamr:latest .
```
Run the image in interactive mode:
``` Bash
docker run --rm -it wamr:latest
```
You'll now enter the container at `/root`.

182
doc/build_wamr_app.md Normal file
View File

@ -0,0 +1,182 @@
Build WASM app
=========================
You can write a simple ```test.c``` as the first sample.
```C
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
char *buf;
printf("Hello world!\n");
buf = malloc(1024);
if (!buf) {
printf("malloc buf failed\n");
return -1;
}
printf("buf ptr: %p\n", buf);
sprintf(buf, "%s", "1234\n");
printf("buf: %s", buf);
free(buf);
return 0;
}
```
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.
(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 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`.
We can generate a `CMakeLists.txt` file for `test.c`:
```cmake
cmake_minimum_required (VERSION 3.5)
project(hello_world)
add_executable(hello_world test.c)
```
It is quite simple to build this project by cmake:
```Bash
mkdir build && cd build
cmake .. -DCMAKE_TOOLCHAIN_FILE=$WAMR_ROOT/test-tools/toolchain/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).
## 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
```
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.
## 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.
Run WASM app
========================
Assume you are using Linux, the command to run the test.wasm is:
``` Bash
cd iwasm/products/linux/build
./iwasm test.wasm
```
You will get the following output:
```
Hello world!
buf ptr: 0x400002b0
buf: 1234
```
If you would like to run the test app on Zephyr, we have embedded a test sample into its OS image. You will need to execute:
```
ninja run
```

116
doc/export_native_api.md Normal file
View File

@ -0,0 +1,116 @@
The mechanism of exporting native API to WASM application
=======================================================
The basic working flow for WASM application calling into the native API is shown in the following diagram:
![WAMR WASM API ext diagram](./pics/extend_library.PNG "WAMR WASM API ext architecture diagram")
WAMR provides the macro `EXPORT_WASM_API` to enable users to export a native API to a WASM application. WAMR has implemented a base API for the timer and messaging by using `EXPORT_WASM_API`. This can be a point of reference for extending your own library.
``` C
static NativeSymbol extended_native_symbol_defs[] = {
EXPORT_WASM_API(wasm_register_resource),
EXPORT_WASM_API(wasm_response_send),
EXPORT_WASM_API(wasm_post_request),
EXPORT_WASM_API(wasm_sub_event),
EXPORT_WASM_API(wasm_create_timer),
EXPORT_WASM_API(wasm_timer_set_interval),
EXPORT_WASM_API(wasm_timer_cancel),
EXPORT_WASM_API(wasm_timer_restart)
};
```
![#f03c15](https://placehold.it/15/f03c15/000000?text=+) **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.
<img src="./pics/safe.PNG" width="90%">
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 ```
``` C
#include "lib_export.h"
static NativeSymbol extended_native_symbol_defs[] =
{
};
#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
}
// lib_export_dec.h
#ifndef _LIB_EXPORT_DEC_H_
#define _LIB_EXPORT_DEC_H_
#ifdef __cplusplus
extern "C" {
#endif
void customized();
#ifdef __cplusplus
}
#endif
#endif
// ext_lib_export.c
#include "lib_export.h"
#include "lib_export_dec.h"
static NativeSymbol extended_native_symbol_defs[] =
{
EXPORT_WASM_API(customized)
};
#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:
``` C
#include <stdio.h>
#include "lib_export_dec.h" // provided by the platform vendor
int main(int argc, char **argv)
{
int I;
char *buf = “abcd”;
customized(); // customized API provided by the platform vendor
return i;
}
```

View File

@ -1,5 +1,5 @@
WASM application library
WAMR application library
========================
WAMR APP API includes built-in Libc API's, Base library and Extension library reference.
@ -89,120 +89,6 @@ 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.
The mechanism of exporting native API to WASM application
=======================================================
The basic working flow for WASM application calling into the native API is shown in the following diagram:
![WAMR WASM API ext diagram](./pics/extend_library.PNG "WAMR WASM API ext architecture diagram")
WAMR provides the macro `EXPORT_WASM_API` to enable users to export a native API to a WASM application. WAMR has implemented a base API for the timer and messaging by using `EXPORT_WASM_API`. This can be a point of reference for extending your own library.
``` C
static NativeSymbol extended_native_symbol_defs[] = {
EXPORT_WASM_API(wasm_register_resource),
EXPORT_WASM_API(wasm_response_send),
EXPORT_WASM_API(wasm_post_request),
EXPORT_WASM_API(wasm_sub_event),
EXPORT_WASM_API(wasm_create_timer),
EXPORT_WASM_API(wasm_timer_set_interval),
EXPORT_WASM_API(wasm_timer_cancel),
EXPORT_WASM_API(wasm_timer_restart)
};
```
![#f03c15](https://placehold.it/15/f03c15/000000?text=+) **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.
<img src="./pics/safe.PNG" width="90%">
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 ```
``` C
#include "lib_export.h"
static NativeSymbol extended_native_symbol_defs[] =
{
};
#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
}
// lib_export_dec.h
#ifndef _LIB_EXPORT_DEC_H_
#define _LIB_EXPORT_DEC_H_
#ifdef __cplusplus
extern "C" {
#endif
void customized();
#ifdef __cplusplus
}
#endif
#endif
// ext_lib_export.c
#include "lib_export.h"
#include "lib_export_dec.h"
static NativeSymbol extended_native_symbol_defs[] =
{
EXPORT_WASM_API(customized)
};
#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:
``` C
#include <stdio.h>
#include "lib_export_dec.h" // provided by the platform vendor
int main(int argc, char **argv)
{
int I;
char *buf = “abcd”;
customized(); // customized API provided by the platform vendor
return i;
}
```
Communication programming models
=========================
@ -307,4 +193,4 @@ 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 deail usage.

View File

@ -15,7 +15,7 @@ typedef unsigned int size_t;
int atoi(const char *s);
void exit(int status);
long strtol(const char *nptr, char **endptr, register int base);
unsigned long strtoul(const char *nptr, char **endptr, register int base)
unsigned long strtoul(const char *nptr, char **endptr, register int base);
void *malloc(size_t size);
void *calloc(size_t n, size_t size);
void free(void *ptr);