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  if(CONFIG_BUILD_OUTPUT_MOT)
64    get_runners_prop(mot_file mot "${KERNEL_MOT_NAME}")
65    runners_yaml_append("  mot_file: ${mot}")
66  endif()
67
68  zephyr_get(OPENOCD)
69  zephyr_get(OPENOCD_DEFAULT_PATH)
70  if(CMAKE_GDB OR OPENOCD OR OPENOCD_DEFAULT_PATH)
71    runners_yaml_append("  # Host tools:")
72  endif()
73  if(CMAKE_GDB)
74    runners_yaml_append("  gdb: ${CMAKE_GDB}")
75  endif()
76  if(OPENOCD)
77    runners_yaml_append("  openocd: ${OPENOCD}")
78    runners_yaml_append("  openocd_search:")
79    if(OPENOCD_DEFAULT_PATH)
80      runners_yaml_append("    - ${OPENOCD_DEFAULT_PATH}")
81    endif()
82  endif()
83  runners_yaml_append("")
84endfunction()
85
86# Save runner state in a YAML file.
87function(create_runners_yaml)
88  set(runners ${ARGV})
89
90  set(runners_yaml "${PROJECT_BINARY_DIR}/runners.yaml")
91
92  runners_yaml_append("# Available runners configured by board.cmake.\nrunners:")
93  foreach(runner ${runners})
94    runners_yaml_append("- ${runner}")
95  endforeach()
96
97  if(DEFINED BOARD_FLASH_RUNNER)
98    runners_yaml_append("\n# Default flash runner if --runner is not given.")
99    runners_yaml_append("flash-runner: ${BOARD_FLASH_RUNNER}")
100  endif()
101  if(DEFINED BOARD_DEBUG_RUNNER)
102    runners_yaml_append("\n# Default debug runner if --runner is not given.")
103    runners_yaml_append("debug-runner: ${BOARD_DEBUG_RUNNER}")
104  endif()
105  if(DEFINED BOARD_SIM_RUNNER)
106    runners_yaml_append("\n# Default simulation runner if --runner is not given.")
107    runners_yaml_append("sim-runner: ${BOARD_SIM_RUNNER}")
108  endif()
109  if(DEFINED BOARD_ROBOT_RUNNER)
110    runners_yaml_append("\n# Default test runner if --runner is not given.")
111    runners_yaml_append("robot-runner: ${BOARD_ROBOT_RUNNER}")
112  endif()
113
114  # Sets up common runner configuration values.
115  runners_yaml_append_config()
116
117  # Get runner-specific arguments set in the board files.
118  runners_yaml_append("# Runner specific arguments")
119  runners_yaml_append("args:")
120  foreach(runner ${runners})
121    string(MAKE_C_IDENTIFIER ${runner} runner_id)
122    runners_yaml_append("  ${runner}:")
123    get_property(args GLOBAL PROPERTY "BOARD_RUNNER_ARGS_${runner_id}")
124    if(args)
125      # Usually, the runner has arguments. Append them to runners.yaml,
126      # one per line.
127      foreach(arg ${args})
128        runners_yaml_append("    - ${arg}")
129      endforeach()
130    else()
131      # If the runner doesn't need any arguments, just use an empty list.
132      runners_yaml_append("    []\n")
133    endif()
134  endforeach()
135
136  # Write the final contents.
137  file(GENERATE OUTPUT "${runners_yaml}" CONTENT
138    $<TARGET_PROPERTY:runners_yaml_props_target,yaml_contents>)
139endfunction()
140
141get_property(RUNNERS GLOBAL PROPERTY ZEPHYR_RUNNERS)
142
143# Persist the runner-related state.
144#
145# Available runners and their arguments are configured in board.cmake
146# files.
147#
148# Everything is marked with FORCE so that re-running CMake updates the
149# configuration if the board files change.
150if(RUNNERS)
151  create_runners_yaml(${RUNNERS})
152endif()
153
154zephyr_get(WEST_DIR)
155if(WEST_DIR)
156  set(WEST "PYTHONPATH=${WEST_DIR}/src" "${PYTHON_EXECUTABLE};${WEST_DIR}/src/west/app/main.py;--zephyr-base=${ZEPHYR_BASE} ")
157endif()
158
159# Generate the flash, debug, debugserver, attach targets within the build
160# system itself.
161foreach(target flash debug debugserver attach rtt)
162  if(target STREQUAL flash)
163    set(comment "Flashing ${BOARD}")
164  elseif(target STREQUAL debug)
165    set(comment "Debugging ${BOARD}")
166  elseif(target STREQUAL debugserver)
167    set(comment "Debugging ${BOARD}")
168    if(SUPPORTED_EMU_PLATFORMS)
169      # cmake/qemu/CMakeLists.txt will add a debugserver target for
170      # emulation platforms, so we don't add one here
171      continue()
172    endif()
173  elseif(target STREQUAL attach)
174    set(comment "Debugging ${BOARD}")
175  elseif(target STREQUAL rtt)
176    set(comment "RTT ${BOARD}")
177  endif()
178  string(TOUPPER ${target} TARGET_UPPER)
179
180  list(APPEND RUNNERS_DEPS ${logical_target_for_zephyr_elf})
181
182  # Enable verbose output, if requested.
183  if(CMAKE_VERBOSE_MAKEFILE)
184    set(RUNNER_VERBOSE "--verbose")
185  else()
186    set(RUNNER_VERBOSE)
187  endif()
188
189  if(WEST)
190    add_custom_target(${target}
191      cmake -E echo "WARNING: CMake ${target} target is deprecated, call west directly instead"
192      # This script will print an error message and fail if <target> has added
193      # dependencies. This is done using dedicated CMake script, as
194      # `cmake -E {true|false}` is not available until CMake 3.16.
195      COMMAND ${CMAKE_COMMAND}
196        -DTARGET=${target}
197        -DDEPENDENCIES="$<TARGET_PROPERTY:${target},MANUALLY_ADDED_DEPENDENCIES>"
198        -P ${CMAKE_CURRENT_LIST_DIR}/check_runner_dependencies.cmake
199      COMMAND
200        ${CMAKE_COMMAND} -E env ZEPHYR_BASE=${ZEPHYR_BASE}
201        ${WEST}
202        ${RUNNER_VERBOSE}
203        ${target}
204      WORKING_DIRECTORY
205        ${APPLICATION_BINARY_DIR}
206      COMMENT
207        ${comment}
208      USES_TERMINAL
209    )
210  else()
211    add_custom_target(${target}
212      COMMAND ${CMAKE_COMMAND} -E echo \"West was not found in path. To support
213          '${CMAKE_MAKE_PROGRAM} ${target}', please create a west workspace.\"
214      USES_TERMINAL
215      )
216  endif(WEST)
217endforeach()
218