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_HEX)
40    get_runners_prop(hex_file hex "${KERNEL_HEX_NAME}")
41    runners_yaml_append("  hex_file: ${hex}")
42  endif()
43  if(CONFIG_BUILD_OUTPUT_BIN)
44    get_runners_prop(bin_file bin "${KERNEL_BIN_NAME}")
45    runners_yaml_append("  bin_file: ${bin}")
46  endif()
47
48  if(CMAKE_GDB OR OPENOCD OR OPENOCD_DEFAULT_PATH)
49    runners_yaml_append("  # Host tools:")
50  endif()
51  if(CMAKE_GDB)
52    runners_yaml_append("  gdb: ${CMAKE_GDB}")
53  endif()
54  if(OPENOCD)
55    runners_yaml_append("  openocd: ${OPENOCD}")
56    runners_yaml_append("  openocd_search:")
57    if(OPENOCD_DEFAULT_PATH)
58      runners_yaml_append("    - ${OPENOCD_DEFAULT_PATH}")
59    endif()
60  endif()
61  runners_yaml_append("")
62endfunction()
63
64# Save runner state in a YAML file, and put that YAML file's location
65# in the cache.
66function(create_runners_yaml)
67  set(runners ${ARGV})
68
69  set(runners_yaml "${PROJECT_BINARY_DIR}/runners.yaml")
70
71  runners_yaml_append("# Available runners configured by board.cmake.\nrunners:")
72  foreach(runner ${runners})
73    runners_yaml_append("- ${runner}")
74  endforeach()
75
76  if(DEFINED BOARD_FLASH_RUNNER)
77    runners_yaml_append("\n# Default flash runner if --runner is not given.")
78    runners_yaml_append("flash-runner: ${BOARD_FLASH_RUNNER}")
79  endif()
80  if(DEFINED BOARD_DEBUG_RUNNER)
81    runners_yaml_append("\n# Default debug runner if --runner is not given.")
82    runners_yaml_append("debug-runner: ${BOARD_DEBUG_RUNNER}")
83  endif()
84
85  # Sets up common runner configuration values.
86  runners_yaml_append_config()
87
88  # Get runner-specific arguments set in the board files.
89  runners_yaml_append("# Runner specific arguments")
90  runners_yaml_append("args:")
91  foreach(runner ${runners})
92    string(MAKE_C_IDENTIFIER ${runner} runner_id)
93    runners_yaml_append("  ${runner}:")
94    get_property(args GLOBAL PROPERTY "BOARD_RUNNER_ARGS_${runner_id}")
95    if(args)
96      # Usually, the runner has arguments. Append them to runners.yaml,
97      # one per line.
98      foreach(arg ${args})
99        runners_yaml_append("    - ${arg}")
100      endforeach()
101    else()
102      # If the runner doesn't need any arguments, just use an empty list.
103      runners_yaml_append("    []\n")
104    endif()
105  endforeach()
106
107  # Write the final contents and set its location in the cache.
108  file(GENERATE OUTPUT "${runners_yaml}" CONTENT
109    $<TARGET_PROPERTY:runners_yaml_props_target,yaml_contents>)
110  set(ZEPHYR_RUNNERS_YAML "${runners_yaml}" CACHE INTERNAL
111    "a configuration file for the runners Python package")
112endfunction()
113
114get_property(RUNNERS GLOBAL PROPERTY ZEPHYR_RUNNERS)
115
116# Persist the runner-related state.
117#
118# Available runners and their arguments are configured in board.cmake
119# files.
120#
121# Everything is marked with FORCE so that re-running CMake updates the
122# configuration if the board files change.
123if(RUNNERS)
124  create_runners_yaml(${RUNNERS})
125endif()
126
127if(DEFINED ENV{WEST_DIR} AND NOT WEST_DIR)
128  set(WEST_DIR $ENV{WEST_DIR})
129endif(DEFINED ENV{WEST_DIR} AND NOT WEST_DIR)
130
131if(WEST_DIR)
132  set(WEST "PYTHONPATH=${WEST_DIR}/src" "${PYTHON_EXECUTABLE};${WEST_DIR}/src/west/app/main.py;--zephyr-base=${ZEPHYR_BASE} ")
133endif()
134
135# Generate the flash, debug, debugserver, attach targets within the build
136# system itself.
137foreach(target flash debug debugserver attach)
138  if(target STREQUAL flash)
139    set(comment "Flashing ${BOARD}")
140  elseif(target STREQUAL debug)
141    set(comment "Debugging ${BOARD}")
142  elseif(target STREQUAL debugserver)
143    set(comment "Debugging ${BOARD}")
144    if(EMU_PLATFORM)
145      # cmake/qemu/CMakeLists.txt will add a debugserver target for
146      # emulation platforms, so we don't add one here
147      continue()
148    endif()
149  elseif(target STREQUAL attach)
150    set(comment "Debugging ${BOARD}")
151  endif()
152  string(TOUPPER ${target} TARGET_UPPER)
153
154  list(APPEND RUNNERS_DEPS ${logical_target_for_zephyr_elf})
155
156  # Enable verbose output, if requested.
157  if(CMAKE_VERBOSE_MAKEFILE)
158    set(RUNNER_VERBOSE "--verbose")
159  else()
160    set(RUNNER_VERBOSE)
161  endif()
162
163  if(WEST)
164    add_custom_target(${target}
165      # This script will print an error message and fail if <target> has added
166      # dependencies. This is done using dedicated CMake script, as
167      # `cmake -E {true|false}` is not available until CMake 3.16.
168      COMMAND ${CMAKE_COMMAND}
169        -DTARGET=${target}
170        -DDEPENDENCIES="$<TARGET_PROPERTY:${target},MANUALLY_ADDED_DEPENDENCIES>"
171        -P ${CMAKE_CURRENT_LIST_DIR}/check_runner_dependencies.cmake
172      COMMAND
173        ${CMAKE_COMMAND} -E env
174        ${WEST}
175        ${RUNNER_VERBOSE}
176        ${target}
177      WORKING_DIRECTORY
178        ${APPLICATION_BINARY_DIR}
179      COMMENT
180        ${comment}
181      USES_TERMINAL
182    )
183  else()
184    add_custom_target(${target}
185      COMMAND ${CMAKE_COMMAND} -E echo \"West was not found in path. To support
186          '${CMAKE_MAKE_PROGRAM} ${target}', please create a west workspace.\"
187      USES_TERMINAL
188      )
189  endif(WEST)
190endforeach()
191