1# SPDX-License-Identifier: Apache-2.0 2 3function(runners_yaml_append content) 4 # Append ${content}\n to a target property which is later evaluated as a 5 # generator expression when writing the flash runner yaml file. 6 # We define this function here to have access to the `flash` target. 7 8 set_property( 9 TARGET runners_yaml_props_target 10 APPEND_STRING 11 PROPERTY yaml_contents 12 "${content}\n" 13 ) 14endfunction() 15 16function(get_runners_prop prop out_var default_value) 17 # Get property 'prop' from runners_yaml_props_target, storing its 18 # value in 'out_var'. If the property is not found (value is 19 # ...-NOTFOUND), 'out_var' is set to 'default_value'. 20 21 get_target_property(out runners_yaml_props_target "${prop}") 22 23 if("${out}" STREQUAL "out-NOTFOUND") 24 set("${out_var}" "${default_value}" PARENT_SCOPE) 25 else() 26 set("${out_var}" "${out}" PARENT_SCOPE) 27 endif() 28endfunction() 29 30function(runners_yaml_append_config) 31 # Append the common configuration values to the relevant property target. 32 33 runners_yaml_append("\n# Common runner configuration values.") 34 runners_yaml_append("config:") 35 runners_yaml_append(" board_dir: ${BOARD_DIR}") 36 get_runners_prop(elf_file elf "${KERNEL_ELF_NAME}") 37 runners_yaml_append(" # Build outputs:") 38 runners_yaml_append(" elf_file: ${elf}") 39 if(CONFIG_BUILD_OUTPUT_EXE) 40 get_runners_prop(exe_file exe "${KERNEL_EXE_NAME}") 41 else() 42 get_runners_prop(exe_file exe "") 43 endif() 44 if(exe) 45 runners_yaml_append(" exe_file: ${exe}") 46 endif() 47 if(CONFIG_BUILD_OUTPUT_HEX) 48 get_runners_prop(hex_file hex "${KERNEL_HEX_NAME}") 49 else() 50 get_runners_prop(hex_file hex "") 51 endif() 52 if(hex) 53 runners_yaml_append(" hex_file: ${hex}") 54 endif() 55 if(CONFIG_BUILD_OUTPUT_BIN) 56 get_runners_prop(bin_file bin "${KERNEL_BIN_NAME}") 57 runners_yaml_append(" bin_file: ${bin}") 58 endif() 59 if(CONFIG_BUILD_OUTPUT_UF2) 60 get_runners_prop(uf2_file uf2 "${KERNEL_UF2_NAME}") 61 runners_yaml_append(" uf2_file: ${uf2}") 62 endif() 63 64 zephyr_get(OPENOCD) 65 zephyr_get(OPENOCD_DEFAULT_PATH) 66 if(CMAKE_GDB OR OPENOCD OR OPENOCD_DEFAULT_PATH) 67 runners_yaml_append(" # Host tools:") 68 endif() 69 if(CMAKE_GDB) 70 runners_yaml_append(" gdb: ${CMAKE_GDB}") 71 endif() 72 if(OPENOCD) 73 runners_yaml_append(" openocd: ${OPENOCD}") 74 runners_yaml_append(" openocd_search:") 75 if(OPENOCD_DEFAULT_PATH) 76 runners_yaml_append(" - ${OPENOCD_DEFAULT_PATH}") 77 endif() 78 endif() 79 runners_yaml_append("") 80endfunction() 81 82# Save runner state in a YAML file. 83function(create_runners_yaml) 84 set(runners ${ARGV}) 85 86 set(runners_yaml "${PROJECT_BINARY_DIR}/runners.yaml") 87 88 runners_yaml_append("# Available runners configured by board.cmake.\nrunners:") 89 foreach(runner ${runners}) 90 runners_yaml_append("- ${runner}") 91 endforeach() 92 93 if(DEFINED BOARD_FLASH_RUNNER) 94 runners_yaml_append("\n# Default flash runner if --runner is not given.") 95 runners_yaml_append("flash-runner: ${BOARD_FLASH_RUNNER}") 96 endif() 97 if(DEFINED BOARD_DEBUG_RUNNER) 98 runners_yaml_append("\n# Default debug runner if --runner is not given.") 99 runners_yaml_append("debug-runner: ${BOARD_DEBUG_RUNNER}") 100 endif() 101 if(DEFINED BOARD_SIM_RUNNER) 102 runners_yaml_append("\n# Default simulation runner if --runner is not given.") 103 runners_yaml_append("sim-runner: ${BOARD_SIM_RUNNER}") 104 endif() 105 if(DEFINED BOARD_ROBOT_RUNNER) 106 runners_yaml_append("\n# Default test runner if --runner is not given.") 107 runners_yaml_append("robot-runner: ${BOARD_ROBOT_RUNNER}") 108 endif() 109 110 # Sets up common runner configuration values. 111 runners_yaml_append_config() 112 113 # Get runner-specific arguments set in the board files. 114 runners_yaml_append("# Runner specific arguments") 115 runners_yaml_append("args:") 116 foreach(runner ${runners}) 117 string(MAKE_C_IDENTIFIER ${runner} runner_id) 118 runners_yaml_append(" ${runner}:") 119 get_property(args GLOBAL PROPERTY "BOARD_RUNNER_ARGS_${runner_id}") 120 if(args) 121 # Usually, the runner has arguments. Append them to runners.yaml, 122 # one per line. 123 foreach(arg ${args}) 124 runners_yaml_append(" - ${arg}") 125 endforeach() 126 else() 127 # If the runner doesn't need any arguments, just use an empty list. 128 runners_yaml_append(" []\n") 129 endif() 130 endforeach() 131 132 # Write the final contents. 133 file(GENERATE OUTPUT "${runners_yaml}" CONTENT 134 $<TARGET_PROPERTY:runners_yaml_props_target,yaml_contents>) 135endfunction() 136 137get_property(RUNNERS GLOBAL PROPERTY ZEPHYR_RUNNERS) 138 139# Persist the runner-related state. 140# 141# Available runners and their arguments are configured in board.cmake 142# files. 143# 144# Everything is marked with FORCE so that re-running CMake updates the 145# configuration if the board files change. 146if(RUNNERS) 147 create_runners_yaml(${RUNNERS}) 148endif() 149 150zephyr_get(WEST_DIR) 151if(WEST_DIR) 152 set(WEST "PYTHONPATH=${WEST_DIR}/src" "${PYTHON_EXECUTABLE};${WEST_DIR}/src/west/app/main.py;--zephyr-base=${ZEPHYR_BASE} ") 153endif() 154 155# Generate the flash, debug, debugserver, attach targets within the build 156# system itself. 157foreach(target flash debug debugserver attach rtt) 158 if(target STREQUAL flash) 159 set(comment "Flashing ${BOARD}") 160 elseif(target STREQUAL debug) 161 set(comment "Debugging ${BOARD}") 162 elseif(target STREQUAL debugserver) 163 set(comment "Debugging ${BOARD}") 164 if(SUPPORTED_EMU_PLATFORMS) 165 # cmake/qemu/CMakeLists.txt will add a debugserver target for 166 # emulation platforms, so we don't add one here 167 continue() 168 endif() 169 elseif(target STREQUAL attach) 170 set(comment "Debugging ${BOARD}") 171 elseif(target STREQUAL rtt) 172 set(comment "RTT ${BOARD}") 173 endif() 174 string(TOUPPER ${target} TARGET_UPPER) 175 176 list(APPEND RUNNERS_DEPS ${logical_target_for_zephyr_elf}) 177 178 # Enable verbose output, if requested. 179 if(CMAKE_VERBOSE_MAKEFILE) 180 set(RUNNER_VERBOSE "--verbose") 181 else() 182 set(RUNNER_VERBOSE) 183 endif() 184 185 if(WEST) 186 add_custom_target(${target} 187 # This script will print an error message and fail if <target> has added 188 # dependencies. This is done using dedicated CMake script, as 189 # `cmake -E {true|false}` is not available until CMake 3.16. 190 COMMAND ${CMAKE_COMMAND} 191 -DTARGET=${target} 192 -DDEPENDENCIES="$<TARGET_PROPERTY:${target},MANUALLY_ADDED_DEPENDENCIES>" 193 -P ${CMAKE_CURRENT_LIST_DIR}/check_runner_dependencies.cmake 194 COMMAND 195 ${CMAKE_COMMAND} -E env 196 ${WEST} 197 ${RUNNER_VERBOSE} 198 ${target} 199 WORKING_DIRECTORY 200 ${APPLICATION_BINARY_DIR} 201 COMMENT 202 ${comment} 203 USES_TERMINAL 204 ) 205 else() 206 add_custom_target(${target} 207 COMMAND ${CMAKE_COMMAND} -E echo \"West was not found in path. To support 208 '${CMAKE_MAKE_PROGRAM} ${target}', please create a west workspace.\" 209 USES_TERMINAL 210 ) 211 endif(WEST) 212endforeach() 213