blob: 9075b2705ffae2c93ac9a30c988334705443d7d4 [file] [log] [blame] [edit]
# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
"""Rules for defining cross-platform libraries."""
def dual_inputs(shared = [], device = [], host = []):
"""Constructs a cross-platform input for use with dual_cc_library."""
return struct(shared = shared, device = device, host = host)
def dual_cc_device_library_of(label):
"""
Given the label of a dual_cc_library, returns the label for the
on-device library. This library is private to the Bazel package that
defines it.
"""
return "{}_on_device_do_not_use_directly".format(label)
def _merge_and_split_inputs(inputs):
inputs = inputs if type(inputs) != "list" else dual_inputs(shared = inputs)
return inputs.shared + inputs.device, inputs.shared + inputs.host
def dual_cc_library(
name,
on_device_config_setting = "//rules:opentitan_platform",
srcs = [],
hdrs = [],
deps = [],
target_compatible_with = [],
**kwargs):
"""
Defines a cc_library whose contents are dependent on whether it is
depended on in an on-device or on-host setting.
The macro takes the same arguments as cc_library, but has special
behavior for `hdrs`, `srcs`, and `deps`, which may either be a list of
labels that would usually be inputs to a cc_library, or a dual_inputs object.
The later case allows inputs to be designated as being shared, on-device-only,
or off-device-only.
This rule only needs to be used when the sources for on-device are different
from on-host, such as for mockable interfaces. In this case, the on-device
library may still be used on-host via `dual_cc_device_library_of`, and it will
use the host-side versions of its dependencies. This is useful for testing
the on-device version using mocked dependencies.
Args:
@param name: The name of this rule.
@param on_device_config_setting: A config_setting rule for determining what
"on device" means.
@param srcs: `cc_library()` sources; may be a list or a `dual_inputs()`.
@param hdrs: `cc_library()` headers; may be a list or a `dual_inputs()`.
@param deps: `cc_library()` dependencies; may be a list or a `dual_inputs()`.
@param **kwargs: Arguments to forward to each `cc_library()`.
Emits rules:
cc_library named: dual_cc_device_library_of(<name>)
cc_library named: <unspecified> # Host-only library.
alias named: <name>
"""
hdrs_d, hdrs_h = _merge_and_split_inputs(hdrs)
srcs_d, srcs_h = _merge_and_split_inputs(srcs)
deps_d, deps_h = _merge_and_split_inputs(deps)
tgts_d, tgts_h = _merge_and_split_inputs(target_compatible_with)
native.cc_library(
name = dual_cc_device_library_of(name),
hdrs = hdrs_d,
srcs = srcs_d,
deps = deps_d,
target_compatible_with = tgts_d,
visibility = ["//visibility:private"],
**kwargs
)
off_device_name = "{}_on_host_do_not_use_directly".format(name)
native.cc_library(
name = off_device_name,
hdrs = hdrs_h,
srcs = srcs_h,
deps = deps_h,
target_compatible_with = tgts_h,
visibility = ["//visibility:private"],
**kwargs
)
native.alias(
name = name,
actual = select({
"//rules:host_platform": off_device_name,
"//conditions:default": dual_cc_device_library_of(name),
}),
)