Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extend build_info.yml #84906

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cmake/modules/boards.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -357,3 +357,4 @@ build_info(board name VALUE ${BOARD})
string(REGEX REPLACE "^/" "" qualifiers "${BOARD_QUALIFIERS}")
build_info(board qualifiers VALUE ${qualifiers})
build_info(board revision VALUE ${BOARD_REVISION})
build_info(board path PATH ${BOARD_DIRECTORIES})
96 changes: 81 additions & 15 deletions cmake/modules/yaml.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@
# - foo2
# - foo3
#
# Support for list of maps, like:
# foo:
# - bar: val1
# baz: val1
# - bar: val2
# baz: val2
#
# All of above can be combined, for example like:
# foo:
# bar: baz
Expand All @@ -28,14 +35,6 @@
# - beta
# - gamma
# fred: thud
#
# Support for list of objects are currently experimental and not guranteed to work.
# For example:
# foo:
# - bar: val1
# baz: val1
# - bar: val2
# baz: val2

include_guard(GLOBAL)

Expand Down Expand Up @@ -97,6 +96,13 @@ function(internal_yaml_list_append var genex key)
internal_yaml_list_initializer(subjson TRUE)
if(${arraylength} GREATER 0)
math(EXPR arraystop "${arraylength} - 1")
list(GET ARG_YAML_LIST 0 entry_0)
if(entry_0 STREQUAL MAP)
message(FATAL_ERROR "${function}(GENEX ${argument} ) is not valid at this position.\n"
"Syntax is 'LIST MAP \"key1: value1.1, ...\" MAP \"key1: value1.2, ...\""
)
endif()

foreach(i RANGE 0 ${arraystop})
string(JSON item GET "${json_content}" ${key} ${i})
list(APPEND subjson ${item})
Expand All @@ -109,12 +115,49 @@ function(internal_yaml_list_append var genex key)
# lists are stored as JSON arrays
string(JSON index LENGTH "${subjson}")
list(LENGTH ARGN length)
math(EXPR stop "${index} + ${length} - 1")
if(NOT length EQUAL 0)
foreach(i RANGE ${index} ${stop})
list(POP_FRONT ARGN value)
string(JSON json_content SET "${json_content}" ${key} ${i} "\"${value}\"")
endforeach()
list(GET ARG_YAML_LIST 0 entry_0)
if(entry_0 STREQUAL MAP)
math(EXPR length "${length} / 2")
math(EXPR stop "${index} + ${length} - 1")
foreach(i RANGE ${index} ${stop})
list(POP_FRONT ARG_YAML_LIST argument)
if(NOT argument STREQUAL MAP)
message(FATAL_ERROR "yaml_set(${argument} ) is not valid at this position.\n"
"Syntax is 'LIST MAP \"key1: value1.1, ...\" MAP \"key1: value1.2, ...\""
)
endif()
list(POP_FRONT ARG_YAML_LIST map_value)
string(REGEX REPLACE "([^\\])," "\\1;" pair_list "${map_value}")
set(qouted_map_value)
foreach(pair ${pair_list})
if(NOT pair MATCHES "[^ ]*:[^ ]*")
message(FATAL_ERROR "yaml_set(MAP ${map_value} ) is malformed.\n"
"Syntax is 'LIST MAP \"key1: value1.1, ...\" MAP \"key1: value1.2, ...\"\n"
"If value contains comma ',' then ensure the value field is properly qouted "
"and escaped"
)
endif()
string(REGEX MATCH "^[^:]*" map_key "${pair}")
string(REGEX REPLACE "^${map_key}:[ ]*" "" value "${pair}")
string(STRIP "${map_key}" map_key)
if(value MATCHES "," AND NOT (value MATCHES "\\\\," AND value MATCHES "'.*'"))
message(FATAL_ERROR "value: ${value} is not properly quoted")
endif()
string(REGEX REPLACE "\\\\," "," value "${value}")
list(APPEND qouted_map_value "\"${map_key}\": \"${value}\"")
endforeach()
list(JOIN qouted_map_value "," qouted_map_value)
string(JSON json_content SET "${json_content}" ${key} ${i} "{${qouted_map_value}}")
endforeach()
else()
math(EXPR stop "${index} + ${length} - 1")
list(GET ARG_YAML_LIST 0 entry_0)
foreach(i RANGE ${index} ${stop})
list(POP_FRONT ARGN value)
string(JSON json_content SET "${json_content}" ${key} ${i} "\"${value}\"")
endforeach()
endif()
endif()
endif()
set(${var} "${json_content}" PARENT_SCOPE)
Expand Down Expand Up @@ -293,6 +336,7 @@ endfunction()
# Usage:
# yaml_set(NAME <name> KEY <key>... [GENEX] VALUE <value>)
# yaml_set(NAME <name> KEY <key>... [APPEND] [GENEX] LIST <value>...)
# yaml_set(NAME <name> KEY <key>... [APPEND] LIST MAP <map1> MAP <map2> MAP ...)
#
# Set a value or a list of values to given key.
#
Expand All @@ -306,6 +350,14 @@ endfunction()
# APPEND : Append the list of values to the list of values for the key.
# GENEX : The value(s) contain generator expressions. When using this
# option, also see the notes in the yaml_save() function.
# MAP <map> : Map, with key-value pairs where key-value is separated by ':',
# and pairs separated by ','.
# Format example: "<key1>: <value1>, <key2>: <value2>, ..."
# MAP can be given multiple times to separate maps when adding them to a list.
# LIST MAP cannot be used with GENEX.
#
# Note: if a map value contains commas, ',', then the value string must be quoted in
# single quotes and commas must be double escaped, like this: 'A \\,string'
#
function(yaml_set)
cmake_parse_arguments(ARG_YAML "APPEND;GENEX" "NAME;VALUE" "KEY;LIST" ${ARGN})
Expand All @@ -328,6 +380,10 @@ function(yaml_set)
message(FATAL_ERROR "${CMAKE_CURRENT_FUNCTION}(APPEND ...) can only be used with argument: LIST")
endif()

