zephyr/cmake/dts.cmake
Anas Nashif e172fa3b52 build: support out-of-tree custom boards
This is one way we can support out of tree board definitions. Basically
all this needs is a board definition in the application source directory
that follows the same structure we have in the main Zephyr tree (also
allowing multiple custom boards). An application tree would look like
this for example:

boards/
CMakeLists.txt
prj.conf
README.rst
src/

with boards following the same structure as in Zephyr:

.
├── boards
│   └── x86
│       └── arduino_101
│           ├── doc
│           │   └── img
│           └── support
└── src

To use this, you need to specify the BOARD_ROOT variable on the command
line when building:

cmake -DBOARD=<board name> -DBOARD_ROOT=<path to boards> ..

Signed-off-by: Anas Nashif <anas.nashif@intel.com>
2018-02-14 19:20:29 -05:00

137 lines
4.8 KiB
CMake

# Zephyr code can configure itself based on a KConfig'uration with the
# header file autoconf.h. There exists an analogous file
# generated_dts_board.h that allows configuration based on information
# encoded in DTS.
#
# Here we call on dtc, the gcc preprocessor, and
# scripts/dts/extract_dts_includes.py to generate this header file at
# CMake configure-time.
#
# See ~/zephyr/doc/dts
set(GENERATED_DTS_BOARD_H ${PROJECT_BINARY_DIR}/include/generated/generated_dts_board.h)
set(GENERATED_DTS_BOARD_CONF ${PROJECT_BINARY_DIR}/include/generated/generated_dts_board.conf)
set_ifndef(DTS_SOURCE ${BOARD_ROOT}/boards/${ARCH}/${BOARD_FAMILY}/${BOARD_FAMILY}.dts)
set_ifndef(DTS_COMMON_OVERLAYS ${PROJECT_SOURCE_DIR}/dts/common/common.dts)
message(STATUS "Generating zephyr/include/generated/generated_dts_board.h")
if(CONFIG_HAS_DTS)
if(DTC_OVERLAY_FILE)
# Convert from space-separated files into file list
string(REPLACE " " ";" DTC_OVERLAY_FILE_AS_LIST ${DTC_OVERLAY_FILE})
endif()
# Prepend common overlays
set(DTC_OVERLAY_FILE_AS_LIST ${DTS_COMMON_OVERLAYS} ${DTC_OVERLAY_FILE_AS_LIST})
set(
dts_files
${DTS_SOURCE}
${DTC_OVERLAY_FILE_AS_LIST}
)
unset(DTC_INCLUDE_FLAG_FOR_DTS)
foreach(dts_file ${dts_files})
list(APPEND DTC_INCLUDE_FLAG_FOR_DTS
-include ${dts_file})
endforeach()
# TODO: Cut down on CMake configuration time by avoiding
# regeneration of generated_dts_board.h on every configure. How
# challenging is this? What are the dts dependencies? We run the
# preprocessor, and it seems to be including all kinds of
# directories with who-knows how many header files.
# Run the C preprocessor on an empty C source file that has one or
# more DTS source files -include'd into it to create the
# intermediary file *.dts.pre.tmp
execute_process(
COMMAND ${CMAKE_C_COMPILER}
-x assembler-with-cpp
-nostdinc
-I${PROJECT_SOURCE_DIR}/arch/${ARCH}/soc
-isystem ${PROJECT_SOURCE_DIR}/include
-isystem ${PROJECT_SOURCE_DIR}/dts/${ARCH}
-isystem ${PROJECT_SOURCE_DIR}/dts
-include ${AUTOCONF_H}
${DTC_INCLUDE_FLAG_FOR_DTS} # include the DTS source and overlays
-I${PROJECT_SOURCE_DIR}/dts/common
-I${PROJECT_SOURCE_DIR}/drivers
-undef -D__DTS__
-P
-E ${ZEPHYR_BASE}/misc/empty_file.c
-o ${BOARD_FAMILY}.dts.pre.tmp
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
RESULT_VARIABLE ret
)
if(NOT "${ret}" STREQUAL "0")
message(FATAL_ERROR "command failed with return code: ${ret}")
endif()
# Run the DTC on *.dts.pre.tmp to create the intermediary file *.dts_compiled
execute_process(
COMMAND ${DTC}
-O dts
-o ${BOARD_FAMILY}.dts_compiled
-b 0
${BOARD_FAMILY}.dts.pre.tmp
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
RESULT_VARIABLE ret
)
if(NOT "${ret}" STREQUAL "0")
message(FATAL_ERROR "command failed with return code: ${ret}")
endif()
# Run extract_dts_includes.py for the header file
# generated_dts_board.h
set_ifndef(DTS_BOARD_FIXUP_FILE ${BOARD_ROOT}/boards/${ARCH}/${BOARD_FAMILY}/dts.fixup)
if(EXISTS ${DTS_BOARD_FIXUP_FILE})
set(DTS_BOARD_FIXUP -f ${DTS_BOARD_FIXUP_FILE})
endif()
set_ifndef(DTS_SOC_FIXUP_FILE ${PROJECT_SOURCE_DIR}/arch/${ARCH}/soc/${CONFIG_SOC_FAMILY}/${CONFIG_SOC_SERIES}/dts.fixup)
if(EXISTS ${DTS_SOC_FIXUP_FILE})
set(DTS_SOC_FIXUP -f ${DTS_SOC_FIXUP_FILE})
endif()
if(EXISTS ${APPLICATION_SOURCE_DIR}/dts.fixup)
set(DTS_APP_FIXUP -f ${APPLICATION_SOURCE_DIR}/dts.fixup)
endif()
set(CMD_EXTRACT_DTS_INCLUDES ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/scripts/dts/extract_dts_includes.py
--dts ${BOARD_FAMILY}.dts_compiled
--yaml ${PROJECT_SOURCE_DIR}/dts/bindings
${DTS_SOC_FIXUP} ${DTS_BOARD_FIXUP} ${DTS_APP_FIXUP}
)
execute_process(
COMMAND ${CMD_EXTRACT_DTS_INCLUDES}
OUTPUT_VARIABLE STDOUT
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
RESULT_VARIABLE ret
)
if(NOT "${ret}" STREQUAL "0")
message(FATAL_ERROR "command failed with return code: ${ret}")
endif()
# extract_dts_includes.py writes the header file contents to stdout,
# which we capture in the variable STDOUT and then finaly write into
# the header file.
file(WRITE ${GENERATED_DTS_BOARD_H} "${STDOUT}" )
# Run extract_dts_includes.py to create a .conf file that can be
# included into the CMake namespace
execute_process(
COMMAND ${CMD_EXTRACT_DTS_INCLUDES} --keyvalue
OUTPUT_VARIABLE STDOUT
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
RESULT_VARIABLE ret
)
if(NOT "${ret}" STREQUAL "0")
message(FATAL_ERROR "command failed with return code: ${ret}")
endif()
file(WRITE ${GENERATED_DTS_BOARD_CONF} "${STDOUT}" )
import_kconfig(${GENERATED_DTS_BOARD_CONF})
else()
file(WRITE ${GENERATED_DTS_BOARD_H} "/* WARNING. THIS FILE IS AUTO-GENERATED. DO NOT MODIFY! */")
endif()