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" ]
     }
   }
 }