|  | # SPDX-License-Identifier: Apache-2.0 | 
|  | # | 
|  | # Copyright (c) 2021, Nordic Semiconductor ASA | 
|  |  | 
|  | # Validate shields and setup shields target. | 
|  | # | 
|  | # This module will validate the SHIELD argument. | 
|  | # | 
|  | # If a shield implementation is not found for one of the specified shields, an | 
|  | # error will be raised and a list of valid shields will be printed. | 
|  | # | 
|  | # Outcome: | 
|  | # The following variables will be defined when this module completes: | 
|  | # - shield_conf_files: List of shield-specific Kconfig fragments | 
|  | # - shield_dts_files : List of shield-specific devicetree files | 
|  | # - SHIELD_AS_LIST   : A CMake list of shields created from the SHIELD variable. | 
|  | # - SHIELD_DIRS      : A CMake list of directories which contain shield definitions | 
|  | # | 
|  | # The following targets will be defined when this CMake module completes: | 
|  | # - shields: when invoked, a list of valid shields will be printed | 
|  | # | 
|  | # If the SHIELD variable is changed after this module completes, | 
|  | # a warning will be printed. | 
|  | # | 
|  | # Optional variables: | 
|  | # - BOARD_ROOT: CMake list of board roots containing board implementations | 
|  | # | 
|  | # Variables set by this module and not mentioned above are for internal | 
|  | # use only, and may be removed, renamed, or re-purposed without prior notice. | 
|  |  | 
|  | include_guard(GLOBAL) | 
|  |  | 
|  | include(extensions) | 
|  | include(python) | 
|  |  | 
|  | # Check that SHIELD has not changed. | 
|  | zephyr_check_cache(SHIELD WATCH) | 
|  |  | 
|  | if(SHIELD) | 
|  | message(STATUS "Shield(s): ${SHIELD}") | 
|  | endif() | 
|  |  | 
|  | if(DEFINED SHIELD) | 
|  | string(REPLACE " " ";" SHIELD_AS_LIST "${SHIELD}") | 
|  | endif() | 
|  | # SHIELD-NOTFOUND is a real CMake list, from which valid shields can be popped. | 
|  | # After processing all shields, only invalid shields will be left in this list. | 
|  | set(SHIELD-NOTFOUND ${SHIELD_AS_LIST}) | 
|  |  | 
|  | # 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 '<build-command> shields' target | 
|  | list(TRANSFORM BOARD_ROOT PREPEND "--board-root=" OUTPUT_VARIABLE board_root_args) | 
|  |  | 
|  | 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() | 
|  | endif() | 
|  |  | 
|  | # Process shields in-order | 
|  | if(DEFINED SHIELD) | 
|  | foreach(s ${SHIELD_AS_LIST}) | 
|  | if(NOT ${s} IN_LIST SHIELD_LIST) | 
|  | continue() | 
|  | endif() | 
|  |  | 
|  | list(REMOVE_ITEM SHIELD-NOTFOUND ${s}) | 
|  |  | 
|  | # Add <shield>.overlay to the shield_dts_files output variable. | 
|  | list(APPEND | 
|  | shield_dts_files | 
|  | ${SHIELD_DIR_${s}}/${s}.overlay | 
|  | ) | 
|  |  | 
|  | # Add the shield's directory to the SHIELD_DIRS output variable. | 
|  | list(APPEND | 
|  | SHIELD_DIRS | 
|  | ${SHIELD_DIR_${s}} | 
|  | ) | 
|  |  | 
|  | include(${SHIELD_DIR_${s}}/pre_dt_shield.cmake OPTIONAL) | 
|  |  | 
|  | # Search for shield/shield.conf file | 
|  | if(EXISTS ${SHIELD_DIR_${s}}/${s}.conf) | 
|  | list(APPEND | 
|  | shield_conf_files | 
|  | ${SHIELD_DIR_${s}}/${s}.conf | 
|  | ) | 
|  | endif() | 
|  |  | 
|  | # Add board-specific .conf and .overlay files to their | 
|  | # respective output variables. | 
|  | zephyr_file(CONF_FILES ${SHIELD_DIR_${s}}/boards | 
|  | DTS   shield_dts_files | 
|  | KCONF shield_conf_files | 
|  | ) | 
|  | zephyr_file(CONF_FILES ${SHIELD_DIR_${s}}/boards/${s} | 
|  | DTS   shield_dts_files | 
|  | KCONF shield_conf_files | 
|  | ) | 
|  | endforeach() | 
|  | endif() | 
|  |  | 
|  | # Prepare shield usage command printing. | 
|  | # This command prints all shields in the system in the following cases: | 
|  | # - User specifies an invalid SHIELD | 
|  | # - User invokes '<build-command> shields' target | 
|  | list(SORT SHIELD_LIST) | 
|  |  | 
|  | if(DEFINED SHIELD AND NOT (SHIELD-NOTFOUND STREQUAL "")) | 
|  | # Convert the list to pure string with newlines for printing. | 
|  | string(REPLACE ";" "\n" shield_string "${SHIELD_LIST}") | 
|  |  | 
|  | foreach (s ${SHIELD-NOTFOUND}) | 
|  | message("No shield named '${s}' found") | 
|  | endforeach() | 
|  | message("Please choose from among the following shields:\n" | 
|  | "${shield_string}" | 
|  | ) | 
|  | unset(CACHED_SHIELD CACHE) | 
|  | message(FATAL_ERROR "Invalid SHIELD; see above.") | 
|  | endif() | 
|  |  | 
|  | # Prepend each shield with COMMAND <cmake> -E echo <shield>" for printing. | 
|  | # Each shield is printed as new command because build files are not fond of newlines. | 
|  | list(TRANSFORM SHIELD_LIST PREPEND "COMMAND;${CMAKE_COMMAND};-E;echo;" | 
|  | OUTPUT_VARIABLE shields_target_cmd | 
|  | ) | 
|  |  | 
|  | add_custom_target(shields ${shields_target_cmd} USES_TERMINAL) |