From 5854a0c7fe39acd29fb5aafd118b99787aee1cf6 Mon Sep 17 00:00:00 2001 From: Huang Qi Date: Tue, 8 Sep 2020 20:32:39 +0800 Subject: [PATCH] Introduce support for NuttX RTOS Signed-off-by: Huang Qi --- README.md | 2 +- core/shared/platform/nuttx/nuttx_platform.c | 70 ++++ core/shared/platform/nuttx/nuttx_thread.c | 86 +++++ .../shared/platform/nuttx/platform_internal.h | 45 +++ .../platform/nuttx/shared_platform.cmake | 14 + doc/build_wamr.md | 3 + product-mini/platforms/nuttx/main.c | 320 ++++++++++++++++++ product-mini/platforms/nuttx/wamr.mk | 141 ++++++++ 8 files changed, 680 insertions(+), 1 deletion(-) create mode 100644 core/shared/platform/nuttx/nuttx_platform.c create mode 100644 core/shared/platform/nuttx/nuttx_thread.c create mode 100644 core/shared/platform/nuttx/platform_internal.h create mode 100644 core/shared/platform/nuttx/shared_platform.cmake create mode 100644 product-mini/platforms/nuttx/main.c create mode 100644 product-mini/platforms/nuttx/wamr.mk diff --git a/README.md b/README.md index 446209f..a3e062a 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ The iwasm supports the following architectures: Following platforms are supported. Refer to [WAMR porting guide](./doc/port_wamr.md) for how to port WAMR to a new platform. - [Linux](./doc/build_wamr.md#linux), [Linux SGX (Intel Software Guard Extension)](./doc/linux_sgx.md), [MacOS](./doc/build_wamr.md#macos), [Android](./doc/build_wamr.md#android) -- [Zephyr](./doc/build_wamr.md#zephyr), [AliOS-Things](./doc/build_wamr.md#alios-things), [VxWorks](./doc/build_wamr.md#vxworks) +- [Zephyr](./doc/build_wamr.md#zephyr), [AliOS-Things](./doc/build_wamr.md#alios-things), [VxWorks](./doc/build_wamr.md#vxworks), [NuttX](./doc/build_wamr.md#nuttx) ### Build iwasm VM core (mini product) diff --git a/core/shared/platform/nuttx/nuttx_platform.c b/core/shared/platform/nuttx/nuttx_platform.c new file mode 100644 index 0000000..4a126c7 --- /dev/null +++ b/core/shared/platform/nuttx/nuttx_platform.c @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2020 XiaoMi Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "platform_api_extension.h" +#include "platform_api_vmcore.h" + +int +bh_platform_init() +{ + return 0; +} + +void +bh_platform_destroy() +{} + +void * +os_malloc(unsigned size) +{ + return malloc(size); +} + +void * +os_realloc(void *ptr, unsigned size) +{ + return realloc(ptr, size); +} + +void +os_free(void *ptr) +{ + free(ptr); +} + +void * +os_mmap(void *hint, size_t size, int prot, int flags) +{ + if ((uint64)size >= UINT32_MAX) + return NULL; + return malloc((uint32)size); +} + +void +os_munmap(void *addr, size_t size) +{ + return free(addr); +} + +int +os_mprotect(void *addr, size_t size, int prot) +{ + return 0; +} + +void +os_dcache_flush() +{} + +uint64 +os_time_get_boot_microsecond() +{ + struct timespec ts; + if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) { + return 0; + } + + return ((uint64)ts.tv_sec) * 1000 * 1000 + ((uint64)ts.tv_nsec) / 1000; +} diff --git a/core/shared/platform/nuttx/nuttx_thread.c b/core/shared/platform/nuttx/nuttx_thread.c new file mode 100644 index 0000000..aa69ee4 --- /dev/null +++ b/core/shared/platform/nuttx/nuttx_thread.c @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2020 XiaoMi Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "platform_api_extension.h" +#include "platform_api_vmcore.h" + +korp_tid +os_self_thread() +{ + return (korp_tid)pthread_self(); +} + +int +os_mutex_init(korp_mutex *mutex) +{ + return pthread_mutex_init(mutex, NULL) == 0 ? BHT_OK : BHT_ERROR; +} + +int +os_mutex_destroy(korp_mutex *mutex) +{ + int ret; + + assert(mutex); + ret = pthread_mutex_destroy(mutex); + + return ret == 0 ? BHT_OK : BHT_ERROR; +} + +int +os_mutex_lock(korp_mutex *mutex) +{ + int ret; + + assert(mutex); + ret = pthread_mutex_lock(mutex); + if (0 != ret) { + os_printf("vm mutex lock failed (ret=%d)!\n", ret); + exit(-1); + } + return ret; +} + +int +os_mutex_unlock(korp_mutex *mutex) +{ + int ret; + + assert(mutex); + ret = pthread_mutex_unlock(mutex); + if (0 != ret) { + os_printf("vm mutex unlock failed (ret=%d)!\n", ret); + exit(-1); + } + return ret; +} + +uint8 * +os_thread_get_stack_boundary() +{ + return NULL; +} + +int +os_cond_init(korp_cond *cond) +{ + assert(cond); + + if (pthread_cond_init(cond, NULL) != BHT_OK) + return BHT_ERROR; + + return BHT_OK; +} + +int +os_cond_destroy(korp_cond *cond) +{ + assert(cond); + + if (pthread_cond_destroy(cond) != BHT_OK) + return BHT_ERROR; + + return BHT_OK; +} diff --git a/core/shared/platform/nuttx/platform_internal.h b/core/shared/platform/nuttx/platform_internal.h new file mode 100644 index 0000000..856aab4 --- /dev/null +++ b/core/shared/platform/nuttx/platform_internal.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2020 XiaoMi Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _PLATFORM_INTERNAL_H +#define _PLATFORM_INTERNAL_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef BH_PLATFORM_NUTTX +#define BH_PLATFORM_NUTTX +#endif + +typedef pthread_t korp_tid; +typedef pthread_mutex_t korp_mutex; +typedef pthread_cond_t korp_cond; +typedef pthread_t korp_thread; + +#define BH_APPLET_PRESERVED_STACK_SIZE (2 * BH_KB) + +/* Default thread priority */ +#define BH_THREAD_DEFAULT_PRIORITY 100 + +#define os_printf printf +#define os_vprintf vprintf + +#ifdef __cplusplus +} +#endif + +#endif /* end of _BH_PLATFORM_H */ diff --git a/core/shared/platform/nuttx/shared_platform.cmake b/core/shared/platform/nuttx/shared_platform.cmake new file mode 100644 index 0000000..7b29b5f --- /dev/null +++ b/core/shared/platform/nuttx/shared_platform.cmake @@ -0,0 +1,14 @@ +# Copyright (C) 2020 XiaoMi Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +set (PLATFORM_SHARED_DIR ${CMAKE_CURRENT_LIST_DIR}) + +add_definitions(-DBH_PLATFORM_NUTTX) + +include_directories(${PLATFORM_SHARED_DIR}) +include_directories(${PLATFORM_SHARED_DIR}/../include) + +file (GLOB_RECURSE source_all ${PLATFORM_SHARED_DIR}/*.c) + +set (PLATFORM_SHARED_SOURCE ${source_all} ${PLATFORM_COMMON_MATH_SOURCE}) + diff --git a/doc/build_wamr.md b/doc/build_wamr.md index c0b36f2..f7fc9e2 100644 --- a/doc/build_wamr.md +++ b/doc/build_wamr.md @@ -301,6 +301,9 @@ $ # include/ includes all necesary head files $ # lib includes libiwasm.so ``` +NuttX +------------------------- +WAMR is intergrated with NuttX, just enable the WAMR in Kconfig option (Application Configuration/Interpreters). Docker ------------------------- diff --git a/product-mini/platforms/nuttx/main.c b/product-mini/platforms/nuttx/main.c new file mode 100644 index 0000000..25c654f --- /dev/null +++ b/product-mini/platforms/nuttx/main.c @@ -0,0 +1,320 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif +#include +#include + +#include "bh_platform.h" +#include "bh_read_file.h" +#include "wasm_export.h" + +static int app_argc; +static char **app_argv; + +#define MODULE_PATH ("--module-path=") + +static int +print_help() +{ + printf("Usage: iwasm [-options] wasm_file [args...]\n"); + printf("options:\n"); + printf(" -f|--function name Specify a function name of the module to run rather\n" + " than main\n"); +#if WASM_ENABLE_LOG != 0 + printf(" -v=n Set log verbose level (0 to 5, default is 2) larger\n" + " level with more log\n"); +#endif + printf(" --stack-size=n Set maximum stack size in bytes, default is 16 KB\n"); + printf(" --heap-size=n Set maximum heap size in bytes, default is 16 KB\n"); +#if WASM_ENABLE_LIBC_WASI != 0 + printf(" --env= Pass wasi environment variables with \"key=value\"\n"); + printf(" to the program, for example:\n"); + printf(" --env=\"key1=value1\" --env=\"key2=value2\"\n"); + printf(" --dir= Grant wasi access to the given host directories\n"); + printf(" to the program, for example:\n"); + printf(" --dir= --dir=\n"); +#endif +#if WASM_ENABLE_MULTI_MODULE != 0 + printf(" --module-path= Indicate a module search path. default is current\n" + " directory('./')\n"); +#endif +#if WASM_ENABLE_LIB_PTHREAD != 0 + printf(" --max-threads=n Set maximum thread number per cluster, default is 4\n"); +#endif + return 1; +} + +static void * +app_instance_main(wasm_module_inst_t module_inst) +{ + const char *exception; + + wasm_application_execute_main(module_inst, app_argc, app_argv); + if ((exception = wasm_runtime_get_exception(module_inst))) + printf("%s\n", exception); + return NULL; +} + +static void * +app_instance_func(wasm_module_inst_t module_inst, const char *func_name) +{ + wasm_application_execute_func(module_inst, func_name, app_argc - 1, + app_argv + 1); + /* The result of wasm function or exception info was output inside + wasm_application_execute_func(), here we don't output them again. */ + return NULL; +} + +#if WASM_ENABLE_LIBC_WASI != 0 +static bool +validate_env_str(char *env) +{ + char *p = env; + int key_len = 0; + + while (*p != '\0' && *p != '=') { + key_len++; + p++; + } + + if (*p != '=' || key_len == 0) + return false; + + return true; +} +#endif + +#define USE_GLOBAL_HEAP_BUF 1 + +#if USE_GLOBAL_HEAP_BUF != 0 +static char global_heap_buf[128 * 1024] = { 0 }; +#endif + +#if WASM_ENABLE_MULTI_MODULE != 0 +static char * +handle_module_path(const char *module_path) +{ + // next character after = + return (strchr(module_path, '=')) + 1; +} + +static char *module_search_path = "."; +static bool +module_reader_callback(const char *module_name, uint8 **p_buffer, + uint32 *p_size) +{ + const char *format = "%s/%s.wasm"; + int sz = strlen(module_search_path) + strlen("/") + strlen(module_name) + + strlen(".wasm") + 1; + char *wasm_file_name = BH_MALLOC(sz); + if (!wasm_file_name) { + return false; + } + + snprintf(wasm_file_name, sz, format, module_search_path, module_name); + + *p_buffer = (uint8_t *)bh_read_file_to_buffer(wasm_file_name, p_size); + + wasm_runtime_free(wasm_file_name); + return *p_buffer != NULL; +} + +static void +moudle_destroyer(uint8 *buffer, uint32 size) +{ + if (!buffer) { + return; + } + + wasm_runtime_free(buffer); + buffer = NULL; +} +#endif /* WASM_ENABLE_MULTI_MODULE */ + +int +main(int argc, char *argv[]) +{ + char *wasm_file = NULL; + const char *func_name = NULL; + uint8 *wasm_file_buf = NULL; + uint32 wasm_file_size; + uint32 stack_size = 16 * 1024, heap_size = 16 * 1024; + wasm_module_t wasm_module = NULL; + wasm_module_inst_t wasm_module_inst = NULL; + RuntimeInitArgs init_args; + char error_buf[128] = { 0 }; +#if WASM_ENABLE_LOG != 0 + int log_verbose_level = 2; +#endif +#if WASM_ENABLE_LIBC_WASI != 0 + const char *dir_list[8] = { NULL }; + uint32 dir_list_size = 0; + const char *env_list[8] = { NULL }; + uint32 env_list_size = 0; +#endif + + /* Process options. */ + // TODO: use a option name and option handler pair table to + // optimize + for (argc--, argv++; argc > 0 && argv[0][0] == '-'; argc--, argv++) { + if (!strcmp(argv[0], "-f") || !strcmp(argv[0], "--function")) { + argc--, argv++; + if (argc < 2) { + print_help(); + return 0; + } + func_name = argv[0]; + } +#if WASM_ENABLE_LOG != 0 + else if (!strncmp(argv[0], "-v=", 3)) { + log_verbose_level = atoi(argv[0] + 3); + if (log_verbose_level < 0 || log_verbose_level > 5) + return print_help(); + } +#endif + else if (!strncmp(argv[0], "--stack-size=", 13)) { + if (argv[0][13] == '\0') + return print_help(); + stack_size = atoi(argv[0] + 13); + } + else if (!strncmp(argv[0], "--heap-size=", 12)) { + if (argv[0][12] == '\0') + return print_help(); + heap_size = atoi(argv[0] + 12); + } +#if WASM_ENABLE_LIBC_WASI != 0 + else if (!strncmp(argv[0], "--dir=", 6)) { + if (argv[0][6] == '\0') + return print_help(); + if (dir_list_size >= sizeof(dir_list) / sizeof(char *)) { + printf("Only allow max dir number %d\n", + (int)(sizeof(dir_list) / sizeof(char *))); + return -1; + } + dir_list[dir_list_size++] = argv[0] + 6; + } + else if (!strncmp(argv[0], "--env=", 6)) { + char *tmp_env; + + if (argv[0][6] == '\0') + return print_help(); + if (env_list_size >= sizeof(env_list) / sizeof(char *)) { + printf("Only allow max env number %d\n", + (int)(sizeof(env_list) / sizeof(char *))); + return -1; + } + tmp_env = argv[0] + 6; + if (validate_env_str(tmp_env)) + env_list[env_list_size++] = tmp_env; + else { + printf("Wasm parse env string failed: expect \"key=value\", " + "got \"%s\"\n", + tmp_env); + return print_help(); + } + } +#endif /* WASM_ENABLE_LIBC_WASI */ +#if WASM_ENABLE_MULTI_MODULE != 0 + else if (!strncmp(argv[0], MODULE_PATH, strlen(MODULE_PATH))) { + module_search_path = handle_module_path(argv[0]); + if (!strlen(module_search_path)) { + return print_help(); + } + } +#endif +#if WASM_ENABLE_LIB_PTHREAD != 0 + else if (!strncmp(argv[0], "--max-threads=", 14)) { + if (argv[0][14] == '\0') + return print_help(); + wasm_runtime_set_max_thread_num(atoi(argv[0] + 14)); + } +#endif + else + return print_help(); + } + + if (argc == 0) + return print_help(); + + wasm_file = argv[0]; + app_argc = argc; + app_argv = argv; + + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + +#if USE_GLOBAL_HEAP_BUF != 0 + init_args.mem_alloc_type = Alloc_With_Pool; + init_args.mem_alloc_option.pool.heap_buf = global_heap_buf; + init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf); +#else + init_args.mem_alloc_type = Alloc_With_Allocator; + init_args.mem_alloc_option.allocator.malloc_func = malloc; + init_args.mem_alloc_option.allocator.realloc_func = realloc; + init_args.mem_alloc_option.allocator.free_func = free; +#endif + + /* initialize runtime environment */ + if (!wasm_runtime_full_init(&init_args)) { + printf("Init runtime environment failed.\n"); + return -1; + } + +#if WASM_ENABLE_LOG != 0 + bh_log_set_verbose_level(log_verbose_level); +#endif + + /* load WASM byte buffer from WASM bin file */ + if (!(wasm_file_buf = + (uint8 *)bh_read_file_to_buffer(wasm_file, &wasm_file_size))) + goto fail1; + +#if WASM_ENABLE_MULTI_MODULE != 0 + wasm_runtime_set_module_reader(module_reader_callback, moudle_destroyer); +#endif + + /* load WASM module */ + if (!(wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, + error_buf, sizeof(error_buf)))) { + printf("%s\n", error_buf); + goto fail2; + } + +#if WASM_ENABLE_LIBC_WASI != 0 + wasm_runtime_set_wasi_args(wasm_module, dir_list, dir_list_size, NULL, 0, + env_list, env_list_size, argv, argc); +#endif + + /* instantiate the module */ + if (!(wasm_module_inst = + wasm_runtime_instantiate(wasm_module, stack_size, heap_size, + error_buf, sizeof(error_buf)))) { + printf("%s\n", error_buf); + goto fail3; + } + + if (func_name) + app_instance_func(wasm_module_inst, func_name); + else + app_instance_main(wasm_module_inst); + + /* destroy the module instance */ + wasm_runtime_deinstantiate(wasm_module_inst); + +fail3: + /* unload the module */ + wasm_runtime_unload(wasm_module); + +fail2: + /* free the file buffer */ + wasm_runtime_free(wasm_file_buf); + +fail1: + /* destroy runtime environment */ + wasm_runtime_destroy(); + return 0; +} diff --git a/product-mini/platforms/nuttx/wamr.mk b/product-mini/platforms/nuttx/wamr.mk new file mode 100644 index 0000000..56fadfa --- /dev/null +++ b/product-mini/platforms/nuttx/wamr.mk @@ -0,0 +1,141 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +CORE_ROOT := wamr/core +IWASM_ROOT := wamr/core/iwasm +SHARED_ROOT := wamr/core/shared + +ifeq ($(CONFIG_ARCH_ARMV7M),y) +WAMR_BUILD_TARGET := THUMBV7EM +else ifeq ($(CONFIG_ARCH_ARMV8M),y) +WAMR_BUILD_TARGET := THUMBV8M +else ifeq ($(CONFIG_ARCH_X86),y) +WAMR_BUILD_TARGET := X86_32 +else ifeq ($(CONFIG_ARCH_X86_64),y) +WAMR_BUILD_TARGET := X86_64 +else ifeq ($(CONFIG_ARCH_XTENSA),y) +WAMR_BUILD_TARGET := XTENSA +endif + +WAMR_BUILD_PLATFORM := nuttx + +ifeq (${WAMR_BUILD_TARGET}, X86_32) + CFLAGS += -DBUILD_TARGET_X86_32 + INVOKE_NATIVE := invokeNative_ia32.s + AOT_RELOC := aot_reloc_x86_32.c +else ifeq (${WAMR_BUILD_TARGET}, X86_64) + CFLAGS += -DBUILD_TARGET_X86_64 + INVOKE_NATIVE := invokeNative_em64.s + AOT_RELOC := aot_reloc_x86_64.c +else ifeq ($(findstring ARM,$(WAMR_BUILD_TARGET)), ARM) + CFLAGS += -DBUILD_TARGET_ARM + CFLAGS += -DBUILD_TARGET=\"$(WAMR_BUILD_TARGET)\" + INVOKE_NATIVE := invokeNative_arm.s + AOT_RELOC := aot_reloc_arm.c +else ifeq ($(findstring THUMB,$(WAMR_BUILD_TARGET)), THUMB) + CFLAGS += -DBUILD_TARGET_THUMB + CFLAGS += -DBUILD_TARGET=\"$(WAMR_BUILD_TARGET)\" + ifeq ($(CONFIG_ARCH_FPU),y) + INVOKE_NATIVE := invokeNative_thumb_vfp.s + else + INVOKE_NATIVE := invokeNative_thumb.s + endif + AOT_RELOC := aot_reloc_thumb.c +else ifeq (${WAMR_BUILD_TARGET}, MIPS) + CFLAGS += -DBUILD_TARGET_MIPS + INVOKE_NATIVE := invokeNative_mips.s + AOT_RELOC := aot_reloc_mips.c +else ifeq (${WAMR_BUILD_TARGET}, XTENSA) + CFLAGS += -DBUILD_TARGET_XTENSA + INVOKE_NATIVE := invokeNative_xtensa.s + AOT_RELOC := aot_reloc_xtensa.c +else + $(error Build target don't support) +endif + +ifeq (${CONFIG_INTERPRETERS_WAMR_LOG},y) +CFLAGS += -DWASM_ENABLE_LOG=1 +else +CFLAGS += -DWASM_ENABLE_LOG=0 +endif + +ifeq (${CONFIG_INTERPRETERS_WAMR_AOT},y) +CFLAGS += -I${IWASM_ROOT}/aot +CFLAGS += -DWASM_ENABLE_AOT=1 +CSRCS += aot_loader.c \ + ${AOT_RELOC} \ + aot_runtime.c +else +CFLAGS += -DWASM_ENABLE_AOT=0 +endif + +CFLAGS += -DWASM_ENABLE_INTERP=1 +CSRCS += wasm_runtime.c wasm_loader.c + +ifeq (${CONFIG_INTERPRETERS_WAMR_FAST},y) +CFLAGS += -DWASM_ENABLE_FAST_INTERP=1 +CSRCS += wasm_interp_fast.c +else +CSRCS += wasm_interp_classic.c +endif + +ifeq ($(CONFIG_INTERPRETERS_WAMR_LIBC_BUILTIN),y) +CFLAGS += -DWASM_ENABLE_LIBC_BUILTIN=1 +else +CFLAGS += -DWASM_ENABLE_LIBC_BUILTIN=0 +endif + +CFLAGS += -DWASM_ENABLE_MULTI_MODULE=0 +CFLAGS += -DWASM_ENABLE_THREAD_MGR=0 +CFLAGS += -Wno-strict-prototypes + +CFLAGS += -I${CORE_ROOT} \ + -I${IWASM_ROOT}/include \ + -I${IWASM_ROOT}/common \ + -I${SHARED_ROOT}/include \ + -I${SHARED_ROOT}/platform/include \ + -I${SHARED_ROOT}/utils \ + -I${SHARED_ROOT}/utils/uncommon \ + -I${SHARED_ROOT}/mem-alloc \ + -I${SHARED_ROOT}/platform/nuttx + + +ifeq (${WAMR_BUILD_INTERP}, 1) +CFLAGS += -I${IWASM_ROOT}/interpreter +endif + +CSRCS += nuttx_platform.c \ + nuttx_thread.c \ + mem_alloc.c \ + ems_kfc.c \ + ems_alloc.c \ + ems_hmu.c \ + bh_assert.c \ + bh_common.c \ + bh_hashmap.c \ + bh_list.c \ + bh_log.c \ + bh_queue.c \ + bh_vector.c \ + bh_read_file.c \ + runtime_timer.c \ + libc_builtin_wrapper.c \ + wasm_runtime_common.c \ + wasm_native.c \ + wasm_exec_env.c \ + wasm_memory.c + +ASRCS += ${INVOKE_NATIVE} + +VPATH += ${SHARED_ROOT}/platform/nuttx +VPATH += ${SHARED_ROOT}/mem-alloc +VPATH += ${SHARED_ROOT}/mem-alloc/ems +VPATH += ${SHARED_ROOT}/utils +VPATH += ${SHARED_ROOT}/utils/uncommon +VPATH += ${IWASM_ROOT}/common +VPATH += ${IWASM_ROOT}/interpreter +VPATH += ${IWASM_ROOT}/libraries +VPATH += ${IWASM_ROOT}/libraries/libc-builtin +VPATH += ${IWASM_ROOT}/common/arch +VPATH += ${IWASM_ROOT}/aot +VPATH += ${IWASM_ROOT}/aot/arch -- 2.25.1