You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2024/09/28 07:47:47 UTC
(nuttx-apps) 01/02: wamr: Add external module registration mechanism
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx-apps.git
commit 9320597c00ec1f8f0bc2f20877516d33e49389fe
Author: Huang Qi <hu...@xiaomi.com>
AuthorDate: Fri Aug 23 10:25:06 2024 +0800
wamr: Add external module registration mechanism
This patch adds module registration mechanism for WAMR runtime.
To register a module, these steps are required:
1. Include Module.mk in your module's Makefile
2. Define WAMR_MODULE_NAME as the module name
3. Implement bool wamr_module_WAMR_MODULE_NAME_register(void) function in your module's source file
4. Enable INTERPRETERS_WAMR_EXTERNAL_MODULE_REGISTRY in menuconfig
Signed-off-by: Huang Qi <hu...@xiaomi.com>
---
CMakeLists.txt | 1 +
cmake/nuttx_add_wamrmod.cmake | 76 ++++++++++++++++++++++++++++++++
interpreters/wamr/.gitignore | 2 +
interpreters/wamr/CMakeLists.txt | 13 ++++++
interpreters/wamr/Kconfig | 10 ++++-
interpreters/wamr/Makefile | 58 ++++++++++++++++++++++++-
interpreters/wamr/Module.mk | 37 ++++++++++++++++
interpreters/wamr/registry/.gitignore | 3 ++
interpreters/wamr/wamr_custom_init.c | 82 +++++++++++++++++++++++++++++++++++
9 files changed, 280 insertions(+), 2 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index d07eaef87..f35203b3e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -30,6 +30,7 @@ if(CONFIG_APPS_DIR)
# add apps cmake modules
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/cmake)
include(nuttx_add_luamod)
+ include(nuttx_add_wamrmod)
nuttx_add_library(apps)
if(NOT EXISTS {NUTTX_APPS_BINDIR}/dummy.c)
file(TOUCH ${NUTTX_APPS_BINDIR}/dummy.c)
diff --git a/cmake/nuttx_add_wamrmod.cmake b/cmake/nuttx_add_wamrmod.cmake
new file mode 100644
index 000000000..231c64d9c
--- /dev/null
+++ b/cmake/nuttx_add_wamrmod.cmake
@@ -0,0 +1,76 @@
+# ##############################################################################
+# cmake/nuttx_add_wamrmod.cmake
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more contributor
+# license agreements. See the NOTICE file distributed with this work for
+# additional information regarding copyright ownership. The ASF licenses this
+# file to you under the Apache License, Version 2.0 (the "License"); you may not
+# use this file except in compliance with the License. You may obtain a copy of
+# the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations under
+# the License.
+#
+# ##############################################################################
+
+set(WAMR_MODULE_DIR ${CMAKE_BINARY_DIR}/wamrmod)
+
+if(NOT EXISTS {WAMR_MODULE_DIR})
+ file(MAKE_DIRECTORY ${WAMR_MODULE_DIR})
+endif()
+
+include(nuttx_parse_function_args)
+
+# ~~~
+# nuttx_add_wamrmod
+#
+# Description:
+# Register custom module into WAMR runtime
+#
+# Example:
+# nuttx_add_wamrmod(
+# MODS
+# ${custom_mods}
+# )
+# ~~~
+
+function(nuttx_add_wamrmod)
+
+ # parse arguments into variables
+
+ nuttx_parse_function_args(
+ FUNC
+ nuttx_add_wamrmod
+ MULTI_VALUE
+ MODS
+ REQUIRED
+ MODS
+ ARGN
+ ${ARGN})
+
+ set(WAMR_MODULE_LIST ${WAMR_MODULE_DIR}/wamr_external_module_list.h)
+ set(WAMR_MODULE_PROTO ${WAMR_MODULE_DIR}/wamr_external_module_proto.h)
+ foreach(mod ${MODS})
+ set(MOD_PDAT ${WAMR_MODULE_DIR}/${mod}.pdat)
+ set(MOD_BDAT ${WAMR_MODULE_DIR}/${mod}.bdat)
+ add_custom_command(
+ OUTPUT ${MOD_PDAT} ${MOD_BDAT}
+ COMMAND ${CMAKE_COMMAND} -E echo "wamr_module_${mod}_register," >>
+ ${WAMR_MODULE_LIST}
+ COMMAND ${CMAKE_COMMAND} -E echo "bool wamr_module_${mod}_register(void);"
+ >> ${WAMR_MODULE_PROTO}
+ COMMAND ${CMAKE_COMMAND} -E touch ${MOD_PDAT}
+ COMMAND ${CMAKE_COMMAND} -E touch ${MOD_BDAT}
+ WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
+ VERBATIM
+ COMMENT "WAMR Module: Gen and Updating external module => ${mod}")
+ add_custom_target(wamr_module_${mod} DEPENDS ${MOD_PDAT} ${MOD_BDAT})
+ add_dependencies(apps_context wamr_module_${mod})
+ endforeach()
+
+endfunction()
diff --git a/interpreters/wamr/.gitignore b/interpreters/wamr/.gitignore
index 0cb73d0fd..2a85b17bf 100644
--- a/interpreters/wamr/.gitignore
+++ b/interpreters/wamr/.gitignore
@@ -1,3 +1,5 @@
*.zip
wamr
wasm-micro-runtime-*
+wamr_external_module_list.h
+wamr_external_module_proto.h
diff --git a/interpreters/wamr/CMakeLists.txt b/interpreters/wamr/CMakeLists.txt
index ce3be5f35..1fe37c878 100644
--- a/interpreters/wamr/CMakeLists.txt
+++ b/interpreters/wamr/CMakeLists.txt
@@ -71,4 +71,17 @@ if(CONFIG_INTERPRETERS_WAMR)
DEPENDS
wamr)
+ if(CONFIG_INTERPRETERS_WAMR_LIBC_NUTTX
+ OR CONFIG_INTERPRETERS_WAMR_EXTERNAL_MODULE_REGISTRY)
+ nuttx_append_source_file_properties(
+ ${WAMR_DIR}/product-mini/platforms/nuttx/main.c COMPILE_FLAGS
+ -Dwasm_runtime_full_init=wamr_custom_init)
+ target_sources(wamr PRIVATE wamr_custom_init.c)
+ endif()
+
+ # Add ${CMAKE_BINARY_DIR}/wamrmod to the include directories
+ if(CONFIG_INTERPRETERS_WAMR_EXTERNAL_MODULE_REGISTRY)
+ target_include_directories(wamr PRIVATE ${CMAKE_BINARY_DIR}/wamrmod)
+ endif()
+
endif()
diff --git a/interpreters/wamr/Kconfig b/interpreters/wamr/Kconfig
index fbad67be1..3811d5381 100644
--- a/interpreters/wamr/Kconfig
+++ b/interpreters/wamr/Kconfig
@@ -248,4 +248,12 @@ config INTERPRETERS_WAMR_CONFIGUABLE_BOUNDS_CHECKS
disable bounds checks passing --disable-bounds-checks to
iwasm.
-endif # INTERPRETERS_WAMR
+config INTERPRETERS_WAMR_EXTERNAL_MODULE_REGISTRY
+ bool "Enable external module registry"
+ default n
+ ---help---
+ This option enables the support for loading WASM modules from
+ external libraries, which is useful when you want to extend the
+ functionality of WAMR without modifying its source code.
+
+endif
diff --git a/interpreters/wamr/Makefile b/interpreters/wamr/Makefile
index f7dcae4d6..f52d5adaa 100644
--- a/interpreters/wamr/Makefile
+++ b/interpreters/wamr/Makefile
@@ -39,6 +39,23 @@ PROGNAME = iwasm
PRIORITY = $(CONFIG_INTERPRETERS_WAMR_PRIORITY)
STACKSIZE = $(CONFIG_INTERPRETERS_WAMR_STACKSIZE)
MODULE = $(CONFIG_INTERPRETERS_WAMR)
+
+endif
+
+WAMR_NEED_CUSTOM_INIT = n
+
+# Check if we need to build custom init code
+
+ifeq ($(CONFIG_INTERPRETERS_WAMR_EXTERNAL_MODULE_REGISTRY),y)
+WAMR_NEED_CUSTOM_INIT = y
+endif
+
+# If we need custom init code, add it to the build
+ifeq ($(WAMR_NEED_CUSTOM_INIT),y)
+# When the loadable module configuration is enabled,we need to use CELFFLAGS
+$(WAMR_UNPACK)/product-mini/platforms/nuttx/main.c_CFLAGS = -Dwasm_runtime_full_init=wamr_custom_init
+$(WAMR_UNPACK)/product-mini/platforms/nuttx/main.c_CELFFLAGS = -Dwasm_runtime_full_init=wamr_custom_init
+CSRCS += wamr_custom_init.c
endif
$(WAMR_TARBALL):
@@ -51,11 +68,50 @@ $(WAMR_UNPACK): $(WAMR_TARBALL)
$(Q) mv wasm-micro-runtime-$(WAMR_VERSION) $(WAMR_UNPACK)
$(Q) touch $(WAMR_UNPACK)
+# Register the external WAMR module
+
+ifeq ($(CONFIG_INTERPRETERS_WAMR_EXTERNAL_MODULE_REGISTRY),y)
+
+PDATLIST = $(strip $(call RWILDCARD, registry, *.pdat))
+BDATLIST = $(strip $(call RWILDCARD, registry, *.bdat))
+
+registry$(DELIM).updated:
+ $(Q) touch registry$(DELIM).updated
+
+wamr_external_module_list.h: registry$(DELIM).updated
+ifeq ($(BDATLIST),)
+ $(call DELFILE, wamr_external_module_list.h)
+ $(Q) touch wamr_external_module_list.h
+else
+ $(call CATFILE, wamr_external_module_list.h, $(BDATLIST))
+endif
+
+wamr_external_module_proto.h: registry$(DELIM).updated
+ifeq ($(PDATLIST),)
+ $(call DELFILE, wamr_external_module_proto.h)
+ $(Q) touch wamr_external_module_proto.h
+else
+ $(call CATFILE, wamr_external_module_proto.h, $(PDATLIST))
+endif
+
+depend:: $(GLUECSRCS) wamr_external_module_list.h wamr_external_module_proto.h
+endif # CONFIG_INTERPRETERS_WAMR_EXTERNAL_MODULE_REGISTRY
+
+clean::
+ $(call DELFILE, wamr_external_module_list.h)
+ $(call DELFILE, wamr_external_module_proto.h)
+
+clean_context::
+ $(call DELFILE, $(BDATLIST))
+ $(call DELFILE, $(PDATLIST))
+
# Download and unpack tarball if no git repo found
ifeq ($(wildcard $(WAMR_UNPACK)/.git),)
context:: $(WAMR_UNPACK)
+endif
-distclean::
+distclean:: clean clean_context
+ifeq ($(wildcard $(WAMR_UNPACK)/.git),)
$(call DELDIR, $(WAMR_UNPACK))
$(call DELFILE, $(WAMR_TARBALL))
endif
diff --git a/interpreters/wamr/Module.mk b/interpreters/wamr/Module.mk
new file mode 100644
index 000000000..b30eb6c87
--- /dev/null
+++ b/interpreters/wamr/Module.mk
@@ -0,0 +1,37 @@
+############################################################################
+# apps/interpreters/wamr/Module.mk
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership. The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+############################################################################
+
+WAMR_MODULE_REGISTRY = $(APPDIR)$(DELIM)interpreters$(DELIM)wamr$(DELIM)registry
+
+define WAMR_MODULE_REGISTER
+ $(Q) echo Register WAMR Module: $1
+ $(Q) echo "$2," > "$(WAMR_MODULE_REGISTRY)$(DELIM)$1.bdat"
+ $(Q) echo "bool $2(void);" > "$(WAMR_MODULE_REGISTRY)$(DELIM)$1.pdat"
+ $(Q) touch "$(WAMR_MODULE_REGISTRY)$(DELIM).updated"
+endef
+
+ifneq ($(WAMR_MODULE_NAME),)
+WAMR_MODULE_LIST := $(addprefix $(WAMR_MODULE_REGISTRY)$(DELIM),$(addsuffix .bdat,$(WAMR_MODULE_NAME)))
+$(WAMR_MODULE_LIST): $(DEPCONFIG) Makefile
+ $(call WAMR_MODULE_REGISTER,$(firstword $(WAMR_MODULE_NAME)),$(firstword wamr_module_$(WAMR_MODULE_NAME)_register))
+ $(eval WAMR_MODULE_NAME=$(filter-out $(firstword $(WAMR_MODULE_NAME)),$(WAMR_MODULE_NAME)))
+
+register:: $(WAMR_MODULE_LIST)
+endif
diff --git a/interpreters/wamr/registry/.gitignore b/interpreters/wamr/registry/.gitignore
new file mode 100644
index 000000000..3fd3b08fc
--- /dev/null
+++ b/interpreters/wamr/registry/.gitignore
@@ -0,0 +1,3 @@
+.updated
+*.pdat
+*.bdat
diff --git a/interpreters/wamr/wamr_custom_init.c b/interpreters/wamr/wamr_custom_init.c
new file mode 100644
index 000000000..1c4dd4303
--- /dev/null
+++ b/interpreters/wamr/wamr_custom_init.c
@@ -0,0 +1,82 @@
+/****************************************************************************
+ * apps/interpreters/wamr/wamr_custom_init.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <semaphore.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <iconv.h>
+
+#include "wasm_native.h"
+
+#include "wamr_custom_init.h"
+
+#ifdef CONFIG_INTERPRETERS_WAMR_EXTERNAL_MODULE_REGISTRY
+#include "wamr_external_module_proto.h"
+#endif
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+typedef bool (*module_register_t)(void);
+
+#ifdef CONFIG_INTERPRETERS_WAMR_EXTERNAL_MODULE_REGISTRY
+static const module_register_t g_wamr_modules[] =
+{
+#include "wamr_external_module_list.h"
+};
+#endif
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+bool wamr_custom_init(RuntimeInitArgs *init_args)
+{
+ bool ret = wasm_runtime_full_init(init_args);
+
+ if (!ret)
+ {
+ return ret;
+ }
+
+ /* Add extra init hook here */
+
+#ifdef CONFIG_INTERPRETERS_WAMR_EXTERNAL_MODULE_REGISTRY
+ for (int i = 0; i < nitems(g_wamr_modules); i++)
+ {
+ ret = g_wamr_modules[i]();
+ if (!ret)
+ {
+ return ret;
+ }
+ }
+#endif
+
+ return ret;
+}