blob: c0104760ed2bdf5b674e6deed7b35a030d8aea27 [file] [edit]
# 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.
"""Public API for Zephyr Sysbuild in Bazel."""
load("@zephyr_index//:index.bzl", "SYSBUILD_METADATA")
load("//bazel/private:transition_rule.bzl", "transitioned_dep")
def zephyr_sysbuild(name, main, **kwargs):
"""Defines a multi-image Sysbuild target.
Args:
name: Target name.
main: Label of the main Zephyr application.
**kwargs: Additional arguments passed to the underlying rule.
"""
# Normalize main label to match index keys
norm_main = str(main).split(":")[0]
if "//" in norm_main:
norm_main = norm_main.split("//")[-1]
norm_main = norm_main.strip("/").lstrip(":")
metadata = SYSBUILD_METADATA.get(norm_main, {"helpers": {}, "board_helpers": {}})
global_helpers = metadata.get("helpers", {})
board_helpers = metadata.get("board_helpers", {})
# Instantiate targets for all possible helpers
all_helpers_targets = {}
# Helper for global helpers
for helper_name, helper_config in global_helpers.items():
helper_target = helper_config.get("target")
if not helper_target:
continue
platform = helper_config.get("platform")
if platform:
t_name = "%s_helper_%s" % (name, helper_name)
transitioned_dep(
name = t_name,
dep = helper_target,
platform = platform,
)
all_helpers_targets[helper_name] = ":" + t_name
else:
all_helpers_targets[helper_name] = helper_target
# Helper for board-specific helpers
for board_id, helpers in board_helpers.items():
for helper_name, helper_config in helpers.items():
helper_target = helper_config.get("target")
if not helper_target:
continue
platform = helper_config.get("platform")
t_name = "%s_helper_%s_%s" % (name, helper_name, sanitize_board_id(board_id))
if not platform:
platform = "@zephyr//boards:%s" % board_id
transitioned_dep(
name = t_name,
dep = helper_target,
platform = platform,
)
all_helpers_targets["%s:%s" % (board_id, helper_name)] = ":" + t_name
# Build select() dictionary
select_dict = {}
# Global helpers are always included
base_helpers = []
for helper_name in global_helpers.keys():
target = all_helpers_targets.get(helper_name)
if target:
base_helpers.append(target)
select_dict["//conditions:default"] = base_helpers
# Add board-specific helpers
for board_id, helpers in board_helpers.items():
board_condition = "@zephyr_kconfig//:CONFIG_BOARD_%s=true" % board_id.upper()
current_board_helpers = list(base_helpers)
for helper_name in helpers.keys():
target = all_helpers_targets.get("%s:%s" % (board_id, helper_name))
if target:
current_board_helpers.append(target)
select_dict[board_condition] = current_board_helpers
# Instantiate the underlying rule
_zephyr_sysbuild_rule(
name = name,
main = main,
helpers = select(select_dict),
**kwargs
)
def sanitize_board_id(board_id):
return board_id.replace("/", "_").replace("-", "_").replace(".", "_")
def _zephyr_sysbuild_rule_impl(ctx):
all_files = []
all_files.extend(ctx.attr.main[DefaultInfo].files.to_list())
for helper in ctx.attr.helpers:
all_files.extend(helper[DefaultInfo].files.to_list())
return [DefaultInfo(files = depset(all_files))]
_zephyr_sysbuild_rule = rule(
implementation = _zephyr_sysbuild_rule_impl,
attrs = {
"main": attr.label(mandatory = True),
"helpers": attr.label_list(),
},
)