From fb367c9792388a8bf3257115bd9b7f7c6bb83f23 Mon Sep 17 00:00:00 2001 From: xuxin19 Date: Tue, 26 Nov 2024 17:21:29 +0800 Subject: [PATCH] cmake(enhance):Enhanced full WASM library and application compilation 1.add complete compilation FLAGS for wasm toolchain 2.wasm build no longer traverses the native directory, saving build time 3.implement OPT and AOT process actions for wasm files 4.create a bridge interface for navtie build and wasm build Signed-off-by: xuxin19 --- CMakeLists.txt | 3 +- cmake/nuttx_wasm_interface.cmake | 58 +++++++ tools/CMakeLists.txt | 24 ++- tools/Wasm/CMakeLists.txt | 57 +++---- tools/Wasm/WASI-SDK.cmake | 269 ++++++++++++++++++++++++++++++- 5 files changed, 364 insertions(+), 47 deletions(-) create mode 100644 cmake/nuttx_wasm_interface.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 225c354d1..8641d690b 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 000000000..4e746f764 --- /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 48204653a..d53a81929 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 ca7fe114c..29c66a724 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,11 @@ 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() +# ~~~ +# 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 5f5309e3f..ca340d06e 100644 --- a/tools/Wasm/WASI-SDK.cmake +++ b/tools/Wasm/WASI-SDK.cmake @@ -46,6 +46,43 @@ 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_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 +108,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 +130,219 @@ 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_WLD_FLAGS}) + + 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() + else() + set(APP_INSTALL_BIN ${APP_NAME}.wasm) + if(NOT APP_INSTALL_NAME) + set(APP_INSTALL_NAME ${APP_NAME}.wasm) + endif() + 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,8 +365,10 @@ 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) @@ -131,7 +383,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()