| # 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. |
| |
| import("$dir_pw_build/python_script.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 `dir_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 |
| # |
| template("pw_facade") { |
| assert(defined(invoker.backend), |
| "pw_facade requires a reference to a backend variable for the 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" ] |
| # } |
| # |
| # 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", |
| ] |
| source_set("facade") { |
| forward_variables_from(invoker, _facade_vars) |
| sources = public |
| } |
| |
| if (invoker.backend == "") { |
| # If backend is not set to anything, create a script that emits an error. |
| pw_python_script(target_name) { |
| stamp = true |
| script = "$dir_pw_build/py/null_backend.py" |
| args = [ target_name ] |
| not_needed(invoker, "*") |
| } |
| } else { |
| # When a backend is set, create a target defining the facade library. |
| 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", |
| |
| # Inject the backend as a dependency. |
| invoker.backend, |
| ] |
| |
| if (defined(sources)) { |
| # Protect against the pattern |
| # |
| # sources = [ "foo.cc" ] + public |
| # |
| # as the public headers are already listed in the :facade target. |
| sources -= invoker.public |
| } |
| } |
| } |
| } |