Move all examples to a top-level directory (#1286)

* Move all examples to a top-level directory

This commit moves all API examples (Rust and C) to a top-level
`examples` directory. This is intended to make it more discoverable and
conventional as to where examples are located. Additionally all examples
are now available in both Rust and C to see how to execute the example
in the language you're familiar with. The intention is that as more
languages are supported we'd add more languages as examples here too.

Each example is also accompanied by either a `*.wat` file which is
parsed as input, or a Rust project in a `wasm` folder which is compiled
as input.

A simple driver crate was also added to `crates/misc` which executes all
the examples on CI, ensuring the C and Rust examples all execute
successfully.
This commit is contained in:
Alex Crichton
2020-03-11 15:37:24 -05:00
committed by GitHub
parent d44384da8a
commit 3c51d3adb8
33 changed files with 1131 additions and 528 deletions

View File

@@ -1,171 +0,0 @@
###############################################################################
# Configuration
# Inherited from wasm-c-api/Makefile to just run C examples
WASM_FLAGS = -DWASM_API_DEBUG # -DWASM_API_DEBUG_LOG
C_FLAGS = ${WASM_FLAGS} -Wall -Werror -ggdb -O -fsanitize=address
CC_FLAGS = -std=c++11 ${C_FLAGS}
LD_FLAGS = -fsanitize-memory-track-origins -fsanitize-memory-use-after-dtor
C_COMP = clang
WASMTIME_API_MODE = debug
# Base directories
WASMTIME_API_DIR = ..
WASM_DIR = wasm-c-api
EXAMPLE_DIR = ${WASM_DIR}/example
OUT_DIR = ${WASM_DIR}/out
# Example config
EXAMPLE_OUT = ${OUT_DIR}/example
EXAMPLES = \
hello \
callback \
trap \
start \
reflect \
global \
table \
memory \
hostref \
finalize \
serialize \
threads \
# multi \
# Wasm config
WASM_INCLUDE = ${WASM_DIR}/include
WASM_SRC = ${WASM_DIR}/src
WASM_OUT = ${OUT_DIR}
WASM_C_LIBS = wasm-bin wasm-rust-api
WASM_CC_LIBS = $(error unsupported C++)
# Compiler config
ifeq (${WASMTIME_API_MODE},release)
CARGO_BUILD_FLAGS = --release
else
CARGO_BUILD_FLAGS =
endif
ifeq (${C_COMP},clang)
CC_COMP = clang++
LD_GROUP_START =
LD_GROUP_END =
else ifeq (${C_COMP},gcc)
CC_COMP = g++
LD_GROUP_START = -Wl,--start-group
LD_GROUP_END = -Wl,--end-group
else
$(error C_COMP set to unknown compiler, must be clang or gcc)
endif
WASMTIME_BIN_DIR = ${WASMTIME_API_DIR}/../../target/${WASMTIME_API_MODE}
WASMTIME_C_LIB_DIR = ${WASMTIME_BIN_DIR}
WASMTIME_C_LIBS = wasmtime
WASMTIME_CC_LIBS = $(error unsupported c++)
WASMTIME_C_BINS = ${WASMTIME_C_LIBS:%=${WASMTIME_C_LIB_DIR}/lib%.a}
###############################################################################
# Examples
#
# To build Wasm APIs and run all examples:
# make all
#
# To run only C examples:
# make c
#
# To run only C++ examples:
# make cc
#
# To run individual C example (e.g. hello):
# make run-hello-c
#
# To run individual C++ example (e.g. hello):
# make run-hello-cc
#
.PHONY: all cc c
all: cc c
cc: ${EXAMPLES:%=run-%-cc}
c: ${EXAMPLES:%=run-%-c}
# Running a C / C++ example
run-%-c: ${EXAMPLE_OUT}/%-c ${EXAMPLE_OUT}/%.wasm
@echo ==== C ${@:run-%-c=%} ====; \
cd ${EXAMPLE_OUT}; ./${@:run-%=%}
@echo ==== Done ====
run-%-cc: ${EXAMPLE_OUT}/%-cc ${EXAMPLE_OUT}/%.wasm
@echo ==== C++ ${@:run-%-cc=%} ====; \
cd ${EXAMPLE_OUT}; ./${@:run-%=%}
@echo ==== Done ====
# Compiling C / C++ example
${EXAMPLE_OUT}/%-c.o: ${EXAMPLE_DIR}/%.c ${WASM_INCLUDE}/wasm.h
mkdir -p ${EXAMPLE_OUT}
${C_COMP} -c ${C_FLAGS} -I. -I${WASM_INCLUDE} $< -o $@
${EXAMPLE_OUT}/%-cc.o: ${EXAMPLE_DIR}/%.cc ${WASM_INCLUDE}/wasm.hh
mkdir -p ${EXAMPLE_OUT}
${CC_COMP} -c ${CC_FLAGS} -I. -I${WASM_INCLUDE} $< -o $@
# Linking C / C++ example
.PRECIOUS: ${EXAMPLES:%=${EXAMPLE_OUT}/%-c}
${EXAMPLE_OUT}/%-c: ${EXAMPLE_OUT}/%-c.o ${WASMTIME_C_BINS}
${CC_COMP} ${CC_FLAGS} ${LD_FLAGS} $< -o $@ \
${LD_GROUP_START} \
${WASMTIME_C_BINS} \
${LD_GROUP_END} \
-ldl -pthread
# Installing Wasm binaries
.PRECIOUS: ${EXAMPLES:%=${EXAMPLE_OUT}/%.wasm}
${EXAMPLE_OUT}/%.wasm: ${EXAMPLE_DIR}/%.wasm
cp $< $@
###############################################################################
# Wasm C / C++ API
#
# To build both C / C++ APIs:
# make wasm
.PHONY: wasm wasm-c wasm-cc
wasm: wasm-c wasm-cc
wasm-c: ${WASMTIME_C_BIN}
wasm-cc: ${WASMTIME_CC_BIN}
${WASMTIME_C_BINS}: CARGO_RUN
cd ${WASMTIME_API_DIR}; cargo build --lib ${CARGO_BUILD_FLAGS}
.PHONY: CARGO_RUN
CARGO_RUN:
###############################################################################
# Clean-up
.PHONY: clean
clean:
rm -rf ${OUT_DIR}
###############################################################################
# Other examples
WASM_EXT_INCLUDE = ${WASMTIME_API_DIR}/include
run-config-debug-c: ${EXAMPLE_OUT}/config-debug-c ${EXAMPLE_OUT}/fib-wasm.wasm
@echo ==== C config ====; \
cd ${EXAMPLE_OUT}; ./config-debug-c
@echo ==== Done ====
${EXAMPLE_OUT}/fib-wasm.wasm: fib-wasm.wasm
cp $< $@
${EXAMPLE_OUT}/config-debug-c.o: config-debug.c ${WASM_INCLUDE}/wasm.h ${WASM_EXT_INCLUDE}/wasmtime.h
mkdir -p ${EXAMPLE_OUT}
${C_COMP} -c ${C_FLAGS} -I. -I${WASM_INCLUDE} -I${WASM_EXT_INCLUDE} $< -o $@

View File

@@ -1,99 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include <wasm.h>
#include "wasmtime.h"
#define own
int main(int argc, const char* argv[]) {
// Configuring engine to support generating of DWARF info.
// lldb can be used to attach to the program and observe
// original fib-wasm.c source code and variables.
wasm_config_t* config = wasm_config_new();
wasmtime_config_debug_info_set(config, true);
// Initialize.
printf("Initializing...\n");
wasm_engine_t* engine = wasm_engine_new_with_config(config);
wasm_store_t* store = wasm_store_new(engine);
// Load binary.
printf("Loading binary...\n");
FILE* file = fopen("fib-wasm.wasm", "r");
if (!file) {
printf("> Error loading module!\n");
return 1;
}
fseek(file, 0L, SEEK_END);
size_t file_size = ftell(file);
fseek(file, 0L, SEEK_SET);
wasm_byte_vec_t binary;
wasm_byte_vec_new_uninitialized(&binary, file_size);
if (fread(binary.data, file_size, 1, file) != 1) {
printf("> Error loading module!\n");
return 1;
}
fclose(file);
// Compile.
printf("Compiling module...\n");
own wasm_module_t* module = wasm_module_new(store, &binary);
if (!module) {
printf("> Error compiling module!\n");
return 1;
}
wasm_byte_vec_delete(&binary);
// Instantiate.
printf("Instantiating module...\n");
own wasm_instance_t* instance =
wasm_instance_new(store, module, NULL, NULL);
if (!instance) {
printf("> Error instantiating module!\n");
return 1;
}
// Extract export.
printf("Extracting export...\n");
own wasm_extern_vec_t exports;
wasm_instance_exports(instance, &exports);
if (exports.size == 0) {
printf("> Error accessing exports!\n");
return 1;
}
// Getting second export (first is memory).
const wasm_func_t* run_func = wasm_extern_as_func(exports.data[1]);
if (run_func == NULL) {
printf("> Error accessing export!\n");
return 1;
}
wasm_module_delete(module);
wasm_instance_delete(instance);
// Call.
printf("Calling fib...\n");
wasm_val_t params[1] = { {.kind = WASM_I32, .of = {.i32 = 6}} };
wasm_val_t results[1];
if (wasm_func_call(run_func, params, results)) {
printf("> Error calling function!\n");
return 1;
}
wasm_extern_vec_delete(&exports);
printf("> fib(6) = %d\n", results[0].of.i32);
// Shut down.
printf("Shutting down...\n");
wasm_store_delete(store);
wasm_engine_delete(engine);
// All done.
printf("Done.\n");
return 0;
}

View File

@@ -1,13 +0,0 @@
// Compile with:
// clang --target=wasm32 fib-wasm.c -o fib-wasm.wasm -g \
// -Wl,--no-entry,--export=fib -nostdlib -fdebug-prefix-map=$PWD=.
int fib(int n) {
int i, t, a = 0, b = 1;
for (i = 0; i < n; i++) {
t = a;
a = b;
b += t;
}
return b;
}

Binary file not shown.

View File

@@ -9,6 +9,8 @@
extern "C" {
#endif
#define own
typedef uint8_t wasmtime_strategy_t;
enum wasmtime_strategy_enum { // Strategy
WASMTIME_STRATEGY_AUTO,
@@ -51,13 +53,15 @@ WASMTIME_CONFIG_PROP(cranelift_opt_level, wasmtime_opt_level_t)
// optional.
//
// Returns `true` if conversion succeeded, or `false` if it failed.
bool wasmtime_wat2wasm(
WASM_API_EXTERN bool wasmtime_wat2wasm(
wasm_engine_t *engine,
const wasm_byte_vec_t *wat,
own wasm_byte_vec_t *ret,
own wasm_byte_vec_t *error_message,
own wasm_byte_vec_t *error_message
);
#undef own
#ifdef __cplusplus
} // extern "C"
#endif