tools: New CMake based Wasm build system

Introduce a new CMake based build system for Wasm.
And target the Wasm ABI to wasm32-wasi, it should
be a more commnly used and standard ABI for Wasm.

Signed-off-by: Huang Qi <huangqi3@xiaomi.com>
This commit is contained in:
Huang Qi 2024-03-07 12:37:18 +08:00 committed by Alan Carvalho de Assis
parent ec4d7a19f7
commit c138651300
12 changed files with 447 additions and 1 deletions

View File

@ -59,6 +59,7 @@ add_subdirectory(platform)
add_subdirectory(sdr)
add_subdirectory(system)
add_subdirectory(testing)
add_subdirectory(tools)
add_subdirectory(wireless)
# add examples and external at the end to allow library dependencies

View File

@ -64,6 +64,25 @@ $(INCDIR): $(TOPDIR)/tools/incdir.c
IMPORT_TOOLS = $(MKDEP) $(INCDIR)
ifeq ($(CONFIG_TOOLS_WASM_BUILD),y)
configure_wasm:
$(Q) cmake -B$(APPDIR)$(DELIM)tools$(DELIM)Wasm$(DELIM)build \
$(APPDIR)$(DELIM)tools$(DELIM)Wasm \
-DAPPDIR=$(APPDIR) -DTOPDIR=$(TOPDIR) \
-DWASI_SDK_PATH=$(WASI_SDK_PATH) \
-DKCONFIG_FILE_PATH=$(TOPDIR)$(DELIM).config
context_wasm: configure_wasm
$(Q) cmake --build $(APPDIR)$(DELIM)tools$(DELIM)Wasm$(DELIM)build
else
context_wasm:
endif
# In the KERNEL build, we must build and install all of the modules. No
# symbol table is needed
@ -155,6 +174,7 @@ staging:
context: | staging
$(Q) $(MAKE) context_all
$(Q) $(MAKE) register_all
$(Q) $(MAKE) context_wasm
Kconfig:
$(foreach SDIR, $(CONFIGDIRS), $(call MAKE_template,$(SDIR),preconfig))
@ -205,4 +225,5 @@ distclean: $(foreach SDIR, $(CLEANDIRS), $(SDIR)_distclean)
$(call DELDIR, $(BINDIR))
$(call DELDIR, staging)
$(call DELDIR, wasm)
$(call DELDIR, $(APPDIR)$(DELIM)tools$(DELIM)Wasm$(DELIM)build)
$(call CLEAN)

View File

@ -0,0 +1,36 @@
# ##############################################################################
# apps/examples/hello_wasm/CMakeLists.txt
#
# 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_EXAMPLES_HELLO_WASM_BUILD_NATIVE)
nuttx_add_application(
NAME
${CONFIG_EXAMPLES_HELLO_WASM_PROGNAME}
SRCS
hello_main.c
STACKSIZE
${CONFIG_EXAMPLES_HELLO_WASM_STACKSIZE}
PRIORITY
${CONFIG_EXAMPLES_HELLO_WASM_PRIORITY})
endif()
if(CONFIG_EXAMPLES_HELLO_WASM_BUILD_WASM)
wasm_add_application(NAME ${CONFIG_EXAMPLES_HELLO_WASM_PROGNAME} SRCS
hello_main.c)
endif()

View File

@ -26,4 +26,16 @@ config EXAMPLES_HELLO_WASM_STACKSIZE
int "Hello wasm stack size"
default DEFAULT_TASK_STACKSIZE
config EXAMPLES_HELLO_WASM_BUILD_WASM
bool "Build as WebAssembly module"
default y
---help---
Build the WebAssembly binary from the C source code.
config EXAMPLES_HELLO_WASM_BUILD_NATIVE
bool "Build as native program"
default n
---help---
Build the native binary from the C source code.
endif

View File

