From 66fda826e1155a9dc9ea507426b2559b5f6dd8b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20Cab=C3=A9?= Date: Wed, 21 May 2025 15:43:29 +0200 Subject: [PATCH] shields: scripts: cmake: use list_shields.py in shields.cmake MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The logic to "guess" shield names/dirs was duplicated between list_shields.py (which is used by e.g. west shields) and shields.cmake. This commit moves the logic to list_shields.py, and updates shields.cmake to call the script and process its JSON output. Signed-off-by: Benjamin Cabé --- cmake/modules/shields.cmake | 58 ++++++++++++++++++++++--------------- scripts/list_shields.py | 18 ++++++++++-- 2 files changed, 50 insertions(+), 26 deletions(-) diff --git a/cmake/modules/shields.cmake b/cmake/modules/shields.cmake index 04aaec57ac7..256da13e8db 100644 --- a/cmake/modules/shields.cmake +++ b/cmake/modules/shields.cmake @@ -31,6 +31,7 @@ include_guard(GLOBAL) include(extensions) +include(python) # Check that SHIELD has not changed. zephyr_check_cache(SHIELD WATCH) @@ -46,31 +47,42 @@ endif() # After processing all shields, only invalid shields will be left in this list. set(SHIELD-NOTFOUND ${SHIELD_AS_LIST}) -foreach(root ${BOARD_ROOT}) - set(shield_dir ${root}/boards/shields) - # Match the Kconfig.shield files in the shield directories to make sure we are - # finding shields, e.g. x_nucleo_iks01a1/Kconfig.shield - file(GLOB_RECURSE shields_refs_list ${shield_dir}/*/Kconfig.shield) +# Prepare list shields command. +# This command is used for locating the shield dir as well as printing all shields +# in the system in the following cases: +# - User specifies an invalid SHIELD +# - User invokes ' shields' target +list(TRANSFORM BOARD_ROOT PREPEND "--board-root=" OUTPUT_VARIABLE board_root_args) - # The above gives a list of Kconfig.shield files, like this: - # - # x_nucleo_iks01a1/Kconfig.shield;x_nucleo_iks01a2/Kconfig.shield - # - # we construct a list of shield names by extracting the directories - # from each file and looking for .overlay files in there. - # Each overlay corresponds to a shield. We obtain the shield name by - # removing the .overlay extension. - # We also create a SHIELD_DIR_${name} variable for each shield's directory. - foreach(shields_refs ${shields_refs_list}) - get_filename_component(shield_path ${shields_refs} DIRECTORY) - file(GLOB shield_overlays RELATIVE ${shield_path} ${shield_path}/*.overlay) - foreach(overlay ${shield_overlays}) - get_filename_component(shield ${overlay} NAME_WE) - list(APPEND SHIELD_LIST ${shield}) - set(SHIELD_DIR_${shield} ${shield_path}) - endforeach() +set(list_shields_commands + COMMAND ${PYTHON_EXECUTABLE} ${ZEPHYR_BASE}/scripts/list_shields.py + ${board_root_args} --json +) + +# Get list of shields in JSON format +execute_process(${list_shields_commands} + OUTPUT_VARIABLE shields_json + ERROR_VARIABLE err_shields + RESULT_VARIABLE ret_val +) + +if(ret_val) + message(FATAL_ERROR "Error finding shields\nError message: ${err_shields}") +endif() + +string(JSON shields_length LENGTH ${shields_json}) + +if(shields_length GREATER 0) + math(EXPR shields_length "${shields_length} - 1") + + foreach(i RANGE ${shields_length}) + string(JSON shield GET "${shields_json}" "${i}") + string(JSON shield_name GET ${shield} name) + string(JSON shield_dir GET ${shield} dir) + list(APPEND SHIELD_LIST ${shield_name}) + set(SHIELD_DIR_${shield_name} ${shield_dir}) endforeach() -endforeach() +endif() # Process shields in-order if(DEFINED SHIELD) diff --git a/scripts/list_shields.py b/scripts/list_shields.py index fe27f77f6e8..7021755dcc9 100755 --- a/scripts/list_shields.py +++ b/scripts/list_shields.py @@ -5,6 +5,7 @@ # SPDX-License-Identifier: Apache-2.0 import argparse +import json from dataclasses import dataclass from pathlib import Path @@ -57,6 +58,7 @@ def find_shields_in(root): def parse_args(): parser = argparse.ArgumentParser(allow_abbrev=False) add_args(parser) + add_args_formatting(parser) return parser.parse_args() def add_args(parser): @@ -66,9 +68,19 @@ def add_args(parser): type=Path, action='append', help='add a board root, may be given more than once') +def add_args_formatting(parser): + parser.add_argument("--json", action='store_true', + help='''output list of shields in JSON format''') + def dump_shields(shields): - for shield in shields: - print(f' {shield.name}') + if args.json: + print( + json.dumps([{'dir': shield.dir.as_posix(), 'name': shield.name} for shield in shields]) + ) + else: + for shield in shields: + print(f' {shield.name}') if __name__ == '__main__': - dump_shields(find_shields(parse_args())) + args = parse_args() + dump_shields(find_shields(args))