# 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 ' 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 .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 ' 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 -E echo " 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)