sysbuild: Make the image processing order well-defined
Adjust the order in which image-specific `sysbuild.cmake` files are iteratively included by sysbuild. This is motivated by the introduction of `sysbuild_add_dependencies()`. In the following example: sysbuild_add_dependencies(CONFIGURE my_sample sample_a sample_b) the `my_sample` image is expected to be added before this function is called. Success depends not only on the placement of the call, but on the order in which new images are added, which itself is influenced by the order in which `sysbuild.cmake` files are included. This last order can be tweaked to make the "dependencies" feature more user-friendly. This is done by rewriting the internal `sysbuild.cmake` processing loop into a new, general purpose function - `sysbuild_add_subdirectory()` - which is a wrapper for `add_subdirectory(<source_dir>)` that recursively includes `sysbuild.cmake` files for all images found in `<source_dir>`. With the new function, all images that are expected to be found in a given `<source_dir>` are guaranteed to be added around the same time. This wasn't the case with the old processing loop, because the image- specific `sysbuild.cmake` files (where "sub-images" could be defined) were left to be processed at the very end. Below is the initial order in which sysbuild will add all images. Note: the order of Zephyr modules (from 1 to n) is well-defined. 1. Main application (aka DEFAULT_IMAGE) 2. MCUboot (optional) 3. All images added via these directories: 3.1. <module-1>.sysbuild-cmake 3.2. <module-2>.sysbuild-cmake ... 3.n. <module-n>.sysbuild-cmake 4. All images added via these files: 4.1. ${BOARD_DIR}/sysbuild.cmake 4.2. ${APP_DIR}/sysbuild.cmake (aka sub-images of DEFAULT_IMAGE) These images are intended to be sorted for the users' convenience, from most to least important in the build system, or least to most dependent on other images for configuration (potentially). Finally, the use of `sysbuild_add_subdirectory()` requires updating the directory structure in sysbuild: ./images - All images should belong here. The `DEFAULT_IMAGE` should be the first and only image at the top level, so that it gets added first and its sub-images get added last. ./images/bootloader - Moved from ./bootloader. ./images/boards - Adds images from the board-specific `sysbuild.cmake` file. Signed-off-by: Grzegorz Swiderski <grzegorz.swiderski@nordicsemi.no>
This commit is contained in:
parent
6640c04df6
commit
4cfea45c44
|
@ -26,62 +26,12 @@ project(sysbuild LANGUAGES)
|
|||
|
||||
get_filename_component(APP_DIR ${APP_DIR} ABSOLUTE)
|
||||
get_filename_component(app_name ${APP_DIR} NAME)
|
||||
|
||||
# Include zephyr modules generated sysbuild CMake file.
|
||||
foreach(SYSBUILD_CURRENT_MODULE_NAME ${SYSBUILD_MODULE_NAMES})
|
||||
# Note the second, binary_dir parameter requires the added
|
||||
# subdirectory to have its own, local cmake target(s). If not then
|
||||
# this binary_dir is created but stays empty. Object files land in
|
||||
# the main binary dir instead.
|
||||
# https://cmake.org/pipermail/cmake/2019-June/069547.html
|
||||
zephyr_string(SANITIZE TOUPPER MODULE_NAME_UPPER ${SYSBUILD_CURRENT_MODULE_NAME})
|
||||
if(NOT ${SYSBUILD_${MODULE_NAME_UPPER}_CMAKE_DIR} STREQUAL "")
|
||||
set(SYSBUILD_CURRENT_MODULE_DIR ${SYSBUILD_${MODULE_NAME_UPPER}_MODULE_DIR})
|
||||
set(SYSBUILD_CURRENT_CMAKE_DIR ${SYSBUILD_${MODULE_NAME_UPPER}_CMAKE_DIR})
|
||||
add_subdirectory(${SYSBUILD_CURRENT_CMAKE_DIR} ${CMAKE_BINARY_DIR}/modules/${SYSBUILD_CURRENT_MODULE_NAME})
|
||||
endif()
|
||||
endforeach()
|
||||
# Done processing modules, clear SYSBUILD_CURRENT_MODULE_DIR and SYSBUILD_CURRENT_CMAKE_DIR.
|
||||
set(SYSBUILD_CURRENT_MODULE_DIR)
|
||||
set(SYSBUILD_CURRENT_CMAKE_DIR)
|
||||
|
||||
# This adds the primary application to the build.
|
||||
ExternalZephyrProject_Add(
|
||||
APPLICATION ${app_name}
|
||||
SOURCE_DIR ${APP_DIR}
|
||||
APP_TYPE MAIN
|
||||
)
|
||||
set(DEFAULT_IMAGE "${app_name}")
|
||||
|
||||
add_subdirectory(bootloader)
|
||||
# This is where all Zephyr applications are added to the multi-image build.
|
||||
sysbuild_add_subdirectory(images)
|
||||
|
||||
# This allows for board and app specific images to be included.
|
||||
include(${BOARD_DIR}/sysbuild.cmake OPTIONAL)
|
||||
|
||||
# This allows image specific sysbuild.cmake to be processed.
|
||||
get_property(IMAGES GLOBAL PROPERTY sysbuild_images)
|
||||
list(LENGTH IMAGES images_length)
|
||||
while(NOT "${images_length}" EQUAL "${processed_length}")
|
||||
foreach(image ${IMAGES})
|
||||
if(NOT image IN_LIST images_sysbuild_processed)
|
||||
ExternalProject_Get_property(${image} SOURCE_DIR)
|
||||
include(${SOURCE_DIR}/sysbuild.cmake OPTIONAL)
|
||||
list(APPEND images_sysbuild_processed ${image})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
get_property(IMAGES GLOBAL PROPERTY sysbuild_images)
|
||||
list(LENGTH IMAGES images_length)
|
||||
list(LENGTH images_sysbuild_processed processed_length_new)
|
||||
|
||||
# Check for any duplicate entries in image names to prevent an infinite loop
|
||||
if("${processed_length_new}" EQUAL "${processed_length}")
|
||||
# Image length was different than processed length, but no new images are processed.
|
||||
message(FATAL_ERROR "A duplicate image name was provided, image names must be unique.")
|
||||
endif()
|
||||
set(processed_length ${processed_length_new})
|
||||
endwhile()
|
||||
|
||||
sysbuild_module_call(PRE_CMAKE MODULES ${SYSBUILD_MODULE_NAMES} IMAGES ${IMAGES})
|
||||
sysbuild_images_order(IMAGES_CONFIGURATION_ORDER CONFIGURE IMAGES ${IMAGES})
|
||||
foreach(image ${IMAGES_CONFIGURATION_ORDER})
|
||||
|
|
|
@ -39,4 +39,4 @@ config WARN_DEPRECATED
|
|||
Print a warning when the Kconfig tree is parsed if any deprecated
|
||||
features are enabled.
|
||||
|
||||
rsource "bootloader/Kconfig"
|
||||
rsource "images/Kconfig"
|
||||
|
|
|
@ -145,6 +145,13 @@ function(ExternalZephyrProject_Add)
|
|||
)
|
||||
endif()
|
||||
|
||||
if(TARGET ${ZBUILD_APPLICATION})
|
||||
message(FATAL_ERROR
|
||||
"ExternalZephyrProject_Add(APPLICATION ${ZBUILD_APPLICATION} ...) "
|
||||
"already exists. Application names must be unique."
|
||||
)
|
||||
endif()
|
||||
|
||||
if(DEFINED ZBUILD_APP_TYPE)
|
||||
if(NOT ZBUILD_APP_TYPE IN_LIST app_types)
|
||||
message(FATAL_ERROR
|
||||
|
@ -155,6 +162,16 @@ function(ExternalZephyrProject_Add)
|
|||
|
||||
endif()
|
||||
|
||||
if(NOT DEFINED SYSBUILD_CURRENT_SOURCE_DIR)
|
||||
message(FATAL_ERROR
|
||||
"ExternalZephyrProject_Add(${ARGV0} <val> ...) must not be called outside of"
|
||||
" sysbuild_add_subdirectory(). SYSBUILD_CURRENT_SOURCE_DIR is undefined."
|
||||
)
|
||||
endif()
|
||||
set_property(
|
||||
DIRECTORY "${SYSBUILD_CURRENT_SOURCE_DIR}"
|
||||
APPEND PROPERTY sysbuild_images ${ZBUILD_APPLICATION}
|
||||
)
|
||||
set_property(
|
||||
GLOBAL
|
||||
APPEND PROPERTY sysbuild_images ${ZBUILD_APPLICATION}
|
||||
|
@ -566,6 +583,45 @@ function(set_config_string image setting value)
|
|||
set_property(TARGET ${image} APPEND_STRING PROPERTY CONFIG "${setting}=\"${value}\"\n")
|
||||
endfunction()
|
||||
|
||||
# Usage:
|
||||
# sysbuild_add_subdirectory(<source_dir> [<binary_dir>])
|
||||
#
|
||||
# This function extends the standard add_subdirectory() command with additional,
|
||||
# recursive processing of the sysbuild images added via <source_dir>.
|
||||
#
|
||||
# After exiting <source_dir>, this function will take every image added so far,
|
||||
# and include() its sysbuild.cmake file (if found). If more images get added at
|
||||
# this stage, their sysbuild.cmake files will be included as well, and so on.
|
||||
# This continues until all expected images have been added, before returning.
|
||||
#
|
||||
function(sysbuild_add_subdirectory source_dir)
|
||||
if(ARGC GREATER 2)
|
||||
message(FATAL_ERROR
|
||||
"sysbuild_add_subdirectory(...) called with incorrect number of arguments"
|
||||
" (expected at most 2, got ${ARGC})"
|
||||
)
|
||||
endif()
|
||||
set(binary_dir ${ARGV1})
|
||||
|
||||
# Update SYSBUILD_CURRENT_SOURCE_DIR in this scope, to support nesting
|
||||
# of sysbuild_add_subdirectory() and even regular add_subdirectory().
|
||||
cmake_path(ABSOLUTE_PATH source_dir NORMALIZE OUTPUT_VARIABLE SYSBUILD_CURRENT_SOURCE_DIR)
|
||||
add_subdirectory(${source_dir} ${binary_dir})
|
||||
|
||||
while(TRUE)
|
||||
get_property(added_images DIRECTORY "${SYSBUILD_CURRENT_SOURCE_DIR}" PROPERTY sysbuild_images)
|
||||
if(NOT added_images)
|
||||
break()
|
||||
endif()
|
||||
set_property(DIRECTORY "${SYSBUILD_CURRENT_SOURCE_DIR}" PROPERTY sysbuild_images "")
|
||||
|
||||
foreach(image ${added_images})
|
||||
ExternalProject_Get_property(${image} SOURCE_DIR)
|
||||
include(${SOURCE_DIR}/sysbuild.cmake OPTIONAL)
|
||||
endforeach()
|
||||
endwhile()
|
||||
endfunction()
|
||||
|
||||
# Usage:
|
||||
# sysbuild_add_dependencies(<CONFIGURE | FLASH> <image> [<image-dependency> ...])
|
||||
#
|
||||
|
|
36
share/sysbuild/images/CMakeLists.txt
Normal file
36
share/sysbuild/images/CMakeLists.txt
Normal file
|
@ -0,0 +1,36 @@
|
|||
# Copyright (c) 2021-2023 Nordic Semiconductor
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
# The primary application is the first image to be added to the build, so that
|
||||
# it is available while processing the remaining images.
|
||||
ExternalZephyrProject_Add(
|
||||
APPLICATION ${DEFAULT_IMAGE}
|
||||
SOURCE_DIR ${APP_DIR}
|
||||
APP_TYPE MAIN
|
||||
)
|
||||
|
||||
# This allows for MCUboot to be included.
|
||||
sysbuild_add_subdirectory(bootloader)
|
||||
|
||||
# Include zephyr modules generated sysbuild CMake file.
|
||||
foreach(SYSBUILD_CURRENT_MODULE_NAME ${SYSBUILD_MODULE_NAMES})
|
||||
# Note the second, binary_dir parameter requires the added
|
||||
# subdirectory to have its own, local cmake target(s). If not then
|
||||
# this binary_dir is created but stays empty. Object files land in
|
||||
# the main binary dir instead.
|
||||
# https://cmake.org/pipermail/cmake/2019-June/069547.html
|
||||
zephyr_string(SANITIZE TOUPPER MODULE_NAME_UPPER ${SYSBUILD_CURRENT_MODULE_NAME})
|
||||
if(NOT ${SYSBUILD_${MODULE_NAME_UPPER}_CMAKE_DIR} STREQUAL "")
|
||||
set(SYSBUILD_CURRENT_MODULE_DIR ${SYSBUILD_${MODULE_NAME_UPPER}_MODULE_DIR})
|
||||
set(SYSBUILD_CURRENT_CMAKE_DIR ${SYSBUILD_${MODULE_NAME_UPPER}_CMAKE_DIR})
|
||||
sysbuild_add_subdirectory(${SYSBUILD_CURRENT_CMAKE_DIR}
|
||||
${CMAKE_BINARY_DIR}/modules/${SYSBUILD_CURRENT_MODULE_NAME})
|
||||
endif()
|
||||
endforeach()
|
||||
# Done processing modules, clear SYSBUILD_CURRENT_MODULE_DIR and SYSBUILD_CURRENT_CMAKE_DIR.
|
||||
set(SYSBUILD_CURRENT_MODULE_DIR)
|
||||
set(SYSBUILD_CURRENT_CMAKE_DIR)
|
||||
|
||||
# This allows for board specific images to be included.
|
||||
sysbuild_add_subdirectory(boards)
|
5
share/sysbuild/images/Kconfig
Normal file
5
share/sysbuild/images/Kconfig
Normal file
|
@ -0,0 +1,5 @@
|
|||
# Copyright (c) 2021-2023 Nordic Semiconductor
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
rsource "bootloader/Kconfig"
|
5
share/sysbuild/images/boards/CMakeLists.txt
Normal file
5
share/sysbuild/images/boards/CMakeLists.txt
Normal file
|
@ -0,0 +1,5 @@
|
|||
# Copyright (c) 2021-2023 Nordic Semiconductor
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
include(${BOARD_DIR}/sysbuild.cmake OPTIONAL)
|
Loading…
Reference in a new issue