if(ARG_YAML_GENEX AND MAP IN_LIST ARG_YAML_LIST)
message(FATAL_ERROR "${function}(GENEX ...) cannot be used with argument: LIST MAP")
endif()

zephyr_get_scoped(json_content ${ARG_YAML_NAME} JSON)
zephyr_get_scoped(genex ${ARG_YAML_NAME} GENEX)

Expand Down Expand Up @@ -366,7 +422,6 @@ function(yaml_set)
internal_yaml_list_initializer(json_string ${genex})
string(JSON json_content SET "${json_content}" ${ARG_YAML_KEY} "${json_string}")
endif()

internal_yaml_list_append(json_content ${genex} "${ARG_YAML_KEY}" ${ARG_YAML_LIST})
else()
string(JSON json_content SET "${json_content}" ${ARG_YAML_KEY} "\"${ARG_YAML_VALUE}\"")
Expand Down Expand Up @@ -520,7 +575,18 @@ function(to_yaml json level yaml genex)
math(EXPR arraystop "${arraylength} - 1")
foreach(i RANGE 0 ${arraystop})
string(JSON item GET "${json}" ${member} ${i})
set(${yaml} "${${yaml}}${indent_${level}} - ${item}\n")
# Check the length of item. Only OBJECT and ARRAY may have length, so a length at this
# level means `to_yaml()` should be called recursively.
string(JSON length ERROR_VARIABLE ignore LENGTH "${item}")
if(length)
set(non_indent_yaml)
to_yaml("${item}" 0 non_indent_yaml FALSE)
string(REGEX REPLACE "\n$" "" non_indent_yaml "${non_indent_yaml}")
string(REPLACE "\n" "\n${indent_${level}} " indent_yaml "${non_indent_yaml}")
set(${yaml} "${${yaml}}${indent_${level}} - ${indent_yaml}\n")
else()
set(${yaml} "${${yaml}}${indent_${level}} - ${item}\n")
endif()
endforeach()
endif()
elseif(type STREQUAL STRING)
Expand Down
11 changes: 11 additions & 0 deletions scripts/schemas/build-schema.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,17 @@ mapping:
type: seq
sequence:
- type: str
images:
type: seq
sequence:
- type: map
mapping:
name:
type: str
source-dir:
type: str
type:
type: str
kconfig:
type: map
mapping:
Expand Down
23 changes: 23 additions & 0 deletions share/sysbuild/cmake/modules/sysbuild_images.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,26 @@
# This module is responsible for including images into sysbuild and to call
# pre and post hooks.

# Internal function to update build info with list of images abnd write the file.
# Main reason for using an internal function is to properly scope variable usage.
# Function takes a list of images.
function(sysbuild_info_image images)
set(info_image_list)
foreach(image ${images})
ExternalProject_Get_Property(${image} SOURCE_DIR)
get_target_property(type ${image} APP_TYPE)
if(type)
list(APPEND info_image_list MAP "name: ${image}, source-dir: ${SOURCE_DIR}, type: ${type}")
else()
list(APPEND info_image_list MAP "name: ${image}, source-dir: ${source_dir}")
endif()
endforeach()
build_info(images VALUE ${info_image_list})
# Save current state of build info. This allow external tools to fetch sysbuild controlled images
# even in the event that one or more image fails configuration stage.
yaml_save(NAME build_info)
endfunction()

get_filename_component(APP_DIR ${APP_DIR} ABSOLUTE)
get_filename_component(app_name ${APP_DIR} NAME)
set(DEFAULT_IMAGE "${app_name}")
Expand All @@ -15,6 +35,9 @@ sysbuild_add_subdirectory(${sysbuild_toplevel_SOURCE_DIR}/images sysbuild/images
get_property(IMAGES GLOBAL PROPERTY sysbuild_images)
sysbuild_module_call(PRE_CMAKE MODULES ${SYSBUILD_MODULE_NAMES} IMAGES ${IMAGES})
sysbuild_images_order(IMAGES_CONFIGURATION_ORDER CONFIGURE IMAGES ${IMAGES})

sysbuild_info_image("${IMAGES}")

foreach(image ${IMAGES_CONFIGURATION_ORDER})
sysbuild_module_call(PRE_IMAGE_CMAKE MODULES ${SYSBUILD_MODULE_NAMES} IMAGES ${IMAGES} IMAGE ${image})
ExternalZephyrProject_Cmake(APPLICATION ${image})
Expand Down
Loading
Loading