852 lines
28 KiB
CMake
852 lines
28 KiB
CMake
# ##############################################################################
|
|
# 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.
|
|
#
|
|
# ##############################################################################
|
|
|
|
# ~~~
|
|
# Instructions:
|
|
# - Run CMake from the user project directory:
|
|
# cmake -S <nuttx-dir> -B <build-directory> -DBOARD_CONFIG=<board>
|
|
# - NuttX will look for the nuttx-apps repository from its parent folder
|
|
# i.e., ../nuttx-apps.
|
|
# - A custom directory can be specified with -DNUTTX_APPS_DIR=<apps-dir>.
|
|
# - Build the user project with:
|
|
# cmake --build <build-dir>
|
|
# ~~~
|
|
|
|
# Request a version available on latest Ubuntu LTS (20.04)
|
|
|
|
cmake_minimum_required(VERSION 3.16)
|
|
|
|
# Handle newer CMake versions correctly by setting policies
|
|
|
|
if(POLICY CMP0115)
|
|
# do not auto-guess extension in target_sources()
|
|
cmake_policy(SET CMP0115 NEW)
|
|
endif()
|
|
|
|
# Avoid warning about DOWNLOAD_EXTRACT_TIMESTAMP in CMake 3.24:
|
|
|
|
if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.24.0")
|
|
cmake_policy(SET CMP0135 NEW)
|
|
endif()
|
|
|
|
if(POLICY CMP0169)
|
|
# allow to call FetchContent_Populate directly
|
|
cmake_policy(SET CMP0169 OLD)
|
|
endif()
|
|
|
|
# Basic CMake configuration ##################################################
|
|
|
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
|
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
|
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
|
|
|
# Setup build type (Debug Release RelWithDebInfo MinSizeRel Coverage). Default
|
|
# to minimum size release
|
|
|
|
# Use nuttx optimization configuration options, workaround for cmake build type
|
|
# TODO Integration the build type with CMAKE
|
|
|
|
# if (NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE "MinSizeRel" CACHE STRING
|
|
# "Build type" FORCE) endif() set_property(CACHE CMAKE_BUILD_TYPE PROPERTY
|
|
# STRINGS "Debug;Release;RelWithDebInfo;MinSizeRel")
|
|
|
|
# Process board config & directory locations #################################
|
|
|
|
set(NUTTX_DIR ${CMAKE_CURRENT_SOURCE_DIR})
|
|
|
|
# unceaned previous make build can cause various types of cmake error
|
|
if(EXISTS "${NUTTX_DIR}/.config")
|
|
message(
|
|
FATAL_ERROR "Please distclean previous make build with `make distclean`")
|
|
endif()
|
|
|
|
if(NOT DEFINED BOARD_CONFIG)
|
|
message(FATAL_ERROR "Please define configuration with BOARD_CONFIG")
|
|
endif()
|
|
|
|
find_program(KCONFIGLIB olddefconfig)
|
|
if(NOT KCONFIGLIB)
|
|
message(
|
|
FATAL_ERROR "Kconfig environment depends on kconfiglib, Please install:
|
|
$ pip install kconfiglib")
|
|
endif()
|
|
|
|
# BOARD CONFIG can be set to directory path, or <board-name>[/:]<config-name>
|
|
# configuration pair
|
|
|
|
if((EXISTS ${BOARD_CONFIG} AND EXISTS ${BOARD_CONFIG}/defconfig)
|
|
OR (EXISTS ${NUTTX_DIR}/${BOARD_CONFIG}
|
|
AND EXISTS ${NUTTX_DIR}/${BOARD_CONFIG}/defconfig))
|
|
get_filename_component(NUTTX_BOARD_ABS_DIR ${BOARD_CONFIG} ABSOLUTE BASE_DIR
|
|
${NUTTX_DIR})
|
|
|
|
string(REPLACE "/" ";" CONFIG_ARRAY ${NUTTX_BOARD_ABS_DIR})
|
|
|
|
list(LENGTH CONFIG_ARRAY CONFIG_ARRAY_LENGTH)
|
|
|
|
if(${CONFIG_ARRAY_LENGTH} LESS 4)
|
|
message(FATAL_ERROR "Please define correct board config : ${BOARD_CONFIG}")
|
|
endif()
|
|
|
|
math(EXPR NUTTX_CONFIG_INDEX "${CONFIG_ARRAY_LENGTH} - 1")
|
|
math(EXPR NUTTX_BOARD_INDEX "${CONFIG_ARRAY_LENGTH} - 3")
|
|
list(GET CONFIG_ARRAY ${NUTTX_BOARD_INDEX} NUTTX_BOARD)
|
|
list(GET CONFIG_ARRAY ${NUTTX_CONFIG_INDEX} NUTTX_CONFIG)
|
|
|
|
string(REGEX REPLACE "(.*)/(.*)/${NUTTX_CONFIG}" "\\1" NUTTX_BOARD_DIR
|
|
${NUTTX_BOARD_ABS_DIR})
|
|
set(NUTTX_DEFCONFIG ${NUTTX_BOARD_ABS_DIR}/defconfig)
|
|
else()
|
|
if(BOARD_CONFIG MATCHES "/")
|
|
set(MATCH_REGEX "/")
|
|
else()
|
|
set(MATCH_REGEX ":")
|
|
endif()
|
|
|
|
string(REPLACE ${MATCH_REGEX} ";" CONFIG_ARRAY ${BOARD_CONFIG})
|
|
|
|
list(LENGTH CONFIG_ARRAY CONFIG_ARRAY_LENGTH)
|
|
|
|
if(${CONFIG_ARRAY_LENGTH} LESS 2)
|
|
message(FATAL_ERROR "Please define correct board config : ${BOARD_CONFIG}")
|
|
endif()
|
|
|
|
list(GET CONFIG_ARRAY 0 NUTTX_BOARD)
|
|
list(GET CONFIG_ARRAY 1 NUTTX_CONFIG)
|
|
|
|
file(
|
|
GLOB NUTTX_BOARD_DIR
|
|
LIST_DIRECTORIES true
|
|
"${NUTTX_DIR}/boards/*/*/${NUTTX_BOARD}")
|
|
|
|
if(EXISTS ${NUTTX_BOARD_DIR}/configs/${NUTTX_CONFIG}/defconfig)
|
|
set(NUTTX_DEFCONFIG ${NUTTX_BOARD_DIR}/configs/${NUTTX_CONFIG}/defconfig)
|
|
endif()
|
|
endif()
|
|
|
|
if("${NUTTX_CONFIG}" STREQUAL "")
|
|
message(FATAL_ERROR "Please define correct board config : ${NUTTX_CONFIG}")
|
|
endif()
|
|
|
|
if(NOT EXISTS "${NUTTX_DEFCONFIG}")
|
|
message(FATAL_ERROR "No config file found at ${NUTTX_DEFCONFIG}")
|
|
endif()
|
|
|
|
# Generate inital .config ###################################################
|
|
# This is needed right before any other configure step so that we can source
|
|
# Kconfig variables into CMake variables
|
|
|
|
# The following commands need these variables to be passed via environment
|
|
|
|
include(nuttx_kconfig)
|
|
nuttx_export_kconfig_by_value(${NUTTX_DEFCONFIG} "CONFIG_APPS_DIR")
|
|
|
|
if((NOT NUTTX_APPS_DIR) AND (NOT CONFIG_APPS_DIR))
|
|
if(EXISTS "${NUTTX_DIR}/../apps")
|
|
set(NUTTX_APPS_DIR "${NUTTX_DIR}/../apps")
|
|
elseif(EXISTS "${NUTTX_DIR}/../nuttx-apps")
|
|
set(NUTTX_APPS_DIR "${NUTTX_DIR}/../nuttx-apps")
|
|
else()
|
|
message(
|
|
WARNING
|
|
"apps/nuttx-apps directory is not found, use dummy directory instead")
|
|
set(NUTTX_APPS_DIR "${NUTTX_DIR}/dummy")
|
|
endif()
|
|
else()
|
|
set(NUTTX_APPS_DIR ${CONFIG_APPS_DIR})
|
|
set(CONFIG_APPS_DIR)
|
|
endif()
|
|
|
|
if(NOT EXISTS "${NUTTX_APPS_DIR}")
|
|
message(FATAL_ERROR "Application directory ${NUTTX_APPS_DIR} is not found")
|
|
endif()
|
|
|
|
get_filename_component(NUTTX_APPS_DIR ${NUTTX_APPS_DIR} ABSOLUTE)
|
|
get_filename_component(apps_dir ${NUTTX_APPS_DIR} NAME)
|
|
set(NUTTX_APPS_BINDIR "${CMAKE_BINARY_DIR}/${apps_dir}")
|
|
|
|
# Support not having application directory
|
|
|
|
if("${apps_dir}" STREQUAL "dummy")
|
|
file(MAKE_DIRECTORY ${NUTTX_APPS_BINDIR})
|
|
file(TOUCH ${NUTTX_APPS_BINDIR}/Kconfig)
|
|
endif()
|
|
|
|
set(ENV{PYTHONPYCACHEPREFIX} ${CMAKE_BINARY_DIR})
|
|
set(ENV{APPSDIR} ${NUTTX_APPS_DIR}) # TODO: support not having apps/
|
|
set(ENV{APPSBINDIR} ${NUTTX_APPS_BINDIR}) # TODO: support not having apps/
|
|
set(ENV{BINDIR} ${CMAKE_BINARY_DIR}) # TODO: support not having apps/
|
|
set(ENV{EXTERNALDIR} dummy) # TODO
|
|
set(ENV{DRIVERS_PLATFORM_DIR} dummy) # TODO
|
|
|
|
set(ENV{HOST_LINUX} n)
|
|
set(ENV{HOST_MACOS} n)
|
|
set(ENV{HOST_WINDOWS} n)
|
|
set(ENV{HOST_OTHER} n)
|
|
|
|
if(APPLE)
|
|
set(ENV{HOST_MACOS} y)
|
|
elseif(WIN32)
|
|
set(ENV{HOST_WINDOWS} y)
|
|
elseif(UNIX)
|
|
set(ENV{HOST_LINUX} y)
|
|
set(LINUX TRUE)
|
|
else()
|
|
set(ENV{HOST_OTHER} y)
|
|
set(OTHER_OS TRUE)
|
|
endif()
|
|
|
|
include(nuttx_parse_function_args)
|
|
include(nuttx_add_subdirectory)
|
|
include(nuttx_create_symlink)
|
|
|
|
# Add apps/ to the build (if present)
|
|
|
|
if(NOT EXISTS ${NUTTX_APPS_BINDIR}/Kconfig)
|
|
add_subdirectory(${NUTTX_APPS_DIR} preapps)
|
|
endif()
|
|
|
|
nuttx_export_kconfig(${NUTTX_DEFCONFIG})
|
|
|
|
if(CONFIG_ARCH_BOARD_CUSTOM)
|
|
get_filename_component(NUTTX_BOARD_DIR ${CONFIG_ARCH_BOARD_CUSTOM_DIR}
|
|
ABSOLUTE BASE_DIR ${NUTTX_DIR})
|
|
endif()
|
|
|
|
if("${NUTTX_BOARD_DIR}" STREQUAL "")
|
|
message(FATAL_ERROR "Please define correct board : ${NUTTX_BOARD_DIR}")
|
|
endif()
|
|
|
|
if(NOT EXISTS "${NUTTX_BOARD_DIR}/CMakeLists.txt"
|
|
AND NOT EXISTS "${NUTTX_BOARD_DIR}/../common/CMakeLists.txt")
|
|
message(FATAL_ERROR "No CMakeLists.txt found at ${NUTTX_BOARD_DIR}")
|
|
endif()
|
|
|
|
# Custom board ###################################################
|
|
|
|
file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/boards/dummy)
|
|
if(CONFIG_ARCH_BOARD_CUSTOM)
|
|
get_filename_component(NUTTX_BOARD_ABS_DIR ${CONFIG_ARCH_BOARD_CUSTOM_DIR}
|
|
ABSOLUTE BASE_DIR ${NUTTX_DIR})
|
|
else()
|
|
set(NUTTX_BOARD_ABS_DIR ${NUTTX_BOARD_DIR})
|
|
file(TOUCH ${CMAKE_BINARY_DIR}/boards/dummy/Kconfig)
|
|
endif()
|
|
|
|
if(NOT EXISTS ${CMAKE_BINARY_DIR}/boards/dummy/Kconfig)
|
|
if(CONFIG_ARCH_BOARD_CUSTOM AND EXISTS ${NUTTX_BOARD_ABS_DIR}/Kconfig)
|
|
nuttx_create_symlink(${NUTTX_BOARD_ABS_DIR}/Kconfig
|
|
${CMAKE_BINARY_DIR}/boards/dummy/Kconfig)
|
|
else()
|
|
file(TOUCH ${CMAKE_BINARY_DIR}/boards/dummy/Kconfig)
|
|
endif()
|
|
endif()
|
|
|
|
# board platfrom driver
|
|
|
|
file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/drivers)
|
|
|
|
if(EXISTS ${NUTTX_BOARD_ABS_DIR}/../drivers
|
|
AND EXISTS ${NUTTX_BOARD_ABS_DIR}/../drivers/Kconfig)
|
|
nuttx_create_symlink(${NUTTX_BOARD_ABS_DIR}/../drivers
|
|
${CMAKE_BINARY_DIR}/drivers/platform)
|
|
else()
|
|
file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/drivers/platform)
|
|
file(TOUCH ${CMAKE_BINARY_DIR}/drivers/platform/Kconfig)
|
|
endif()
|
|
|
|
# Custom chip ###################################################
|
|
|
|
if(CONFIG_ARCH_CHIP_CUSTOM)
|
|
get_filename_component(NUTTX_CHIP_ABS_DIR ${CONFIG_ARCH_CHIP_CUSTOM_DIR}
|
|
ABSOLUTE BASE_DIR ${NUTTX_DIR})
|
|
set(NUTTX_CHIP_ABS_DIR ${NUTTX_CHIP_ABS_DIR})
|
|
else()
|
|
set(NUTTX_CHIP_ABS_DIR
|
|
"${NUTTX_DIR}/arch/${CONFIG_ARCH}/src/${CONFIG_ARCH_CHIP}")
|
|
endif()
|
|
|
|
if(NOT EXISTS ${CMAKE_BINARY_DIR}/arch/dummy)
|
|
file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/arch/dummy)
|
|
endif()
|
|
|
|
if(NOT EXISTS ${CMAKE_BINARY_DIR}/arch/dummy/Kconfig)
|
|
if(CONFIG_ARCH_CHIP_CUSTOM AND EXISTS ${NUTTX_CHIP_ABS_DIR}/Kconfig)
|
|
nuttx_create_symlink(${NUTTX_CHIP_ABS_DIR}/Kconfig
|
|
${CMAKE_BINARY_DIR}/arch/dummy/Kconfig)
|
|
else()
|
|
file(TOUCH ${CMAKE_BINARY_DIR}/arch/dummy/Kconfig)
|
|
endif()
|
|
endif()
|
|
|
|
if(NOT EXISTS ${CMAKE_BINARY_DIR}/arch/${CONFIG_ARCH})
|
|
file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/arch/${CONFIG_ARCH})
|
|
file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/arch/${CONFIG_ARCH}/src)
|
|
endif()
|
|
|
|
if(NOT EXISTS ${CMAKE_BINARY_DIR}/arch/${CONFIG_ARCH}/src/chip)
|
|
nuttx_create_symlink(${NUTTX_CHIP_ABS_DIR}
|
|
${CMAKE_BINARY_DIR}/arch/${CONFIG_ARCH}/src/chip)
|
|
endif()
|
|
|
|
# Unsupport custom board/chips yet, workaround
|
|
|
|
if(NOT EXISTS ${NUTTX_APPS_BINDIR}/platform/board/Kconfig)
|
|
file(MAKE_DIRECTORY ${NUTTX_APPS_BINDIR}/platform/board)
|
|
file(TOUCH ${NUTTX_APPS_BINDIR}/platform/board/Kconfig)
|
|
endif()
|
|
|
|
# Copy board defconfig into main directory and expand TODO: do also for changes
|
|
# in board/config (by comparing stored defconfig to specified one)
|
|
|
|
if(NOT EXISTS ${CMAKE_BINARY_DIR}/.config OR NOT "${NUTTX_DEFCONFIG}" STREQUAL
|
|
"${NUTTX_DEFCONFIG_SAVED}")
|
|
|
|
message(STATUS "Initializing NuttX")
|
|
configure_file(${NUTTX_DEFCONFIG} defconfig COPYONLY)
|
|
configure_file(${NUTTX_DEFCONFIG} .config.compressed COPYONLY)
|
|
|
|
set(ENV{KCONFIG_CONFIG} ${CMAKE_BINARY_DIR}/.config.compressed)
|
|
|
|
# Do olddefconfig step to expand the abbreviated defconfig into normal config
|
|
execute_process(
|
|
COMMAND olddefconfig
|
|
ERROR_VARIABLE KCONFIG_ERROR
|
|
OUTPUT_VARIABLE KCONFIG_OUTPUT
|
|
RESULT_VARIABLE KCONFIG_STATUS
|
|
WORKING_DIRECTORY ${NUTTX_DIR})
|
|
|
|
file(RENAME ${CMAKE_BINARY_DIR}/.config.compressed
|
|
${CMAKE_BINARY_DIR}/.config)
|
|
set(ENV{KCONFIG_CONFIG} ${CMAKE_BINARY_DIR}/.config)
|
|
|
|
# store original expanded .config
|
|
configure_file(${CMAKE_BINARY_DIR}/.config ${CMAKE_BINARY_DIR}/.config.orig
|
|
COPYONLY)
|
|
|
|
string(REPLACE "\n" ";" KCONFIG_ESTRING ${KCONFIG_ERROR})
|
|
foreach(estring ${KCONFIG_ESTRING})
|
|
string(REGEX MATCH "the 'modules' option is not supported" result
|
|
${estring})
|
|
if(NOT result)
|
|
message(WARNING "Kconfig Configuration Error: ${estring}")
|
|
endif()
|
|
endforeach()
|
|
|
|
if(KCONFIG_STATUS AND NOT KCONFIG_STATUS EQUAL 0)
|
|
message(
|
|
FATAL_ERROR
|
|
"Failed to initialize Kconfig configuration: ${KCONFIG_OUTPUT}")
|
|
endif()
|
|
|
|
set(NUTTX_DEFCONFIG_SAVED
|
|
${NUTTX_DEFCONFIG}
|
|
CACHE INTERNAL "Saved defconfig path" FORCE)
|
|
|
|
# Print configuration choices
|
|
|
|
message(STATUS " Board: ${NUTTX_BOARD}")
|
|
message(STATUS " Config: ${NUTTX_CONFIG}")
|
|
message(STATUS " Appdir: ${NUTTX_APPS_DIR}")
|
|
endif()
|
|
|
|
# Include .cmake files #######################################################
|
|
|
|
# this exposes all Kconfig vars to CMake
|
|
|
|
nuttx_export_kconfig(${CMAKE_BINARY_DIR}/.config)
|
|
|
|
include(nuttx_generate_headers)
|
|
include(nuttx_generate_outputs)
|
|
include(nuttx_add_library)
|
|
include(nuttx_add_application)
|
|
include(nuttx_add_romfs)
|
|
include(nuttx_add_symtab)
|
|
include(nuttx_add_module)
|
|
include(nuttx_add_dependencies)
|
|
include(nuttx_export_header)
|
|
include(nuttx_source_file_properties)
|
|
include(menuconfig)
|
|
|
|
include(ExternalProject)
|
|
include(FetchContent)
|
|
|
|
set(FETCHCONTENT_QUIET OFF)
|
|
|
|
# Board common directory #####################################################
|
|
|
|
if(CONFIG_ARCH_BOARD_COMMON)
|
|
file(
|
|
GLOB NUTTX_COMMON_DIR
|
|
LIST_DIRECTORIES true
|
|
"${NUTTX_DIR}/boards/${CONFIG_ARCH}/${CONFIG_ARCH_CHIP}/common")
|
|
endif()
|
|
|
|
# Setup toolchain ############################################################
|
|
|
|
# This needs to happen before project() when binaries are searched for
|
|
|
|
list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/arch/${CONFIG_ARCH}/src/cmake)
|
|
set(CMAKE_TOOLCHAIN_FILE
|
|
"${CMAKE_SOURCE_DIR}/arch/${CONFIG_ARCH}/src/cmake/Toolchain.cmake")
|
|
|
|
# Define project #############################################################
|
|
# This triggers configuration
|
|
|
|
project(NuttX LANGUAGES C CXX ASM)
|
|
if(WIN32)
|
|
enable_language(ASM_MASM)
|
|
endif()
|
|
|
|
# Setup platform options (this needs to happen after project(), once the
|
|
# toolchain file has been processed)
|
|
|
|
include(platform)
|
|
|
|
# Setup main nuttx target ####################################################
|
|
|
|
add_executable(nuttx)
|
|
if(CONFIG_BUILD_PROTECTED)
|
|
add_executable(nuttx_user)
|
|
endif()
|
|
|
|
if(CONFIG_ALLSYMS)
|
|
include(nuttx_allsyms)
|
|
endif()
|
|
|
|
add_dependencies(nuttx nuttx_context)
|
|
|
|
if(WIN32)
|
|
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT
|
|
nuttx)
|
|
endif()
|
|
|
|
if(CONFIG_ARCH_SIM)
|
|
# Create separate sim_head OBJECT library built as part of NuttX kernel It
|
|
# must be separated to allow for linking against the rest of NuttX libraries
|
|
|
|
add_library(sim_head OBJECT)
|
|
nuttx_add_library_internal(sim_head)
|
|
get_property(
|
|
definitions
|
|
TARGET nuttx
|
|
PROPERTY NUTTX_KERNEL_DEFINITIONS)
|
|
target_compile_definitions(sim_head PRIVATE ${definitions})
|
|
|
|
get_property(
|
|
options
|
|
TARGET nuttx
|
|
PROPERTY NUTTX_KERNEL_COMPILE_OPTIONS)
|
|
target_compile_options(sim_head PRIVATE ${options})
|
|
target_compile_options(sim_head PRIVATE -fvisibility=default)
|
|
|
|
# We need the relocatable object to be first in the list of libraries to be
|
|
# linked against final nuttx binary
|
|
|
|
if(NOT WIN32)
|
|
target_link_libraries(nuttx PRIVATE ${CMAKE_BINARY_DIR}/nuttx.rel)
|
|
endif()
|
|
else()
|
|
# These flags apply to source files not part of the library. In sim build this
|
|
# corresponds to "host" files, so we only do this on non-sim build
|
|
target_compile_definitions(
|
|
nuttx
|
|
PRIVATE $<GENEX_EVAL:$<TARGET_PROPERTY:nuttx,NUTTX_COMPILE_DEFINITIONS>>)
|
|
target_compile_options(
|
|
nuttx PRIVATE $<GENEX_EVAL:$<TARGET_PROPERTY:nuttx,NUTTX_COMPILE_OPTIONS>>)
|
|
endif()
|
|
|
|
# Compiler options TODO: move elsewhere
|
|
|
|
if("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU")
|
|
if(CMAKE_C_COMPILER_VERSION VERSION_GREATER 4.9)
|
|
# force color for gcc > 4.9
|
|
add_compile_options(-fdiagnostics-color=always)
|
|
endif()
|
|
endif()
|
|
|
|
if(WIN32)
|
|
add_compile_options(
|
|
-W2
|
|
-wd4116 # unnamed type definition in parentheses
|
|
-wd4146 # unary minus operator applied to unsigned type, result still
|
|
# unsigned
|
|
-wd4244 # 'argument' : conversion from 'type1' to 'type2', possible loss of
|
|
# data
|
|
-wd4305 # 'context' : truncation from 'type1' to 'type2'
|
|
)
|
|
else()
|
|
add_compile_options(
|
|
# system wide warnings
|
|
-Wall $<$<COMPILE_LANGUAGE:C>:-Wstrict-prototypes> -Wshadow -Wundef
|
|
# system wide options
|
|
$<$<COMPILE_LANGUAGE:ASM>:-D__ASSEMBLY__>)
|
|
endif()
|
|
|
|
if(NOT CONFIG_LIBCXXTOOLCHAIN)
|
|
add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-nostdinc++>)
|
|
else()
|
|
add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-D_STDLIB_H_>)
|
|
endif()
|
|
|
|
if(NOT CONFIG_CXX_EXCEPTION)
|
|
add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-fno-exceptions>
|
|
$<$<COMPILE_LANGUAGE:CXX>:-fcheck-new>)
|
|
endif()
|
|
|
|
if(CONFIG_STACK_CANARIES)
|
|
add_compile_options(-fstack-protector-all)
|
|
endif()
|
|
|
|
if(CONFIG_NDEBUG)
|
|
add_compile_options(-DNDEBUG)
|
|
endif()
|
|
|
|
# Cmake build provide absolute paths to compile files. If __FILE__ macros are
|
|
# used in the source code(ASSERT), the binary will contain many invalid paths.
|
|
# This saves some memory, stops exposing build systems locations in binaries,
|
|
# make failure logs more deterministic and most importantly makes builds more
|
|
# failure logs more deterministic and most importantly makes builds more
|
|
# deterministic. Debuggers usually have a path mapping feature to ensure the
|
|
# files are still found.
|
|
if(CONFIG_OUTPUT_STRIP_PATHS)
|
|
add_compile_options(-fmacro-prefix-map=${NUTTX_DIR}=)
|
|
add_compile_options(-fmacro-prefix-map=${NUTTX_APPS_DIR}=)
|
|
add_compile_options(-fmacro-prefix-map=${NUTTX_BOARD_ABS_DIR}=)
|
|
add_compile_options(-fmacro-prefix-map=${NUTTX_CHIP_ABS_DIR}=)
|
|
endif()
|
|
|
|
add_definitions(-D__NuttX__)
|
|
|
|
set_property(
|
|
TARGET nuttx
|
|
APPEND
|
|
PROPERTY NUTTX_KERNEL_DEFINITIONS __KERNEL__)
|
|
|
|
# Recurse subdirectories #####################################################
|
|
|
|
# Each subdirectory will generate a static library
|
|
|
|
if(CONFIG_OPENAMP)
|
|
include_directories(${CMAKE_SOURCE_DIR}/openamp/open-amp/lib/include)
|
|
endif()
|
|
|
|
add_subdirectory(openamp)
|
|
add_subdirectory(arch)
|
|
add_subdirectory(audio)
|
|
add_subdirectory(binfmt)
|
|
add_subdirectory(crypto)
|
|
add_subdirectory(drivers)
|
|
add_subdirectory(fs)
|
|
add_subdirectory(graphics)
|
|
add_subdirectory(libs)
|
|
add_subdirectory(mm)
|
|
add_subdirectory(net)
|
|
add_subdirectory(sched)
|
|
add_subdirectory(syscall)
|
|
add_subdirectory(wireless)
|
|
|
|
# This picks up the chosen board (as well as common board code)
|
|
|
|
add_subdirectory(boards)
|
|
|
|
# POSTBUILD -- Perform post build operations Some architectures require the use
|
|
# of special tools and special handling AFTER building the NuttX binary.
|
|
# Make.defs files for those architectures should override the following define
|
|
# with the correct operations for that platform
|
|
|
|
if(TARGET nuttx_post_build)
|
|
add_custom_target(post_build ALL DEPENDS nuttx_post_build)
|
|
endif()
|
|
|
|
# Add apps/ to the build (if present)
|
|
|
|
if(NOT CONFIG_BUILD_KERNEL)
|
|
|
|
if(EXISTS ${NUTTX_APPS_DIR}/CMakeLists.txt)
|
|
add_subdirectory(${NUTTX_APPS_DIR} apps)
|
|
else()
|
|
message(
|
|
STATUS "Application directory not found at ${NUTTX_APPS_DIR}, skipping")
|
|
endif()
|
|
|
|
endif()
|
|
|
|
# Link step ##################################################################
|
|
|
|
# Get linker script to use
|
|
get_property(ldscript GLOBAL PROPERTY LD_SCRIPT)
|
|
|
|
# Pre-compile linker script
|
|
if(DEFINED PREPROCES)
|
|
get_filename_component(LD_SCRIPT_NAME ${ldscript} NAME)
|
|
set(LD_SCRIPT_TMP "${CMAKE_BINARY_DIR}/${LD_SCRIPT_NAME}.tmp")
|
|
|
|
add_custom_command(
|
|
OUTPUT ${LD_SCRIPT_TMP}
|
|
DEPENDS ${ldscript}
|
|
COMMAND ${PREPROCES} -I${CMAKE_BINARY_DIR}/include -I${NUTTX_CHIP_ABS_DIR}
|
|
${ldscript} > ${LD_SCRIPT_TMP}
|
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
|
|
|
|
add_custom_target(ldscript_tmp DEPENDS ${LD_SCRIPT_TMP})
|
|
add_dependencies(nuttx ldscript_tmp)
|
|
|
|
set(ldscript ${LD_SCRIPT_TMP})
|
|
endif()
|
|
|
|
# Perform link
|
|
|
|
# Add empty source file to nuttx target since cmake requires at least one file
|
|
# and we will only be linking libraries
|
|
|
|
if(CONFIG_HAVE_CXX)
|
|
file(TOUCH "${CMAKE_CURRENT_BINARY_DIR}/empty.cxx")
|
|
target_sources(nuttx PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/empty.cxx")
|
|
else()
|
|
file(TOUCH "${CMAKE_CURRENT_BINARY_DIR}/empty.c")
|
|
target_sources(nuttx PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/empty.c")
|
|
endif()
|
|
|
|
# initialize manifest to hold all generated files
|
|
file(TOUCH ${CMAKE_BINARY_DIR}/nuttx.manifest)
|
|
|
|
get_property(nuttx_kernel_libs GLOBAL PROPERTY NUTTX_KERNEL_LIBRARIES)
|
|
get_property(nuttx_extra_libs GLOBAL PROPERTY NUTTX_EXTRA_LIBRARIES)
|
|
|
|
if(CONFIG_BUILD_FLAT)
|
|
get_property(nuttx_system_libs GLOBAL PROPERTY NUTTX_SYSTEM_LIBRARIES)
|
|
get_property(nuttx_apps_libs GLOBAL PROPERTY NUTTX_APPS_LIBRARIES)
|
|
endif()
|
|
|
|
set(nuttx_libs ${nuttx_kernel_libs} ${nuttx_system_libs} ${nuttx_apps_libs})
|
|
|
|
if(NOT CONFIG_ARCH_SIM)
|
|
|
|
# TODO: nostart/nodefault not applicable to nuttx toolchain
|
|
target_link_libraries(
|
|
nuttx PRIVATE ${NUTTX_EXTRA_FLAGS} -T${ldscript} -Wl,--start-group
|
|
${nuttx_libs} ${nuttx_extra_libs} -Wl,--end-group)
|
|
|
|
# generate binary outputs in different formats (.bin, .hex, etc)
|
|
nuttx_generate_outputs(nuttx)
|
|
|
|
if(CONFIG_UBOOT_UIMAGE)
|
|
add_custom_command(
|
|
OUTPUT uImage
|
|
COMMAND
|
|
${MKIMAGE} -A ${CONFIG_ARCH} -O linux -C none -T kernel -a
|
|
${CONFIG_UIMAGE_LOAD_ADDRESS} -e ${CONFIG_UIMAGE_ENTRY_POINT} -n nuttx
|
|
-d nuttx.bin uImage
|
|
DEPENDS nuttx)
|
|
add_custom_target(nuttx-uImage ALL DEPENDS uImage)
|
|
|
|
# TODO: install? $(Q) if [ -w /tftpboot ] ; then \ cp -f uImage
|
|
# /tftpboot/uImage; \ fi
|
|
file(APPEND ${CMAKE_BINARY_DIR}/nuttx.manifest uImage)
|
|
endif()
|
|
elseif(WIN32)
|
|
target_link_options(nuttx PUBLIC /SAFESEH:NO)
|
|
math(EXPR LINK_STACKSIZE
|
|
"${CONFIG_SIM_STACKSIZE_ADJUSTMENT} + ${CONFIG_IDLETHREAD_STACKSIZE}"
|
|
OUTPUT_FORMAT DECIMAL)
|
|
target_link_options(nuttx PUBLIC /STACK:${LINK_STACKSIZE},${LINK_STACKSIZE})
|
|
set(nuttx_libs_paths)
|
|
foreach(lib ${nuttx_libs})
|
|
list(APPEND nuttx_libs_paths $<TARGET_FILE:${lib}>)
|
|
endforeach()
|
|
|
|
add_custom_command(
|
|
OUTPUT ${CMAKE_BINARY_DIR}/nuttx_all.lib
|
|
COMMAND ${CMAKE_AR} /OUT:${CMAKE_BINARY_DIR}/nuttx_all.lib
|
|
${nuttx_libs_paths} ${nuttx_extra_libs}
|
|
DEPENDS ${nuttx_libs} ${nuttx_extra_libs}
|
|
VERBATIM)
|
|
add_custom_target(nuttx_all-lib DEPENDS ${CMAKE_BINARY_DIR}/nuttx_all.lib)
|
|
add_dependencies(nuttx nuttx_all-lib)
|
|
target_link_libraries(nuttx PRIVATE $<TARGET_OBJECTS:sim_head>
|
|
${CMAKE_BINARY_DIR}/nuttx_all.lib)
|
|
else()
|
|
# On sim platform the link step is a little different. NuttX is first built
|
|
# into a partially linked relocatable object nuttx.rel with no interface to
|
|
# host OS. Then, the names of symbols that conflict with libc symbols are
|
|
# renamed. The final nuttx binary is built by linking the host-specific
|
|
# objects with the relocatable binary.
|
|
|
|
# C++ global objects are constructed before main get executed, but it isn't a
|
|
# good point for simulator because NuttX doesn't finish the kernel
|
|
# initialization yet. So we have to skip the standard facilities and do the
|
|
# construction by ourself. But how to achieve the goal? 1.Command linker
|
|
# generate the default script(-verbose) 2.Replace
|
|
# __init_array_start/__init_array_end with _sinit/_einit 3.Append
|
|
# __init_array_start = .; __init_array_end = .; Step 2 let nxtask_startup find
|
|
# objects need to construct Step 3 cheat the host there is no object to
|
|
# construct Note: the destructor can be fixed in the same way.
|
|
|
|
if(NOT APPLE)
|
|
add_custom_command(
|
|
OUTPUT nuttx.ld
|
|
COMMAND
|
|
${CMAKE_C_COMPILER} ${CMAKE_EXE_LINKER_FLAGS}
|
|
$<$<BOOL:${CONFIG_SIM_M32}>:-m32> -Wl,-verbose 2> /dev/null >
|
|
nuttx-orig.ld || true
|
|
COMMAND
|
|
cat nuttx-orig.ld | sed -e '/====/,/====/!d\;//d' -e
|
|
's/__executable_start/_stext/g' -e 's/__init_array_start/_sinit/g' -e
|
|
's/__init_array_end/_einit/g' -e 's/__fini_array_start/_sfini/g' -e
|
|
's/__fini_array_end/_efini/g' > nuttx.ld
|
|
COMMAND
|
|
echo ARGS
|
|
'__init_array_start = .\; __init_array_end = .\; __fini_array_start = .\; __fini_array_end = .\;'
|
|
>> nuttx.ld
|
|
COMMAND sed -i '/\\.data *:/i " ${CONFIG_SIM_CUSTOM_DATA_SECTION} " '
|
|
nuttx.ld)
|
|
endif()
|
|
|
|
# conflicting symbols to rename
|
|
|
|
include(nuttx_redefine_symbols)
|
|
|
|
# TODO: do with single function call?
|
|
set(nuttx_libs_paths)
|
|
foreach(lib ${nuttx_libs})
|
|
list(APPEND nuttx_libs_paths $<TARGET_FILE:${lib}>)
|
|
endforeach()
|
|
|
|
if(APPLE)
|
|
add_custom_command(
|
|
OUTPUT nuttx.rel
|
|
COMMAND
|
|
${CMAKE_LINKER} ARGS -r $<$<BOOL:${CONFIG_SIM_M32}>:-m32>
|
|
$<TARGET_OBJECTS:sim_head> $<$<NOT:$<BOOL:${APPLE}>>:-Wl,--start-group>
|
|
${nuttx_libs_paths} ${nuttx_extra_libs}
|
|
$<$<NOT:$<BOOL:${APPLE}>>:-Wl,--end-group> -o nuttx.rel
|
|
DEPENDS ${nuttx_libs} ${nuttx_extra_libs} sim_head
|
|
COMMAND_EXPAND_LISTS)
|
|
else()
|
|
add_custom_command(
|
|
OUTPUT nuttx.rel
|
|
COMMAND
|
|
${CMAKE_C_COMPILER} ARGS -r $<$<BOOL:${CONFIG_SIM_M32}>:-m32>
|
|
$<TARGET_OBJECTS:sim_head> $<$<NOT:$<BOOL:${APPLE}>>:-Wl,--start-group>
|
|
${nuttx_libs_paths} ${nuttx_extra_libs}
|
|
$<$<NOT:$<BOOL:${APPLE}>>:-Wl,--end-group> -o nuttx.rel
|
|
COMMAND ${CMAKE_OBJCOPY} --redefine-syms=nuttx-names.dat nuttx.rel
|
|
DEPENDS ${nuttx_libs} ${nuttx_extra_libs} sim_head sim_redefine_symbols
|
|
COMMAND_EXPAND_LISTS)
|
|
endif()
|
|
add_custom_target(nuttx-rel DEPENDS nuttx.rel
|
|
$<$<NOT:$<BOOL:${APPLE}>>:nuttx.ld>)
|
|
|
|
# link the final nuttx binary
|
|
add_dependencies(nuttx nuttx-rel)
|
|
target_link_options(nuttx PUBLIC $<$<NOT:$<BOOL:${APPLE}>>:-T nuttx.ld>
|
|
$<$<BOOL:${CONFIG_SIM_M32}>:-m32>)
|
|
endif()
|
|
|
|
# TODO: if we use an install target a manifest may not be needed
|
|
if(CONFIG_ARCH_SIM)
|
|
file(APPEND ${CMAKE_BINARY_DIR}/nuttx.manifest "nuttx\n")
|
|
endif()
|
|
|
|
# Userspace portion ##########################################################
|
|
|
|
if(CONFIG_BUILD_PROTECTED)
|
|
|
|
get_property(nuttx_system_libs GLOBAL PROPERTY NUTTX_SYSTEM_LIBRARIES)
|
|
|
|
get_property(nuttx_apps_libs GLOBAL PROPERTY NUTTX_APPS_LIBRARIES)
|
|
|
|
get_property(user_ldscript GLOBAL PROPERTY LD_SCRIPT_USER)
|
|
|
|
if(DEFINED PREPROCES)
|
|
get_filename_component(LD_SCRIPT_NAME ${user_ldscript} NAME)
|
|
set(LD_SCRIPT_TMP "${CMAKE_BINARY_DIR}/${LD_SCRIPT_NAME}.tmp")
|
|
add_custom_command(
|
|
OUTPUT ${LD_SCRIPT_TMP}
|
|
DEPENDS ${user_ldscript}
|
|
COMMAND ${PREPROCES} -I${CMAKE_BINARY_DIR}/include -I${NUTTX_CHIP_ABS_DIR}
|
|
${user_ldscript} > ${LD_SCRIPT_TMP}
|
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
|
|
add_custom_target(user_ldscript_tmp DEPENDS ${LD_SCRIPT_TMP})
|
|
add_dependencies(nuttx_user user_ldscript_tmp)
|
|
set(user_ldscript ${LD_SCRIPT_TMP})
|
|
endif()
|
|
|
|
list(TRANSFORM user_ldscript PREPEND "-T")
|
|
|
|
execute_process(
|
|
COMMAND ${CMAKE_C_COMPILER} ${CMAKE_C_FLAGS} ${NUTTX_EXTRA_FLAGS}
|
|
--print-libgcc-file-name
|
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
|
OUTPUT_VARIABLE nuttx_user_libgcc)
|
|
|
|
# reset link options for userspace to prevent sections from being accidentally
|
|
# deleted
|
|
set_target_properties(nuttx_user PROPERTIES LINK_OPTIONS "")
|
|
|
|
target_link_options(
|
|
nuttx_user PRIVATE -nostartfiles -nodefaultlibs
|
|
-Wl,--entry=${CONFIG_INIT_ENTRYPOINT}
|
|
-Wl,--undefined=${CONFIG_INIT_ENTRYPOINT})
|
|
|
|
target_link_libraries(
|
|
nuttx_user
|
|
PRIVATE ${user_ldscript}
|
|
$<$<NOT:$<BOOL:${APPLE}>>:-Wl,--start-group>
|
|
${nuttx_system_libs}
|
|
${nuttx_apps_libs}
|
|
${nuttx_user_libgcc}
|
|
$<$<BOOL:${CONFIG_HAVE_CXX}>:supc++>
|
|
$<$<NOT:$<BOOL:${APPLE}>>:-Wl,--end-group>)
|
|
|
|
target_include_directories(
|
|
nuttx_user SYSTEM
|
|
PRIVATE ${CMAKE_SOURCE_DIR}/include ${CMAKE_BINARY_DIR}/include
|
|
${CMAKE_BINARY_DIR}/include_arch)
|
|
|
|
add_custom_command(
|
|
OUTPUT User.map
|
|
COMMAND ${CMAKE_NM} nuttx_user > User.map
|
|
DEPENDS nuttx_user)
|
|
add_custom_target(usermap ALL DEPENDS User.map)
|
|
|
|
# generate binary outputs in different formats (.bin, .hex, etc)
|
|
nuttx_generate_outputs(nuttx_user)
|
|
|
|
# create merged .hex file ready to be flashed TODO: does not seem to be
|
|
# generating a functional hex file
|
|
if(CONFIG_INTELHEX_BINARY AND SREC_CAT)
|
|
add_custom_command(
|
|
OUTPUT nuttx_combined.hex
|
|
COMMAND ${SREC_CAT} nuttx.hex -intel nuttx_user.hex -intel -o
|
|
nuttx_combined.hex -intel
|
|
DEPENDS nuttx_user nuttx)
|
|
add_custom_target(nuttx-combined ALL DEPENDS nuttx_combined.hex)
|
|
endif()
|
|
|
|
# TODO: could also merge elf binaries
|
|
endif()
|
|
|
|
if(CONFIG_BUILD_KERNEL)
|
|
# TODO: generate nuttx-export-xxx.tar.gz for userland development
|
|
|
|
endif()
|