• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2024 The Pigweed Authors
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may not
4# use this file except in compliance with the License. You may obtain a copy of
5# the License at
6#
7#     https://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations under
13# the License.
14"""Bazel rules for declaring Pigweed facade interface layers."""
15
16load("@rules_cc//cc:cc_library.bzl", "cc_library")
17
18def pw_facade(name, srcs = None, backend = None, **kwargs):
19    """Create a cc_library with a facade.
20
21    This macro simplifies instantiating Pigweed's facade pattern. It generates
22    two targets:
23
24    * cc_library with the label "name". This is the complete library target.
25      Users of the functionality provided by this library should depend on this
26      target.  It has a public dependency on the "backend".
27    * cc_library with the label "name.facade". This library exposes only the
28      headers. Implementations of the backend should depend on it.
29
30    Args:
31      name: The name of the cc_library.
32      srcs: The source files of the cc_library.
33      backend: The backend for the facade. This should be a label_flag or other
34        target that allows swapping out the backend implementation at build
35        time. (In a downstream project an alias with an "actual = select(...)"
36        attribute may also be appropriate, but in upstream Pigweed use only a
37        label_flag.).
38      **kwargs: Passed on to cc_library.
39    """
40    if type(backend) != "string":
41        fail(
42            "The 'backend' attribute must be a single label, " +
43            "got {} of type {}".format(backend, type(backend)),
44        )
45
46    facade_kwargs = dict(**kwargs)
47
48    # A facade has no srcs, so it can only have public deps. Don't specify any
49    # implementation_deps on the facade target.
50    facade_kwargs.pop("implementation_deps", [])
51    cc_library(
52        name = name + ".facade",
53        # The .facade target is not self-contained (it's missing a dependency
54        # on the backend headers), so it can't be successfully clang-tidied.
55        # "no-clang-tidy-headers" is a special tag defined in bazel_clang_tidy
56        # that exempts a build target's headers from tidying; see
57        # https://github.com/erenon/bazel_clang_tidy/pull/76.
58        tags = facade_kwargs.pop("tags", []) + ["no-clang-tidy-headers"],
59        **facade_kwargs
60    )
61
62    kwargs["deps"] = kwargs.get("deps", []) + [backend]
63    cc_library(
64        name = name,
65        srcs = srcs,
66        **kwargs
67    )
68