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 16def pw_facade(name, srcs = None, backend = None, **kwargs): 17 """Create a cc_library with a facade. 18 19 This macro simplifies instantiating Pigweed's facade pattern. It generates 20 two targets: 21 22 * cc_library with the label "name". This is the complete library target. 23 Users of the functionality provided by this library should depend on this 24 target. It has a public dependency on the "backend". 25 * cc_library with the label "name.facade". This library exposes only the 26 headers. Implementations of the backend should depend on it. 27 28 Args: 29 name: The name of the cc_library. 30 srcs: The source files of the cc_library. 31 backend: The backend for the facade. This should be a label_flag or other 32 target that allows swapping out the backend implementation at build 33 time. (In a downstream project an alias with an "actual = select(...)" 34 attribute may also be appropriate, but in upstream Pigweed use only a 35 label_flag.). 36 **kwargs: Passed on to cc_library. 37 """ 38 if type(backend) != "string": 39 fail( 40 "The 'backend' attribute must be a single label, " + 41 "got {} of type {}".format(backend, type(backend)), 42 ) 43 44 facade_kwargs = dict(**kwargs) 45 46 # This is a workaround for layering_check, which appears to only allow 47 # two libraries to export the same headers if one lists it as textual_hdrs 48 # for unclear reasons (b/142314377#comment11). 49 facade_kwargs["textual_hdrs"] = facade_kwargs.pop("hdrs", []) 50 51 # TODO: https://github.com/bazelbuild/bazel/issues/12424 - Unfortunately, 52 # strip_include_prefix does not work correctly with textual_hdrs. 53 if "strip_include_prefix" in facade_kwargs: 54 facade_kwargs["includes"] = [facade_kwargs["strip_include_prefix"]] 55 56 # A facade has no srcs, so it can only have public deps. Don't specify any 57 # implementation_deps on the facade target. 58 facade_kwargs.pop("implementation_deps", []) 59 native.cc_library( 60 name = name + ".facade", 61 **facade_kwargs 62 ) 63 64 kwargs["deps"] = kwargs.get("deps", []) + [backend] 65 native.cc_library( 66 name = name, 67 srcs = srcs, 68 **kwargs 69 ) 70