pw_build: Facade and configuration tweaks and docs
- Add documentation for facades and the pw_facade template.
- Document the module config pattern.
- Remove the need for the facade_name argument to pw_facade.
Change-Id: I77529583967cfdb4f47ee87313982b1259ca036e
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/22045
Reviewed-by: Alexei Frolov <frolv@google.com>
Commit-Queue: Wyatt Hepler <hepler@google.com>
diff --git a/pw_build/docs.rst b/pw_build/docs.rst
index 64c67f9..8fe235b 100644
--- a/pw_build/docs.rst
+++ b/pw_build/docs.rst
@@ -42,7 +42,7 @@
Target types
^^^^^^^^^^^^
-.. code::
+.. code-block::
import("$dir_pw_build/target_types.gni")
@@ -75,6 +75,34 @@
All of the ``pw_*`` target type overrides accept any arguments, as they simply
forward them through to the underlying target.
+.. _module-pw_build-facade:
+
+pw_facade
+^^^^^^^^^
+In their simplest form, a :ref:`facade<docs-module-structure-facades>` is a GN
+build arg used to change a dependency at compile time. Pigweed targets configure
+these facades as needed.
+
+The ``pw_facade`` template bundles a ``pw_source_set`` with a facade build arg.
+This allows the facade to provide header files, compilation options or anything
+else a GN ``source_set`` provides.
+
+The ``pw_facade`` template declares two targets:
+
+* ``$target_name``: the public-facing ``pw_source_set``, with a ``public_dep``
+ on the backend
+* ``$target_name.facade``: target used by the backend to avoid circular
+ dependencies
+
+.. code-block::
+
+ # Declares ":foo" and ":foo.facade" GN targets
+ pw_facade("foo") {
+ backend = pw_log_BACKEND
+ public_configs = [ ":public_include_path" ]
+ public = [ "public/pw_foo/foo.h" ]
+ }
+
.. _module-pw_build-python-script:
pw_python_action
@@ -127,13 +155,13 @@
Evaluates to the output file of the provided GN target. For example, the
expression
- .. code::
+ .. code-block::
"<TARGET_FILE(//foo/bar:static_lib)>"
might expand to
- .. code::
+ .. code-block::
"/home/User/project_root/out/obj/foo/bar/static_lib.a"
@@ -158,14 +186,14 @@
For example, consider this expression:
- .. code::
+ .. code-block::
"--database=<TARGET_FILE_IF_EXISTS(//alpha/bravo)>"
If the ``//alpha/bravo`` target file exists, this might expand to the
following:
- .. code::
+ .. code-block::
"--database=/home/User/project/out/obj/alpha/bravo/bravo.elf"
@@ -181,13 +209,13 @@
For example, the expression
- .. code::
+ .. code-block::
"<TARGET_OBJECTS(//foo/bar:a_source_set)>"
might expand to multiple separate arguments:
- .. code::
+ .. code-block::
"/home/User/project_root/out/obj/foo/bar/a_source_set.file_a.cc.o"
"/home/User/project_root/out/obj/foo/bar/a_source_set.file_b.cc.o"
@@ -195,7 +223,7 @@
**Example**
-.. code::
+.. code-block::
import("$dir_pw_build/python_action.gni")
@@ -235,7 +263,7 @@
**Example**
-.. code::
+.. code-block::
import("$dir_pw_build/input_group.gni")
@@ -254,7 +282,7 @@
files are modified.
pw_zip
-^^^^^^^^^^^^^^
+^^^^^^
``pw_zip`` is a target that allows users to zip up a set of input files and
directories into a single output ``.zip`` file—a simple automation of a
potentially repetitive task.
@@ -286,7 +314,7 @@
Let's say we have the following structure for a ``//source/`` directory:
-.. code::
+.. code-block::
source/
├── file1.txt
@@ -299,7 +327,7 @@
And we create the following build target:
-.. code::
+.. code-block::
import("$dir_pw_build/zip.gni")
@@ -324,7 +352,7 @@
This will result in a ``.zip`` file called ``foo.zip`` stored in
``//$target_out_dir`` with the following structure:
-.. code::
+.. code-block::
foo.zip
├── bar/
@@ -345,7 +373,7 @@
The following command generates Ninja build files in the out/cmake directory.
-.. code:: sh
+.. code-block:: sh
cmake -B out/cmake -S /path/to/pigweed -G Ninja
@@ -373,7 +401,7 @@
To use Pigweed libraries form a CMake-based project, simply include the Pigweed
repository from a ``CMakeLists.txt``.
-.. code:: cmake
+.. code-block:: cmake
add_subdirectory(path/to/pigweed pigweed)
@@ -382,7 +410,7 @@
If desired, modules can be included individually.
-.. code:: cmake
+.. code-block:: cmake
include(path/to/pigweed/pw_build/pigweed.cmake)
diff --git a/pw_build/facade.gni b/pw_build/facade.gni
index 684a4f7..4bda84f 100644
--- a/pw_build/facade.gni
+++ b/pw_build/facade.gni
@@ -23,8 +23,19 @@
# link against. Typically this will be done by pointing a build arg like
# `pw_[module]_BACKEND` at a backend implementation for that module.
#
+# To avoid circular dependencies, pw_facade creates two targets:
+#
+# - $target_name: the public-facing pw_source_set
+# - $target_name.facade: target used by the backend to avoid circular
+# dependencies
+#
+# If the target name matches the directory name (e.g. //foo:foo), a ":facade"
+# alias of the facade target (e.g. //foo:facade) is also provided. This avoids
+# the need to repeat the directory name, for consistency with the main target.
+#
# Example facade:
#
+# # Creates ":module_name" and ":module_name.facade" GN targets.
# pw_facade("module_name") {
# backend = dir_module_name_backend
# public_deps = [
@@ -32,20 +43,32 @@
# ]
# }
#
-# 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".
+# Accepts the standard pw_source_set args with the following additions:
+#
+# - backend: the dependency that implements this facade (a GN variable)
#
template("pw_facade") {
assert(defined(invoker.backend),
"pw_facade requires a reference to a backend variable for the facade")
+ _facade_name = "$target_name.facade"
+
if (defined(invoker.facade_name)) {
- _facade_name = invoker.facade_name
- } else {
- _facade_name = "facade"
+ not_needed([ invoker.facade_name ])
+ print("pw_facade(\"$target_name\") uses the facade_name arg, which is",
+ "deprecated. Access the facade target as $target_name.facade")
+ }
+
+ if (get_path_info(get_label_info(":$target_name", "dir"), "name") ==
+ get_label_info(":$target_name", "name")) {
+ group("facade") {
+ public_deps = [ ":$_facade_name" ]
+ }
+ }
+
+ # For backwards compatibility, provide a _facade version of the name.
+ group(target_name + "_facade") {
+ public_deps = [ ":$_facade_name" ]
}
# A facade's headers are split into a separate target to avoid a circular
@@ -90,7 +113,7 @@
# error message.
_main_target_name = target_name
- pw_python_action(_main_target_name + "_NO_BACKEND_SET") {
+ pw_python_action(_main_target_name + ".NO_BACKEND_SET") {
stamp = true
script = "$dir_pw_build/py/pw_build/null_backend.py"
args = [ _main_target_name ]
@@ -112,8 +135,8 @@
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" ]
+ # If the backend is not set, depend on the *.NO_BACKEND_SET target.
+ public_deps += [ ":$_main_target_name" + ".NO_BACKEND_SET" ]
}
}
}