| # Copyright 2026 The Pigweed Authors |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| # use this file except in compliance with the License. You may obtain a copy of |
| # the License at |
| # |
| # https://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| # License for the specific language governing permissions and limitations under |
| # the License. |
| |
| """Rules and providers for Zephyr hardware runners configuration.""" |
| |
| load("@zephyr-bazel//bazel:runfiles.bzl", "resolve_runfiles_path") |
| load("@zephyr-bazel//bazel/private:zephyr_transition.bzl", "zephyr_transition") |
| |
| ZephyrRunnerConfigInfo = provider( |
| doc = "Carries configuration for Zephyr hardware runners.", |
| fields = { |
| "runner": "The name of the runner (e.g. jlink, openocd).", |
| "args": "List of arguments for the runner.", |
| "board_dir": "The directory of the board.", |
| "runner_source": "Optional Python file implementing the runner.", |
| "tools": "Depset or list of tool targets required by the runner.", |
| }, |
| ) |
| |
| def _zephyr_runner_config_impl(ctx): |
| # Retrieve the package path of the board. |
| # For OOT boards in the main workspace, this will be the package path. |
| # For in-tree boards, it will be the package path in the @zephyr repo. |
| board_dir = ctx.label.package |
| return [ |
| ZephyrRunnerConfigInfo( |
| runner = ctx.attr.runner, |
| args = ctx.attr.args, |
| board_dir = board_dir, |
| runner_source = ctx.file.runner_source, |
| tools = ctx.attr.tools, |
| ), |
| ] |
| |
| zephyr_runner_config = rule( |
| implementation = _zephyr_runner_config_impl, |
| doc = "Defines the hardware runner configuration for a board.", |
| attrs = { |
| "runner": attr.string(mandatory = True, doc = "The name of the runner (e.g. jlink, openocd)."), |
| "args": attr.string_list(doc = "Default list of arguments for the runner."), |
| "runner_source": attr.label(allow_single_file = [".py"], doc = "Optional Python file implementing the runner."), |
| "tools": attr.label_list(cfg = "exec", doc = "Tools required by the runner (e.g. @openocd//:all)"), |
| }, |
| ) |
| |
| def _zephyr_runners_yaml_impl(ctx): |
| config_info = ctx.attr.runner_config[ZephyrRunnerConfigInfo] |
| runner = config_info.runner |
| runner_source = getattr(config_info, "runner_source", None) |
| |
| content = [] |
| content.append("config:") |
| content.append(" board_dir: %s" % config_info.board_dir) |
| content.append(" elf_file: %s" % resolve_runfiles_path(ctx, ctx.file.elf)) |
| if ctx.file.hex: |
| content.append(" hex_file: %s" % resolve_runfiles_path(ctx, ctx.file.hex)) |
| if ctx.file.bin: |
| content.append(" bin_file: %s" % resolve_runfiles_path(ctx, ctx.file.bin)) |
| if runner_source: |
| content.append(" runner_source: %s" % resolve_runfiles_path(ctx, runner_source)) |
| |
| content.append("runners:") |
| if runner: |
| content.append(" - %s" % runner) |
| content.append("flash-runner: %s" % runner) |
| |
| content.append("args:") |
| if runner: |
| content.append(" %s:" % runner) |
| for arg in config_info.args: |
| content.append(" - %s" % arg) |
| |
| out_file = ctx.actions.declare_file(ctx.label.name + ".yaml") |
| ctx.actions.write(out_file, "\n".join(content) + "\n") |
| |
| runfiles_files = [ctx.file.elf] |
| if ctx.file.hex: |
| runfiles_files.append(ctx.file.hex) |
| if ctx.file.bin: |
| runfiles_files.append(ctx.file.bin) |
| if runner_source: |
| runfiles_files.append(runner_source) |
| |
| tool_runfiles = [] |
| tools = getattr(config_info, "tools", []) |
| for tool in tools: |
| if DefaultInfo in tool: |
| tool_runfiles.append(tool[DefaultInfo].default_runfiles) |
| tool_runfiles.append(ctx.runfiles(transitive_files = tool[DefaultInfo].files)) |
| |
| runfiles = ctx.runfiles(files = runfiles_files) |
| if tool_runfiles: |
| runfiles = runfiles.merge_all(tool_runfiles) |
| |
| return [ |
| DefaultInfo( |
| files = depset([out_file]), |
| runfiles = runfiles, |
| ), |
| ] |
| |
| zephyr_runners_yaml = rule( |
| implementation = _zephyr_runners_yaml_impl, |
| doc = "Generates a runners.yaml file for flashing and debugging.", |
| attrs = { |
| "runner_config": attr.label( |
| mandatory = True, |
| providers = [ZephyrRunnerConfigInfo], |
| doc = "The runner configuration to use.", |
| ), |
| "elf": attr.label( |
| mandatory = True, |
| allow_single_file = True, |
| doc = "The ELF binary to flash.", |
| ), |
| "hex": attr.label( |
| allow_single_file = True, |
| doc = "Optional HEX file to flash.", |
| ), |
| "bin": attr.label( |
| allow_single_file = True, |
| doc = "Optional BIN file to flash.", |
| ), |
| "app_label": attr.string( |
| mandatory = True, |
| doc = "The label of the application target.", |
| ), |
| "_allowlist_function_transition": attr.label( |
| default = "@bazel_tools//tools/allowlists/function_transition_allowlist", |
| doc = "Allowlist for function transitions.", |
| ), |
| }, |
| cfg = zephyr_transition, |
| ) |