@ -22,7 +22,6 @@
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdio.h>
/****************************************************************************

65
tools/CMakeLists.txt Normal file
View File

@ -0,0 +1,65 @@
# ##############################################################################
# apps/tools/CMakeLists.txt
#
# 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.
#
# ##############################################################################
# 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)
include(ExternalProject)
set(TOPDIR
${CMAKE_SOURCE_DIR}
CACHE INTERNAL "")
set(KCONFIG_FILE_PATH
${CMAKE_BINARY_DIR}/.config
CACHE INTERNAL "")
# Get parent dir of CMAKE_CURRENT_SOURCE_DIR
get_filename_component(APPDIR ${CMAKE_CURRENT_SOURCE_DIR} DIRECTORY)
# 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})
add_custom_target(wasm_build COMMAND ${CMAKE_COMMAND} --build
${CMAKE_BINARY_DIR}/Wasm)
add_dependencies(wasm_build configure_wasm_build)
# Add the Wasm based application to the build. Notice: Wasm build will be
# triggered by the native build process each time, but it's ok since the
# incremental build is very fast in CMake.
add_dependencies(apps wasm_build)
endif()

20
tools/Kconfig Normal file
View File

@ -0,0 +1,20 @@
#
# For a description of the syntax of this configuration file,
# see the file kconfig-language.txt in the NuttX tools repository.
#
menu "Extra Tools"
menu "Wasm Build Options"
config TOOLS_WASM_BUILD
bool "Enable Wasm build support"
default n
---help---
If enabled, then then build system will trigger the Wasm build
process. This will require the WASI-SDK to be installed on the
host system.
endmenu
endmenu

1
tools/Wasm/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
build

100
tools/Wasm/CMakeLists.txt Normal file
View File

@ -0,0 +1,100 @@
# ##############################################################################
# apps/tools/Wasm/CMakeLists.txt
#
# 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 file is used to manage the WebAssembly (Wasm) build process as entry
# point. All the wasm apps are built using this file as a sub target.
#
# Necessary input for this file is the APPDIR, TOPDIR and KCONFIG_FILE_PATH.
# The APPDIR is the directory where the Wasm apps are located.
# The TOPDIR is the root directory of the NuttX source code.
# The KCONFIG_FILE_PATH is the path to the .config file of the NuttX build.
# ~~~
cmake_minimum_required(VERSION 3.5)
include(WASI-SDK.cmake)
project(WasmApps)
# 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)
message(FATAL_ERROR "APPDIR is not defined")
endif()
# Check wether the TOPDIR is defined or not. If not, then raise an error.
if(NOT DEFINED TOPDIR)
message(FATAL_ERROR "TOPDIR is not defined")
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.
# ~~~
# #define FAR
# ~~~
# It usually defined in nuttx/compiler.h.
set(NUTTX_MACRO_FAR "")
add_definitions(-DFAR=${NUTTX_MACRO_FAR})
# Fake nuttx_add_application to avoid error in the Wasm build process.
function(nuttx_add_application)
endfunction()
# Fake nuttx_add_library to avoid error in the Wasm build process.
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()
endforeach()

4
tools/Wasm/Kconfig Normal file
View File

@ -0,0 +1,4 @@
#
# For a description of the syntax of this configuration file,
# see the file kconfig-language.txt in the NuttX tools repository.
#

52
tools/Wasm/README.md Normal file
View File

@ -0,0 +1,52 @@
# Wasm build system in NuttX
## Overview
The files in this directory are used to build the Wasm module in NuttX:
* CMakeLists.txt - The project configuration file for all Wasm targets
* WASI-SDK.cmake - Provides the toolchain definition and utility functions for the Wasm build
Since the Wasm module is built with dedicated toolchain and flags, the main NuttX build system will treat the Wasm module as an external project, but share the same source tree and configuration (.config file).
## Design goals
* **Consistency**: The Wasm module can be built with the same build system as NuttX, and share the same source tree and configuration.
* **Flexibility**: Can be built with CMake or Makefile, and can be integrated into the NuttX build system easily (until Makefile based build system is deprecated)
* **Maintainability**: The Wasm module build system should be simple and less dependent on the NuttX build system.
* **Portability**: The Wasm module can be built on any platform with CMake and WASI-SDK installed.
## Build process
Each Wasm target (such as examples/hello_wasm) will have its own CMakeLists.txt file, which will be included in the main CMakeLists.txt file in this directory.
Each target will have its own build directory (Wasm) inside the NuttX build directory, such as:
```
* apps
* nuttx
* cmake_build_dir
* other NuttX native targets
* Wasm
* examples
* hello_wasm
* hello_wasm.wasm
* other build files
* benchmarks
* coremark
* coremark.wasm
* netutils
* cjson
* libcJSON.a
* libWasm.a
* other build files
```
Each target can be built with private source files, or shared source files with other targets. The shared source files will be built into a static global library (libWasm.a) or a custom library and linked to the Wasm targets.
Each target will be visible to other targets, so that the module level CMakelists.txt can define the dependencies between targets.
## Limitations
Now the Wasm module is targeted to wasm32-wasi, instead of legacy custom build with NuttX sysroot.
So the source files should not call any NuttX APIs directly, and should not include any NuttX header files.
It will limit the usage that some applications inside apps directory can not be built as Wasm targets directly.But still
can be used for many POSIX compatible applications.

135
tools/Wasm/WASI-SDK.cmake Normal file
View File

@ -0,0 +1,135 @@
# ##############################################################################
# apps/tools/Wasm/WASI-SDK.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 file is to used for finding the WASI SDK and setting up the necessary
# flags for building WebAssembly applications with CMake or Makefile in NuttX
# build system.
#
# This file is intended to be included in the top-level CMakeLists.txt file of
# the application.
#
# For legacy Makefile-based build system, CMake will be called in the Makefile
# to do actual build.
# If no WASI_SDK_PATH is provided, the raise an error and stop the build
if(NOT DEFINED WASI_SDK_PATH)
message(FATAL_ERROR "WASI_SDK_PATH is not defined."
"Please set it to the path of the WASI SDK.")
endif()
# Set the system name, version and processor to WASI These are from original
# WASI SDK's cmake toolchain file
set(CMAKE_SYSTEM_NAME WASI)
set(CMAKE_SYSTEM_VERSION 1)
set(CMAKE_SYSTEM_PROCESSOR wasm32)
# Fetch the wasm compiler and linker from the WASI SDK
set(CMAKE_C_COMPILER ${WASI_SDK_PATH}/bin/clang)
set(CMAKE_CXX_COMPILER ${WASI_SDK_PATH}/bin/clang++)
# ~~~
# Function "wasm_add_application" to add a WebAssembly application to the
# build system.
#
# This function is used to add a WebAssembly application to the build system.
# It creates an executable target for the application and sets the necessary
# properties for building the application.
#
# Usage:
# wasm_add_application(NAME <name> SRCS <source files>
# [STACK_SIZE <stack size>] [INITIAL_MEMORY_SIZE <initial memory size>])
#
# Parameters:
# NAME: The name of the application (NAME.wasm).
# SRCS: The source files of the application.
# STACK_SIZE: The stack size of the application. Default is 2048.
# INITIAL_MEMORY_SIZE: The initial memory size of the application.
# Default is 65536 (One page), and must be a multiple of 65536.
# ~~~
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)
cmake_parse_arguments(APP "" "NAME;STACK_SIZE;INITIAL_MEMORY_SIZE" "SRCS"
${ARGN})
# Check if the APP_NAME (NAME) is provided
if(NOT APP_NAME)
message(FATAL_ERROR "NAME is not provided.")
endif()
# Check if the APP_SRCS (SRCS) is provided
if(NOT APP_SRCS)
message(FATAL_ERROR "SRCS is not provided.")
endif()
# Create the executable target for the application
add_executable(${APP_NAME} ${APP_SRCS})
# Set the target properties
set_target_properties(${APP_NAME} PROPERTIES OUTPUT_NAME ${APP_NAME}.wasm)
endfunction()
# ~~~
# Function "wasm_add_library" to add a WebAssembly library to the build system.
#
# This function is used to add a WebAssembly library to the build system.
# It creates a static library target for the library and sets the necessary
# properties for building the library.
#
# Usage:
# wasm_add_library(NAME <name> SRCS <source files>)
#
# Parameters:
# NAME: The name of the library (libNAME.a).
# SRCS: The source files of the library.
# ~~~
function(wasm_add_library)
# Parse the LIB_NAME and LIB_SRCS from the arguments
set(LIB_NAME "")
set(LIB_SRCS "")
cmake_parse_arguments(LIB "" "NAME" "SRCS" ${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_SRCS (SRCS) is provided
if(NOT LIB_SRCS)
message(FATAL_ERROR "SRCS is not provided.")
endif()
# Create the static library target for the library
add_library(${LIB_NAME} STATIC ${LIB_SRCS})
# Set the target properties
set_target_properties(${LIB_NAME} PROPERTIES OUTPUT_NAME lib${LIB_NAME}.a)
endfunction()