blob: d066cf8b15af8a2c43672e91a41f404ba90086f5 [file]
# 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,
)