Import app manager, samples and test-tools

This commit is contained in:
wenyongh
2019-05-17 17:15:25 +08:00
parent b6e29e2153
commit dd5b133fa5
164 changed files with 21123 additions and 496 deletions

260
README.md
View File

@ -1,17 +1,17 @@
WebAssembly Micro Runtime
=========================
WebAssembly Micro Runtime (WAMR) is standalone WebAssembly (WASM) runtime designed for a small footprint. It includes:
WebAssembly Micro Runtime (WAMR) is a standalone WebAssembly (WASM) runtime designed for a small footprint. It includes:
- A WebAssembly (WASM) VM core
- The supporting APIs for the WASM applications (code is available but compilation depends on the app manager component)
- A mechanism for dynamic management of the WASM application (Not available on Github yet. To be released soon)
Why should you use a WASM runtime out of your browser? There are a few points where this might be meaningful:
1. WASM is already a LLVM official backend target. That means WASM can run any programming languages which can be compiled to LLVM IR. It is a huge advantage compared to language bound runtimes like JS or Lua.
2. WASM is an open standard and it is fast becoming supported by the whole web ecosystem.
3. WASM is designed to be very friendly for compiling to native binaries and gaining the native speed.
4. It can potentially change the development practices. Imagine we can do both the WASM application development and validation in a browser, then just download the WASM binary code onto the target device.
5. WASM can work without garbage collection. It is designed to support execution determinics for the time sensitive requirement.
6. Maintain the safety goals WASM has of providing a sandboxed execution enviornment for untrusted code. In addition, because WASM is a compilation target, this implies a benefit of being able to target both an execution and security profile that is consistent across popular high-level programming languages.
Why should you use a WASM runtime out of your browser? There are a few points where this might be meaningful:
1. WASM is already an LLVM official backend target. That means WASM can run any programming languages which can be compiled to LLVM IR. It is a huge advantage compared to language bound runtimes like JS or Lua.
2. WASM is an open standard and it is fast becoming supported by the whole web ecosystem.
3. WASM is designed to be very friendly for compiling to native binaries and gaining the native speed.
4. It can potentially change the development practices. Imagine we can do both the WASM application development and validation in a browser, then just download the WASM binary code onto the target device.
5. WASM can work without garbage collection. It is designed to support execution determinics for the time sensitive requirement.
6. Maintain the safety goals WASM has of providing a sandboxed execution environment for untrusted code. In addition, because WASM is a compilation target, this implies a benefit of being able to target both an execution and security profile that is consistent across popular high-level programming languages.
@ -24,7 +24,7 @@ Current Features of WAMR
- 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
- Purely asynchronized programming model
- 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
@ -35,7 +35,7 @@ The application manager component handles the packets that the platform receives
- The WebAssembly runtime provides the execution environment for WASM applications.
- The messaging layer can support the API for WASM applications to communicate to each other and also the host environment.
- The messaging layer can support the API for WASM applications to communicate with each other and also the host environment.
- When ahead of time (AOT) compilation is enabled (TODO), the WASM application could be either WASM or a compiled native binary.
@ -88,12 +88,9 @@ git clone https://github.com/emscripten-core/emsdk.git
emsdk install latest
emsdk activate latest
```
add ```./emsdk_env.sh``` into the path to ease future use, or source it everytime.
add ```./emsdk_env.sh``` into the path to ease future use, or source it every time.
The Emscripten website provides other installation methods beyond Linux.
(TODO) The user should copy the app-libs folder into project and include and build.
You can write a simple ```test.c``` as the first sample.
``` C
#include <stdio.h>
@ -101,23 +98,23 @@ You can write a simple ```test.c``` as the first sample.
int main(int argc, char **argv)
{
char *buf;
char *buf;
printf("Hello world!\n");
printf("Hello world!\n");
buf = malloc(1024);
if (!buf) {
printf("malloc buf failed\n");
return -1;
}
buf = malloc(1024);
if (!buf) {
printf("malloc buf failed\n");
return -1;
}
printf("buf ptr: %p\n", buf);
printf("buf ptr: %p\n", buf);
sprintf(buf, "%s", "1234\n");
printf("buf: %s", buf);
sprintf(buf, "%s", "1234\n");
printf("buf: %s", buf);
free(buf);
return 0;
free(buf);
return 0;
}
```
Use the emcc command below to build the WASM C source code into the WASM binary.
@ -147,31 +144,43 @@ ninja run
Embed WAMR into software production
=====================================
WAMR can be built into a standalone executable which takes the WASM application file name as input, and then executes it. To use it in the embedded environment you should embed WAMR into your own software product. WASM provides a set of API's for embedded code to load the WASM module, instantiate the module and invoke 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. To use it in the embedded environment you should embed WAMR into your own software product. WASM provides a set of APIs for embedded code to load the WASM module, instantiate the module and invoke a WASM function from a native call.
<img src="./doc/pics/embed.PNG" width="60%" height="60%">
A typical WAMR API usage is shown below:
A typical WAMR API usage is shown below (some return values checking are ignored):
``` C
static char global_heap_buf[512 * 1024];
char *buffer;
wasm_module_t module;
wasm_module_inst_t inst;
wasm_function_inst_t func;
wasm_exec_env_t env;
uint32 argv[2];
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, err, err_size);
func = wasm_runtime_lookup_function(inst, "fib", "(i32i32");
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);
argv[0] = 8;
if (!wasm_runtime_call_wasm(inst, env, func, 1, argv_buf) ) {
wasm_runtime_clear_exception(inst);
}
wasm_runtime_clear_exception(inst);
}
/* the return value is stored in argv[0] */
printf(“fib function return: %d\n”, argv[0]);
wasm_runtime_destory_exec_env(env);
wasm_runtime_deinstantiate(inst);
wasm_runtime_unload(module);
wasm_runtime_destroy();
bh_memory_destroy();
```
@ -188,7 +197,7 @@ Built-in application library
Built-in API's include Libc APIs, Base library and Extension library reference.
**Libc APIs**<br/>
This is a minimal set of Libc APIs 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:
This is a minimal set of Libc APIs 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:
``` C
void *malloc(size_t size);
void *calloc(size_t n, size_t size);
@ -209,7 +218,7 @@ char *strncpy(char *dest, const char *src, unsigned long n);
```
**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 APIs and timer APIs. Please note that these API's require the native implementations.
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 APIs and timer APIs. Please note that these API's require the native implementations.
The API set is listed below:
``` C
typedef void(*request_handler_f)(request_t *) ;
@ -245,7 +254,7 @@ bool sensor_config_with_attr_container(sensor_t sensor, attr_container_t *cfg);
bool sensor_close(sensor_t sensor);
```
The mechanism of exporting Native API to WASM application
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:
@ -256,14 +265,14 @@ The basic working flow for WASM application calling into the native API is shown
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)
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)
};
```
@ -286,15 +295,15 @@ WAMR implemented a framework for developers to export API's. Below is the proced
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 ```
Export the platform API's, for example in ``` products/linux/ext_lib_export.c ```
``` C
#include "lib-export.h"
#include "lib_export.h"
static NativeSymbol extended_native_symbol_defs[] =
{
};
#include "ext-lib-export.h"
#include "ext_lib_export.h"
```
**Step 3. Register new APIs**<br/>
@ -305,15 +314,16 @@ The pre-defined MACRO `EXPORT_WASM_API` should be used to declare a function exp
```
Below code example shows how to extend the library to support `customized()`:
``` C
//lib-export-impl.c
```
//lib_export_impl.c
void customized()
{
// your code
}
// lib-export-dec.h
// lib_export_dec.h
#ifndef _LIB_EXPORT_DEC_H_
#define _LIB_EXPORT_DEC_H_
#ifdef __cplusplus
@ -328,36 +338,162 @@ void customized();
#endif
// ext-lib-export.c
#include "lib-export.h"
#include "lib-export-dec.h"
// ext_lib_export.c
#include "lib_export.h"
#include "lib_export_dec.h"
static NativeSymbol extended_native_symbol_defs[] =
{
EXPORT_WASM_API(customized)
EXPORT_WASM_API(customized)
};
#include "ext-lib-export.h"
#include "ext_lib_export.h"
```
Use extended library
------------------------
In the application source project, it will include the WAMR built-in APIs 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
#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;
int I;
char *buf = “abcd”;
customized(); // customized API provided by the platform vendor
return i;
}
```
Future Goals
========================
The application manager and related code samples like inter-application communication, application life cycle management, 2D graphic demo and more ...
Communication programming models
=========================
WAMR supports two typical communication programming models, the microservice model and the pub/sub model.
Microservice model
-------------------------
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="./doc/pics/request.PNG" width="60%" height="60%">
Below is the reference implementation of the server application. It provides room temperature measurement service.
``` C
void on_init()
{
/* register resource uri */
init_resource_register();
api_register_resource_handler("/room_temp", room_temp_handler);
}
void on_destroy()
{
}
void room_temp_handler(request_t *request)
{
response_t response[1];
attr_container_t *payload;
payload = attr_container_create("room_temp payload");
if (payload == NULL)
return;
attr_container_set_string(&payload, "temp unit", "centigrade");
attr_container_set_int(&payload, "value", 26);
make_response_for_request(request, response);
set_response(response,
CONTENT_2_05,
FMT_ATTR_CONTAINER,
payload,
attr_container_get_serialize_length(payload));
api_response_send(response);
attr_container_destroy(payload);
}
```
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="./doc/pics/sub.PNG" width="60%" height="60%">
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.
``` C
void on_init(
{
api_subscribe_event ("alert/overheat", overheat_handler);
}
void on_destroy()
{
}
void overheat_handler(request_t *event
{
printf(“Event: %s\n", event->url);
}
/* Timer callback */
void timer_update(user_timer_t timer
{
attr_container_t *event;
printf("Timer update %d\n", num++);
event = attr_container_create("event");
attr_container_set_string(&event,
"warning",
"temperature is over high");
api_publish_event("alert/overheat",
FMT_ATTR_CONTAINER,
event,
attr_container_get_serialize_length(event));
attr_container_destroy(event);
}
void on_init()
{
user_timer_t timer;
timer = api_timer_create(1000, true, true, timer_update);
}
```
Samples and demos
=========================
The simple sample
--------
Please refer to the ```samples/simple``` folder for samples of WASM application life cyle management and programming models.
2D graphic user interface with LittlevGL
------------------------------------------------
This sample demonstrates that a graphic user interface application in WebAssembly integrates the LittlevGL, an open-source embedded 2d graphic library. The sample source code is under ```samples/littlevgl```
In this sample, the LittlevGL source code is built into the WebAssembly code with the user application source files. The platform interfaces defined by LittlevGL is implemented in the runtime and exported to the application through the declarations from source "ext_lib_export.c" as below:
EXPORT_WASM_API(display_init),
EXPORT_WASM_API(display_input_read),
EXPORT_WASM_API(display_flush),
EXPORT_WASM_API(display_fill),
EXPORT_WASM_API(display_vdb_write),
EXPORT_WASM_API(display_map),
EXPORT_WASM_API(time_get_ms), };
The runtime component supports building target for Linux and Zephyr/STM Nucleo board respectively. The beauty of this sample is the WebAssembly application can have identical display and behavior when running from both runtime environments. That implies we can do majority of application validation from desktop environment then load it to the target device as long as two runtime distributions support the same set of application interface.
Below pictures show the WASM application is running on an STM board with an LCD touch panel. When users click the blue button, the WASM application increases the counter, and the latest counter value is displayed on the top banner of the touch panel.
<img src="./doc/pics/vgl.PNG" width="60%" height="60%">
<img src="./doc/pics/vgl2.PNG" width="60%" height="60%">
The sample also provides the native Linux version of application without the runtime under folder "vgl-native-ui-app". It can help to check differences between the implementations in native and WebAssembly.
<img src="./samples/littlevgl/UI.JPG">
Submit issues and request
=========================