diff --git a/CMakeLists.txt b/CMakeLists.txt index 225c354d16c..8641d690b2b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,6 +34,7 @@ if(CONFIG_APPS_DIR) include(nuttx_add_luamod) include(nuttx_add_wamrmod) include(nuttx_add_rust) + include(nuttx_wasm_interface) nuttx_add_library(apps) if(NOT EXISTS {NUTTX_APPS_BINDIR}/dummy.c) file(TOUCH ${NUTTX_APPS_BINDIR}/dummy.c) @@ -66,7 +67,6 @@ add_subdirectory(platform) add_subdirectory(sdr) add_subdirectory(system) add_subdirectory(testing) -add_subdirectory(tools) add_subdirectory(videoutils) add_subdirectory(wireless) @@ -76,6 +76,7 @@ if(EXISTS ${CMAKE_CURRENT_LIST_DIR}/external) add_subdirectory(external) endif() +add_subdirectory(tools) # after traversing all subdirectories add_subdirectory(builtin) # must be last nuttx_generate_kconfig() diff --git a/cmake/nuttx_wasm_interface.cmake b/cmake/nuttx_wasm_interface.cmake new file mode 100644 index 00000000000..4e746f7641f --- /dev/null +++ b/cmake/nuttx_wasm_interface.cmake @@ -0,0 +1,58 @@ +# ############################################################################## +# cmake/nuttx_wasm_interface.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. +# +# ############################################################################## + +# This is NuttX native wrapper for the WAMR interface. + +if(NOT TARGET wasm_interface) + add_custom_target(wasm_interface) +endif() + +# declare WAMS build directory and add INSTALL path +function(wasm_add_application) + + cmake_parse_arguments( + APP "" "NAME;STACK_SIZE;INITIAL_MEMORY_SIZE;WAMR_MODE;INSTALL_NAME" + "SRCS;WLDFLAGS;WCFLAGS;WINCLUDES" ${ARGN}) + + set_property( + TARGET wasm_interface + APPEND + PROPERTY WASM_DIR ${CMAKE_CURRENT_LIST_DIR}) + + if(APP_INSTALL_NAME) + add_custom_command( + OUTPUT ${CMAKE_BINARY_DIR}/wasm/${APP_INSTALL_NAME} + COMMAND ${CMAKE_COMMAND} -E touch_nocreate + ${CMAKE_BINARY_DIR}/wasm/${APP_INSTALL_NAME} + DEPENDS apps) + add_custom_target(wasm_gen_${APP_NAME} + DEPENDS ${CMAKE_BINARY_DIR}/wasm/${APP_INSTALL_NAME}) + add_dynamic_rcraws(RAWS ${CMAKE_BINARY_DIR}/wasm/${APP_INSTALL_NAME} + DEPENDS wasm_gen_${APP_NAME}) + endif() + +endfunction() + +function(wasm_add_library) + set_property( + TARGET wasm_interface + APPEND + PROPERTY WASM_DIR ${CMAKE_CURRENT_LIST_DIR}) +endfunction() diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 48204653a41..640b597e11b 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -20,17 +20,7 @@ # # ############################################################################## -# Fake wasm_add_application function to suppress error from native build process -function(wasm_add_application) - -endfunction() - -# Fake wasm_add_library function to suppress error from native build process -function(wasm_add_library) - -endfunction() - -if(CONFIG_TOOLS_WASM_BUILD) +if(CONFIG_TOOLS_WASM_BUILD OR CONFIG_INTERPRETERS_WAMR_BUILD_MODULES_FOR_NUTTX) include(ExternalProject) @@ -45,14 +35,22 @@ if(CONFIG_TOOLS_WASM_BUILD) # Get parent dir of CMAKE_CURRENT_SOURCE_DIR get_filename_component(APPDIR ${CMAKE_CURRENT_SOURCE_DIR} DIRECTORY) + # Get the Wasm build dirs from the wasm_interface target + get_property( + WASM_DIRS + TARGET wasm_interface + PROPERTY WASM_DIR) + + # ensure the Wasm build dirs are unique + list(REMOVE_DUPLICATES WASM_DIRS) # Configure and build the Wasm based application add_custom_target( configure_wasm_build COMMAND ${CMAKE_COMMAND} -B${CMAKE_BINARY_DIR}/Wasm ${CMAKE_CURRENT_SOURCE_DIR}/Wasm -DAPPDIR=${APPDIR} -DTOPDIR=${TOPDIR} - -DKCONFIG_FILE_PATH=${KCONFIG_FILE_PATH} - -DWASI_SDK_PATH=$ENV{WASI_SDK_PATH}) + -DTOPBINDIR=${CMAKE_BINARY_DIR} -DKCONFIG_FILE_PATH=${KCONFIG_FILE_PATH} + -DWASI_SDK_PATH=$ENV{WASI_SDK_PATH} -DWASM_DIRS="${WASM_DIRS}") add_custom_target(wasm_build COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR}/Wasm) diff --git a/tools/Wasm/CMakeLists.txt b/tools/Wasm/CMakeLists.txt index ca7fe114c75..9272c20c5e9 100644 --- a/tools/Wasm/CMakeLists.txt +++ b/tools/Wasm/CMakeLists.txt @@ -32,10 +32,24 @@ cmake_minimum_required(VERSION 3.5) +cmake_policy(SET CMP0079 NEW) + +# Include the NuttX kconfig parser to shared the configuration between the NuttX +# build and the Wasm build. And then parse the input KCONFIG_FILE_PATH to get +# the configuration. +include(${TOPDIR}/cmake/nuttx_kconfig.cmake) + +# Parse the input KCONFIG_FILE_PATH to get the configuration. +nuttx_export_kconfig(${KCONFIG_FILE_PATH}) + +# Include the WASI-SDK.cmake file to setup the necessary flags for building include(WASI-SDK.cmake) project(WasmApps) +# Add the wasm_interface library to hold all the Wasm libraries. +add_library(wasm_interface INTERFACE) + # Check whether the APPDIR is defined or not. If not, then set it to the parent # directory of the current CMakeLists.txt file. if(NOT DEFINED APPDIR) @@ -47,18 +61,21 @@ if(NOT DEFINED TOPDIR) message(FATAL_ERROR "TOPDIR is not defined") endif() +# Check wether the TOPBINDIR is defined or not. If not, then raise an error. +if(NOT DEFINED TOPBINDIR) + message(FATAL_ERROR "TOPBINDIR is not defined") +endif() + +if(NOT EXISTS ${TOPBINDIR}/wasm) + file(MAKE_DIRECTORY ${TOPBINDIR}/wasm) +endif() + # Check wether the KCONFIG_FILE_PATH is defined or not. If not, then raise an # error. if(NOT DEFINED KCONFIG_FILE_PATH) message(FATAL_ERROR "KCONFIG_FILE_PATH is not defined") endif() -# Include the NuttX kconfig parser to shared the configuration between the NuttX -# build and the Wasm build. And then parse the input KCONFIG_FILE_PATH to get -# the configuration. -include(${TOPDIR}/cmake/nuttx_kconfig.cmake) -nuttx_export_kconfig(${KCONFIG_FILE_PATH}) - # Provide FAR macro from command line since it is not supported in wasi-sdk, but # it is used in NuttX code. # ~~~ @@ -78,25 +95,13 @@ function(nuttx_add_library) endfunction() -# Recursively find all the CMakeLists.txt files in the ${APPDIR} and add it by -# add_subdirectory, but exclude the CMakeLists.txt file in the ${APPDIR}/tools -# directory. -file(GLOB_RECURSE WASM_APPS ${APPDIR}/*/CMakeLists.txt) -list(FILTER WASM_APPS EXCLUDE REGEX ".*/tools/.*") - -# Read and check if wasm_add_application is called in the CMakeLists.txt file in -# WASM_APPS If true, then add the directory to the build process -foreach(WASM_APP ${WASM_APPS}) - file(READ ${WASM_APP} WASM_APP_CONTENTS) - string(FIND "${WASM_APP_CONTENTS}" "wasm_add_application" WASM_APP_FOUND) - string(FIND "${WASM_APP_CONTENTS}" "wasm_add_library" WASM_LIB_FOUND) - if(WASM_APP_FOUND GREATER -1 OR WASM_LIB_FOUND GREATER -1) - get_filename_component(WASM_APP_DIR ${WASM_APP} DIRECTORY) - # Add subdirectory to the build process and put the build directory in the - # current build directory with the name same as the relative path of the - # ${APPDIR} - string(REPLACE ${APPDIR} "" WASM_APP_BUILD_DIR ${WASM_APP_DIR}) - add_subdirectory(${WASM_APP_DIR} - ${CMAKE_CURRENT_BINARY_DIR}/Wasm/${WASM_APP_BUILD_DIR}) - endif() +separate_arguments(WASM_DIRS) + +# ~~~ +# Add all the Wasm apps to the build process. +foreach(WASM_APP ${WASM_DIRS}) + string(REPLACE ${APPDIR} "" WASM_APP_BUILD_DIR ${WASM_APP}) + add_subdirectory(${WASM_APP} + ${CMAKE_CURRENT_BINARY_DIR}/Wasm/${WASM_APP_BUILD_DIR}) endforeach() +# ~~~ diff --git a/tools/Wasm/WASI-SDK.cmake b/tools/Wasm/WASI-SDK.cmake index 5f5309e3fa8..4785e0ec0e5 100644 --- a/tools/Wasm/WASI-SDK.cmake +++ b/tools/Wasm/WASI-SDK.cmake @@ -46,6 +46,44 @@ set(CMAKE_SYSTEM_PROCESSOR wasm32) set(CMAKE_C_COMPILER ${WASI_SDK_PATH}/bin/clang) set(CMAKE_CXX_COMPILER ${WASI_SDK_PATH}/bin/clang++) +# setup the flags for the compiler and linker + +include_directories(${TOPDIR}/include ${TOPBINDIR}/include) + +if(CONFIG_DEBUG_FULLOPT) + add_compile_options(-Oz) +elseif(CONFIG_DEBUG_CUSTOMOPT) + add_compile_options(${CONFIG_DEBUG_OPTLEVEL}) +endif() + +if(CONFIG_LTO_FULL OR CONFIG_LTO_THIN) + add_compile_options(-flto) + add_link_options(-flto) +endif() + +add_compile_options(--sysroot=${TOPDIR}) +add_compile_options(-nostdlib) +add_link_options(-nostdlib) +add_compile_options(-D__NuttX__) + +if(NOT CONFIG_LIBM) + add_compile_options(-DCONFIG_LIBM=1) + include_directories(${APPDIR}/include/wasm) +endif() + +add_link_options(-Wl,--export=main) +add_link_options(-Wl,--export=__main_argc_argv) +add_link_options(-Wl,--export=__heap_base) +add_link_options(-Wl,--export=__data_end) +add_link_options(-Wl,--no-entry) +add_link_options(-Wl,--strip-all) +add_link_options(-Wl,--allow-undefined) + +execute_process( + COMMAND ${CMAKE_C_COMPILER} --print-libgcc-file-name + OUTPUT_STRIP_TRAILING_WHITESPACE + OUTPUT_VARIABLE WCC_COMPILER_RT_LIB) + # ~~~ # Function "wasm_add_application" to add a WebAssembly application to the # build system. @@ -71,11 +109,17 @@ function(wasm_add_application) # Parse the APP_NAME and APP_SRCS from the arguments set(APP_NAME "") set(APP_SRCS "") - set(APP_STACK_SIZE 2048) - set(APP_INITIAL_MEMORY_SIZE 65536) + set(APP_STACK_SIZE "") + set(APP_INITIAL_MEMORY_SIZE "") + set(APP_INSTALL_NAME "") + set(APP_WAMR_MODE INT) + set(APP_WCFLAGS "") + set(APP_WLDFLAGS "") + set(APP_WINCLUDES "") - cmake_parse_arguments(APP "" "NAME;STACK_SIZE;INITIAL_MEMORY_SIZE" "SRCS" - ${ARGN}) + cmake_parse_arguments( + APP "" "NAME;STACK_SIZE;INITIAL_MEMORY_SIZE;WAMR_MODE;INSTALL_NAME" + "SRCS;WLDFLAGS;WCFLAGS;WINCLUDES" ${ARGN}) # Check if the APP_NAME (NAME) is provided if(NOT APP_NAME) @@ -87,12 +131,221 @@ function(wasm_add_application) message(FATAL_ERROR "SRCS is not provided.") endif() + if(NOT APP_STACK_SIZE) + set(APP_STACK_SIZE 2048) + endif() + + if(NOT APP_INITIAL_MEMORY_SIZE) + set(APP_INITIAL_MEMORY_SIZE 65536) + endif() + # Create the executable target for the application add_executable(${APP_NAME} ${APP_SRCS}) + target_link_libraries(${APP_NAME} PRIVATE wasm_interface) + target_include_directories(${APP_NAME} PRIVATE ${APP_WINCLUDES}) + target_compile_options(${APP_NAME} PRIVATE ${APP_WCFLAGS}) + target_link_options(${APP_NAME} PRIVATE -z stack-size=${APP_STACK_SIZE}) + target_link_options(${APP_NAME} PRIVATE + -Wl,--initial-memory=${APP_INITIAL_MEMORY_SIZE}) + target_link_options(${APP_NAME} PRIVATE ${APP_WLDFLAGS}) + + target_link_libraries(${APP_NAME} PRIVATE ${WCC_COMPILER_RT_LIB}) # Set the target properties set_target_properties(${APP_NAME} PROPERTIES OUTPUT_NAME ${APP_NAME}.wasm) + # do WASM OPTIMIZATION + add_custom_target( + ${APP_NAME}_OPT ALL + COMMAND ${WASI_SDK_PATH}/wasm-opt -Oz --enable-bulk-memory -o + ${APP_NAME}.wasm ${APP_NAME}.wasm + DEPENDS ${APP_NAME} + COMMENT "WASM build:Optimizing ${APP_NAME}") + + # armv7a + if(CONFIG_ARCH_ARMV7A) + if(CONFIG_ARCH_CORTEXA5) + set(LLVM_CPUTYPE cortex-a5) + elseif(CONFIG_ARCH_CORTEXA7) + set(LLVM_CPUTYPE cortex-a7) + elseif(CONFIG_ARCH_CORTEXA8) + set(LLVM_CPUTYPE cortex-a8) + elseif(CONFIG_ARCH_CORTEXA9) + set(LLVM_CPUTYPE cortex-a9) + endif() + if(CONFIG_ARM_THUMB) + set(LLVM_ARCHTYPE thumbv7) + else() + set(LLVM_ARCHTYPE armv7a) + endif() + if(CONFIG_ARCH_FPU) + set(LLVM_ABITYPE eabihf) + else() + set(LLVM_ABITYPE eabi) + endif() + endif() + + # armv7m + if(CONFIG_ARCH_ARMV7M) + if(CONFIG_ARCH_CORTEXM4) + set(LLVM_CPUTYPE cortex-m4) + elseif(CONFIG_ARCH_CORTEXM7) + set(LLVM_CPUTYPE cortex-m7) + else() + set(LLVM_CPUTYPE cortex-m3) + endif() + if(CONFIG_ARCH_CORTEXM3) + set(LLVM_ARCHTYPE thumbv7m) + else() + set(LLVM_ARCHTYPE thumbv7em) + endif() + if(CONFIG_ARCH_FPU) + set(LLVM_ABITYPE eabihf) + else() + set(LLVM_ABITYPE eabi) + endif() + endif() + + # armv8m + if(CONFIG_ARCH_ARMV8M) + if(CONFIG_ARM_DS) + set(EXTCPUFLAGS +dsp) + endif() + if(CONFIG_ARM_PACBTI) + set(EXTCPUFLAGS ${EXTCPUFLAGS}+pacbti) + endif() + if(CONFIG_ARM_HAVE_MVE) + set(EXTCPUFLAGS ${EXTCPUFLAGS}+mve.fp+fp.dp) + endif() + if(CONFIG_ARCH_CORTEXM23) + set(LLVM_CPUTYPE cortex-m23) + elseif(CONFIG_ARCH_CORTEXM33) + set(LLVM_CPUTYPE cortex-m33) + elseif(CONFIG_ARCH_CORTEXM35P) + set(LLVM_CPUTYPE cortex-m35p) + elseif(CONFIG_ARCH_CORTEXM55) + set(LLVM_CPUTYPE cortex-m55) + elseif(CONFIG_ARCH_CORTEXM85) + set(LLVM_CPUTYPE cortex-m85) + endif() + set(LLVM_ARCHTYPE thumbv8m.main${EXTCPUFLAGS}) + if(CONFIG_ARCH_FPU) + set(LLVM_ABITYPE eabihf) + else() + set(LLVM_ABITYPE eabi) + endif() + endif() + + # armv7r + if(CONFIG_ARCH_ARMV7R) + if(CONFIG_ARCH_CORTEXR4) + set(LLVM_CPUTYPE cortex-r4) + elseif(CONFIG_ARCH_CORTEXR5) + set(LLVM_CPUTYPE cortex-r5) + elseif(CONFIG_ARCH_CORTEXR7) + set(LLVM_CPUTYPE cortex-r7) + endif() + + if(CONFIG_ARM_THUMB) + set(LLVM_ARCHTYPE thumbv7r) + else() + set(LLVM_ARCHTYPE armv7r) + endif() + if(CONFIG_ARCH_FPU) + set(LLVM_ABITYPE eabihf) + else() + set(LLVM_ABITYPE eabi) + endif() + endif() + + # armv6m + if(CONFIG_ARCH_ARMV6M) + set(LLVM_CPUTYPE cortex-m0) + set(LLVM_ARCHTYPE thumbv6m) + set(LLVM_ABITYPE eabi) + endif() + + set(RCFLAGS) + set(WRC wamrc) + + if(CONFIG_ARCH_XTENSA) + set(WTARGET "xtensa") + elseif(CONFIG_ARCH_X86_64) + set(WTARGET "x86_64") + elseif(CONFIG_ARCH_X86) + set(WTARGET "i386") + elseif(CONFIG_ARCH_MIPS) + set(WTARGET "mips") + elseif(CONFIG_ARCH_SIM) + list(APPEND RCFLAGS --disable-simd) + if(CONFIG_SIM_M32) + set(WTARGET "i386") + else() + set(WTARGET "x86_64") + endif() + elseif(LLVM_ARCHTYPE MATCHES "thumb") + string(FIND "${LLVM_ARCHTYPE}" "+" PLUS_INDEX) + if(PLUS_INDEX EQUAL -1) + set(WTARGET "${LLVM_ARCHTYPE}") + else() + string(SUBSTRING "${LLVM_ARCHTYPE}" 0 ${PLUS_INDEX} WTARGET) + endif() + else() + set(WTARGET ${LLVM_ARCHTYPE}) + endif() + + set(WCPU ${LLVM_CPUTYPE}) + + if("${LLVM_ABITYPE}" STREQUAL "eabihf") + set(WABITYPE "gnueabihf") + else() + set(WABITYPE "${LLVM_ABITYPE}") + endif() + + list(APPEND RCFLAGS --target=${WTARGET}) + list(APPEND RCFLAGS --cpu=${WCPU}) + list(APPEND RCFLAGS --target-abi=${WABITYPE}) + + if(CONFIG_INTERPRETERS_WAMR_AOT) + if("${APP_WAMR_MODE}" STREQUAL "AOT") + # generate AoT + add_custom_target( + ${APP_NAME}_AOT ALL + COMMAND ${WRC} ${RCFLAGS} -o ${APP_NAME}.aot ${APP_NAME}.wasm + DEPENDS ${APP_NAME}_OPT + COMMENT "Wamrc Generate AoT: ${APP_NAME}.aot") + set(APP_INSTALL_BIN ${APP_NAME}.aot) + if(NOT APP_INSTALL_NAME) + set(APP_INSTALL_NAME ${APP_NAME}.aot) + endif() + elseif("${APP_WAMR_MODE}" STREQUAL "XIP") + # generate XIP + add_custom_target( + ${APP_NAME}_AOT ALL + COMMAND ${WRC} ${RCFLAGS} --enable-indirect-mode + --disable-llvm-intrinsics -o ${APP_NAME}.xip ${APP_NAME}.wasm + DEPENDS ${APP_NAME}_OPT + COMMENT "Wamrc Generate XIP: ${APP_NAME}.xip") + set(APP_INSTALL_BIN ${APP_NAME}.xip) + if(NOT APP_INSTALL_NAME) + set(APP_INSTALL_NAME ${APP_NAME}.xip) + endif() + endif() + endif() + + if(NOT APP_INSTALL_BIN) + set(APP_INSTALL_BIN ${APP_NAME}.wasm) + endif() + if(NOT APP_INSTALL_NAME) + set(APP_INSTALL_NAME ${APP_NAME}.wasm) + endif() + # install WASM BIN + add_custom_target( + ${APP_NAME}_INSTALL ALL + COMMAND ${CMAKE_COMMAND} -E copy ${APP_INSTALL_BIN} + ${TOPBINDIR}/wasm/${APP_INSTALL_NAME} + DEPENDS ${APP_NAME}_OPT + COMMENT "Install WASM BIN: ${APP_INSTALL_NAME}") endfunction() # ~~~ @@ -115,14 +368,23 @@ function(wasm_add_library) # Parse the LIB_NAME and LIB_SRCS from the arguments set(LIB_NAME "") set(LIB_SRCS "") + set(APP_WCFLAGS "") + set(APP_WINCLUDES "") - cmake_parse_arguments(LIB "" "NAME" "SRCS" ${ARGN}) + cmake_parse_arguments(LIB "" "NAME" "SRCS;WCFLAGS;WINCLUDES" ${ARGN}) # Check if the LIB_NAME (NAME) is provided if(NOT LIB_NAME) message(FATAL_ERROR "NAME is not provided.") endif() + # Check if the LIB_NAME (NAME) is already declared If it is, then skip the + # rest of the function + if(TARGET ${LIB_NAME}) + message(STATUS "Target ${LIB_NAME} already declared.") + return() + endif() + # Check if the LIB_SRCS (SRCS) is provided if(NOT LIB_SRCS) message(FATAL_ERROR "SRCS is not provided.") @@ -131,7 +393,12 @@ function(wasm_add_library) # Create the static library target for the library add_library(${LIB_NAME} STATIC ${LIB_SRCS}) + target_include_directories(${LIB_NAME} PRIVATE ${LIB_WINCLUDES}) + target_compile_options(${LIB_NAME} PRIVATE ${LIB_WCFLAGS}) + + add_dependencies(wasm_interface ${LIB_NAME}) + target_link_libraries(wasm_interface INTERFACE ${LIB_NAME}) # Set the target properties - set_target_properties(${LIB_NAME} PROPERTIES OUTPUT_NAME lib${LIB_NAME}.a) + set_target_properties(${LIB_NAME} PROPERTIES OUTPUT_NAME ${LIB_NAME}) endfunction()