Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / third_party / pigweed / repo / pw_build / facade.gni
1 # Copyright 2019 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
15 import("//build_overrides/pigweed.gni")
16
17 import("$dir_pw_build/python_action.gni")
18 import("$dir_pw_build/target_types.gni")
19
20 # Declare a facade.
21 #
22 # A Pigweed facade is an API layer that has a single implementation it must
23 # link against. Typically this will be done by pointing a build arg like
24 # `pw_[module]_BACKEND` at a backend implementation for that module.
25 #
26 # pw_facade creates two targets:
27 #
28 #   $target_name: The public-facing pw_source_set that provides the API and
29 #     implementation (backend). Users of the facade should depend on this.
30 #   $target_name.facade: A private source_set that provides ONLY the API. ONLY
31 #     backends should depend on this.
32 #
33 # If the target name matches the directory name (e.g. //foo:foo), a ":facade"
34 # alias of the facade target (e.g. //foo:facade) is also provided. This avoids
35 # the need to repeat the directory name, for consistency with the main target.
36 #
37 # The facade's headers are split out into the *.facade target to avoid circular
38 # dependencies. Here's a concrete example to illustrate why this is needed:
39 #
40 #   foo_BACKEND = "//foo:foo_backend_bar"
41 #
42 #   pw_facade("foo") {
43 #     backend = foo_BACKEND
44 #     public = [ "foo.h" ]
45 #     sources = [ "foo.cc" ]
46 #   }
47 #
48 #   pw_source_set("foo_backend_bar") {
49 #     deps = [ ":foo.facade" ]
50 #     sources = [ "bar.cc" ]
51 #   }
52 #
53 # This creates the following dependency graph:
54 #
55 #   foo.facade  <-.
56 #    ^             \
57 #    |              \
58 #    |               \
59 #   foo  ---------->  foo_backend_bar
60 #
61 # This allows foo_backend_bar to include "foo.h". If you tried to directly
62 # depend on `foo` from `foo_backend_bar`, you'd get a dependency cycle error in
63 # GN.
64 #
65 # Accepts the standard pw_source_set args with the following additions:
66 #
67 # Args:
68 #  backend: (required) The dependency that implements this facade (a GN
69 #    variable)
70 #  public: (required) The headers exposed by this facade. A facade acts as a
71 #    tool to break dependency cycles that come from the backend trying to
72 #    include headers from the facade itself. If the facade doesn't expose any
73 #    headers, it's basically the same as just depending directly on the build
74 #    arg that `backend` is set to.
75 #
76 template("pw_facade") {
77   assert(defined(invoker.backend),
78          "pw_facade requires a reference to a backend variable for the facade")
79   assert(defined(invoker.public),
80          "If your facade does not explicitly expose an API that a backend " +
81              "must depend on, you can just directly depend on the build arg " +
82              "that the `backend` template argument would have been set to.")
83
84   _facade_name = "$target_name.facade"
85
86   if (get_path_info(get_label_info(":$target_name", "dir"), "name") ==
87       get_label_info(":$target_name", "name")) {
88     group("facade") {
89       public_deps = [ ":$_facade_name" ]
90     }
91   }
92
93   _facade_vars = [
94     "public_configs",
95     "public_deps",
96     "public",
97   ]
98   pw_source_set(_facade_name) {
99     forward_variables_from(invoker, _facade_vars)
100   }
101
102   if (invoker.backend == "") {
103     # If backend is not set to anything, create a script that emits an error.
104     # This will be added as a data dependency to the actual target, so that
105     # attempting to build the facade without a backend fails with a relevant
106     # error message.
107     _main_target_name = target_name
108
109     pw_python_action(_main_target_name + ".NO_BACKEND_SET") {
110       stamp = true
111       script = "$dir_pw_build/py/pw_build/null_backend.py"
112       args = [ _main_target_name ]
113       not_needed(invoker, "*")
114     }
115   }
116
117   # Create a target that defines the main facade library. Always emit this
118   # target, even if the backend isn't defined, so that the dependency graph is
119   # correctly expressed for gn check.
120   pw_source_set(target_name) {
121     # The main library contains everything else specified in the template.
122     _ignore_vars = [ "backend" ] + _facade_vars
123     forward_variables_from(invoker, "*", _ignore_vars)
124
125     public_deps = [ ":$_facade_name" ]
126
127     # If the backend is set, inject it as a dependency.
128     if (invoker.backend != "") {
129       public_deps += [ invoker.backend ]
130     } else {
131       # If the backend is not set, depend on the *.NO_BACKEND_SET target.
132       public_deps += [ ":$_main_target_name" + ".NO_BACKEND_SET" ]
133     }
134   }
135 }