From 73bc5cbcc61e3a887a6af4c17e7c9a86eef737eb Mon Sep 17 00:00:00 2001 From: Huang Qi Date: Thu, 25 Dec 2025 14:37:31 +0800 Subject: [PATCH] interpreters: Add mquickjs JavaScript interpreter integration Add complete integration for the MicroQuickJS JavaScript interpreter, supporting both CMake and Make build systems with automatic source acquisition. Key features: * FetchContent downloads mquickjs from bellard/mquickjs if local git repository is not available in interpreters/mquickjs/mquickjs/ * Builds mqjs_stdlib host tool to generate mqjs_stdlib.h and mquickjs_atom.h headers during build * Creates libmquickjs library with proper header generation dependencies to prevent parallel build failures * Provides mqjs NSH application for interactive JavaScript execution * Configurable task priority and stack size via Kconfig options (INTERPRETERS_MQJS_PRIORITY, INTERPRETERS_MQJS_STACKSIZE) * Supports both 32-bit and 64-bit architectures with appropriate build flags Files added: * CMakeLists.txt - CMake build configuration with FetchContent support * Kconfig - Configuration options for interpreter features * Make.defs - Make build definitions * Makefile - Alternative Make-based build support * .gitignore - Ignores generated files and local mquickjs source directory Signed-off-by: Huang Qi --- interpreters/mquickjs/.gitignore | 2 + interpreters/mquickjs/CMakeLists.txt | 123 +++++++++++++++++++++++++++ interpreters/mquickjs/Kconfig | 24 ++++++ interpreters/mquickjs/Make.defs | 30 +++++++ interpreters/mquickjs/Makefile | 92 ++++++++++++++++++++ 5 files changed, 271 insertions(+) create mode 100644 interpreters/mquickjs/.gitignore create mode 100644 interpreters/mquickjs/CMakeLists.txt create mode 100644 interpreters/mquickjs/Kconfig create mode 100644 interpreters/mquickjs/Make.defs create mode 100644 interpreters/mquickjs/Makefile diff --git a/interpreters/mquickjs/.gitignore b/interpreters/mquickjs/.gitignore new file mode 100644 index 000000000..87708e7fd --- /dev/null +++ b/interpreters/mquickjs/.gitignore @@ -0,0 +1,2 @@ +*.d +mquickjs/ diff --git a/interpreters/mquickjs/CMakeLists.txt b/interpreters/mquickjs/CMakeLists.txt new file mode 100644 index 000000000..51d505860 --- /dev/null +++ b/interpreters/mquickjs/CMakeLists.txt @@ -0,0 +1,123 @@ +# ############################################################################## +# apps/interpreters/mquickjs/CMakeLists.txt +# +# SPDX-License-Identifier: Apache-2.0 +# +# 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. +# +# ############################################################################## + +if(CONFIG_INTERPRETERS_MQJS) + set(MQJS_SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/mquickjs) + + # Prefer local git repo if it exists, otherwise download tarball + if(EXISTS ${MQJS_SOURCE_DIR}/.git) + # Use local git-managed mquickjs + set(MQJS_DIR ${MQJS_SOURCE_DIR}) + message(STATUS "Using local mquickjs git repo: ${MQJS_DIR}") + else() + # Download mquickjs to build directory + FetchContent_Declare( + mquickjs_fetch + URL https://github.com/bellard/mquickjs/archive/refs/heads/main.zip + DOWNLOAD_NO_PROGRESS true + TIMEOUT 30) + + FetchContent_MakeAvailable(mquickjs_fetch) + + # The source directory after FetchContent_MakeAvailable + set(MQJS_DIR ${mquickjs_fetch_SOURCE_DIR}) + message(STATUS "Using downloaded mquickjs: ${MQJS_DIR}") + endif() + + # Detect target architecture for header generation + if(CONFIG_ARCH_64BIT) + set(MQJS_BUILD_FLAGS "-m64") + else() + set(MQJS_BUILD_FLAGS "-m32") + endif() + + include(ExternalProject) + + # Build mqjs_stdlib host tool using mquickjs Makefile + ExternalProject_Add( + mqjs_stdlib_host + SOURCE_DIR ${MQJS_DIR} + BINARY_DIR ${MQJS_DIR} + CONFIGURE_COMMAND "" + BUILD_COMMAND make mqjs_stdlib + INSTALL_COMMAND "" + BUILD_BYPRODUCTS ${MQJS_DIR}/mqjs_stdlib) + + # Generate mqjs_stdlib.h + add_custom_command( + OUTPUT ${MQJS_DIR}/mqjs_stdlib.h + COMMAND ${MQJS_DIR}/mqjs_stdlib ${MQJS_BUILD_FLAGS} > + ${MQJS_DIR}/mqjs_stdlib.h + DEPENDS mqjs_stdlib_host + COMMENT "Generating mqjs_stdlib.h") + + # Generate mquickjs_atom.h + add_custom_command( + OUTPUT ${MQJS_DIR}/mquickjs_atom.h + COMMAND ${MQJS_DIR}/mqjs_stdlib -a ${MQJS_BUILD_FLAGS} > + ${MQJS_DIR}/mquickjs_atom.h + DEPENDS mqjs_stdlib_host + COMMENT "Generating mquickjs_atom.h") + + # Custom target for header generation + add_custom_target(mqjs_headers_gen DEPENDS ${MQJS_DIR}/mqjs_stdlib.h + ${MQJS_DIR}/mquickjs_atom.h) + + # Create mquickjs library + nuttx_add_library(libmquickjs) + target_sources( + libmquickjs + PRIVATE ${MQJS_DIR}/mquickjs.c ${MQJS_DIR}/dtoa.c ${MQJS_DIR}/libm.c + ${MQJS_DIR}/cutils.c ${MQJS_DIR}/readline.c + ${MQJS_DIR}/readline_tty.c) + target_include_directories(libmquickjs PRIVATE ${MQJS_DIR}) + nuttx_export_header(TARGET libmquickjs INCLUDE_DIRECTORIES ${MQJS_DIR}) + + # Ensure headers are generated before building library + add_dependencies(libmquickjs mqjs_headers_gen) + + # Add mquickjs include directory to global include paths + set_property( + TARGET nuttx + APPEND + PROPERTY NUTTX_INCLUDE_DIRECTORIES ${NUTTX_APPS_DIR}/interpreters/mquickjs) + + # Create mqjs NSH application + set(MQJS_PRIORITY ${CONFIG_INTERPRETERS_MQJS_PRIORITY}) + set(MQJS_STACKSIZE ${CONFIG_INTERPRETERS_MQJS_STACKSIZE}) + + nuttx_add_application( + NAME + mqjs + PRIORITY + ${MQJS_PRIORITY} + STACKSIZE + ${MQJS_STACKSIZE} + SRCS + ${MQJS_DIR}/mqjs.c + INCLUDE_DIRECTORIES + ${MQJS_DIR} + DEPENDS + libmquickjs + mqjs_headers_gen) + +endif() diff --git a/interpreters/mquickjs/Kconfig b/interpreters/mquickjs/Kconfig new file mode 100644 index 000000000..06e8906b7 --- /dev/null +++ b/interpreters/mquickjs/Kconfig @@ -0,0 +1,24 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +config INTERPRETERS_MQJS + tristate "MicroQuickJS JavaScript interpreter" + default n + +if INTERPRETERS_MQJS + +config INTERPRETERS_MQJS_PRIORITY + int "MicroQuickJS interpreter priority" + default 100 + ---help--- + Task priority of the MicroQuickJS interpreter. + + config INTERPRETERS_MQJS_STACKSIZE + int "MicroQuickJS interpreter stack size" + default 8192 + ---help--- + Size of the stack allocated for MicroQuickJS interpreter. + + endif # INTERPRETERS_MQJS diff --git a/interpreters/mquickjs/Make.defs b/interpreters/mquickjs/Make.defs new file mode 100644 index 000000000..8850fa7b6 --- /dev/null +++ b/interpreters/mquickjs/Make.defs @@ -0,0 +1,30 @@ +############################################################################ +# apps/interpreters/mquickjs/Make.defs +# +# SPDX-License-Identifier: Apache-2.0 +# +# 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 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. +# +############################################################################ + +ifneq ($(CONFIG_INTERPRETERS_MQJS),) +CONFIGURED_APPS += $(APPDIR)/interpreters/mquickjs + +# It allows `` import. +CFLAGS += ${INCDIR_PREFIX}$(APPDIR)/interpreters/mquickjs/mquickjs +CXXFLAGS += ${INCDIR_PREFIX}$(APPDIR)/interpreters/mquickjs/mquickjs + +endif diff --git a/interpreters/mquickjs/Makefile b/interpreters/mquickjs/Makefile new file mode 100644 index 000000000..2c1ed3e49 --- /dev/null +++ b/interpreters/mquickjs/Makefile @@ -0,0 +1,92 @@ +############################################################################ +# apps/interpreters/mquickjs/Makefile +# +# SPDX-License-Identifier: Apache-2.0 +# +# 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 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. +# +############################################################################ + +include $(APPDIR)/Make.defs + +MQJS_UNPACK = mquickjs +MQJS_ARCHIVE = mquickjs-master.zip +MQJS_URL = https://github.com/bellard/mquickjs/archive/refs/heads/master.zip + +# Determine target word size for header generation +ifeq ($(CONFIG_ARCH_64BIT),y) +MQJS_BUILD_FLAGS = -m64 +else +MQJS_BUILD_FLAGS = -m32 +endif + +CSRCS = $(MQJS_UNPACK)/mquickjs.c \ + $(MQJS_UNPACK)/dtoa.c \ + $(MQJS_UNPACK)/libm.c \ + $(MQJS_UNPACK)/cutils.c \ + $(MQJS_UNPACK)/readline.c \ + $(MQJS_UNPACK)/readline_tty.c + +PROGNAME = mqjs +PRIORITY = $(CONFIG_INTERPRETERS_MQJS_PRIORITY) +STACKSIZE = $(CONFIG_INTERPRETERS_MQJS_STACKSIZE) +MODULE = $(CONFIG_INTERPRETERS_MQJS) +MAINSRC = $(MQJS_UNPACK)/mqjs.c + +# Download archive +$(MQJS_ARCHIVE): + $(Q) echo "Downloading $(MQJS_ARCHIVE)" + $(Q) curl -L $(MQJS_URL) -o $(MQJS_ARCHIVE) + +# Unpack archive +$(MQJS_UNPACK): $(MQJS_ARCHIVE) + $(Q) echo "Unpacking $(MQJS_ARCHIVE) to $(MQJS_UNPACK)" + $(Q) unzip -q -o $(MQJS_ARCHIVE) + $(Q) mv bellard-mquickjs-* $(MQJS_UNPACK) + $(Q) touch $(MQJS_UNPACK) + +# Build host tool via upstream Makefile +$(MQJS_UNPACK)/mqjs_stdlib: + $(Q) echo "Building mquickjs host tool via upstream Makefile" + $(Q) rm -f $(MQJS_UNPACK)/mqjs_stdlib + $(Q) $(MAKE) -C $(MQJS_UNPACK) HOSTCC=$(HOSTCC) mqjs_stdlib + +# Generate stdlib header using built host tool +$(MQJS_UNPACK)/mqjs_stdlib.h: $(MQJS_UNPACK)/mqjs_stdlib + $(Q) echo "Generating mquickjs stdlib header" + $(MQJS_UNPACK)/mqjs_stdlib $(MQJS_BUILD_FLAGS) > $@ + +# Generate atom header using built host tool +$(MQJS_UNPACK)/mquickjs_atom.h: $(MQJS_UNPACK)/mqjs_stdlib + $(Q) echo "Generating mquickjs atom header" + $(MQJS_UNPACK)/mqjs_stdlib -a $(MQJS_BUILD_FLAGS) > $@ + +# Download and unpack only if not a git repository +context:: $(MQJS_UNPACK)/mqjs_stdlib.h $(MQJS_UNPACK)/mquickjs_atom.h + +# Clean up on distclean +distclean:: +ifneq ($(wildcard $(MQJS_UNPACK)/.git),) + $(Q) $(MAKE) -C $(MQJS_UNPACK) clean +else + $(call DELDIR, $(MQJS_UNPACK)) +endif + $(call DELFILE, $(MQJS_ARCHIVE)) + +# Dependencies +$(MQJS_UNPACK)/mquickjs.c: $(MQJS_UNPACK)/mquickjs_atom.h + +include $(APPDIR)/Application.mk