| # Copyright 2019 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. |
| # gn-format disable |
| import("//build_overrides/pigweed.gni") |
| |
| import("$dir_pw_build/python_script.gni") |
| import("$dir_pw_build/target_types.gni") |
| |
| # Declare a facade. |
| # |
| # A Pigweed facade is an API layer that has a single implementation it must |
| # link against. Typically this will be done by pointing a build arg like |
| # `pw_[module]_BACKEND` at a backend implementation for that module. |
| # |
| # Example facade: |
| # |
| # pw_facade("module_name") { |
| # backend = dir_module_name_backend |
| # public_deps = [ |
| # ":module_api_layer" |
| # ] |
| # } |
| # |
| # Args: |
| # - backend: the dependency that implements this facade |
| # - facade_name: (optional) The name to use for the facade target on which the |
| # backend depends. Only required when a module defines multiple facades. |
| # Defaults to "facade". |
| # |
| template("pw_facade") { |
| assert(defined(invoker.backend), |
| "pw_facade requires a reference to a backend variable for the facade") |
| |
| if (defined(invoker.facade_name)) { |
| _facade_name = invoker.facade_name |
| } else { |
| _facade_name = "facade" |
| } |
| |
| # A facade's headers are split into a separate target to avoid a circular |
| # dependency between the facade and the backend. |
| # |
| # For example, the following targets: |
| # |
| # foo_backend = "//foo:foo_backend_bar" |
| # |
| # pw_facade("foo") { |
| # backend = foo_backend |
| # public = [ "foo.h" ] |
| # sources = [ "foo.cc" ] |
| # } |
| # |
| # pw_source_set("foo_backend_bar") { |
| # deps = [ ":facade" ] |
| # sources = [ "bar.cc" ] |
| # } |
| # |
| # Create the following dependency graph: |
| # |
| # facade <-. |
| # ^ \ |
| # | \ |
| # | \ |
| # foo ------> foo_backend_bar |
| # |
| _facade_vars = [ |
| "public_configs", |
| "public_deps", |
| "public", |
| ] |
| pw_source_set(_facade_name) { |
| forward_variables_from(invoker, _facade_vars) |
| } |
| |
| if (invoker.backend == "") { |
| # If backend is not set to anything, create a script that emits an error. |
| # This will be added as a data dependency to the actual target, so that |
| # attempting to build the facade without a backend fails with a relevant |
| # error message. |
| _main_target_name = target_name |
| |
| pw_python_script(_main_target_name + "_NO_BACKEND_SET") { |
| stamp = true |
| script = "$dir_pw_build/py/pw_build/null_backend.py" |
| args = [ _main_target_name ] |
| not_needed(invoker, "*") |
| } |
| } |
| |
| # Create a target that defines the main facade library. Always emit this |
| # target, even if the backend isn't defined, so that the dependency graph is |
| # correctly expressed for gn check. |
| pw_source_set(target_name) { |
| # The main library contains everything else specified in the template. |
| _ignore_vars = [ "backend" ] + _facade_vars |
| forward_variables_from(invoker, "*", _ignore_vars) |
| |
| public_deps = [ ":$_facade_name" ] |
| |
| # If the backend is set, inject it as a dependency. |
| if (invoker.backend != "") { |
| public_deps += [ invoker.backend ] |
| } else { |
| # If the backend is not set, depend on the *_NO_BACKEND_SET target. |
| public_deps += [ ":$_main_target_name" + "_NO_BACKEND_SET" ] |
| } |
| } |
| } |