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/docs/module_structure.rst b/docs/module_structure.rst
index 89ec692..c10106a 100644
--- a/docs/module_structure.rst
+++ b/docs/module_structure.rst
@@ -27,7 +27,7 @@
     public/pw_foo/foo.h
     public/pw_foo/baz.h
 
-    # Exposed public headers go under internal/
+    # Exposed private headers go under internal/
     public/pw_foo/internal/bar.h
     public/pw_foo/internal/qux.h
 
@@ -186,6 +186,169 @@
     BUILD.gn
     README.md
 
+Compile-time configuration
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+Pigweed modules are intended to be used in a wide variety of environments.
+In support of this, some modules expose compile-time configuration options.
+Pigweed has an established pattern for declaring and overriding module
+configuration.
+
+.. tip::
+
+  Compile-time configuration provides flexibility, but also imposes
+  restrictions. A module can only have one configuration in a given build.
+  Compile-time configuration also makes testing more difficult. Where
+  appropriate, consider alternatives such as C++ templates or runtime
+  configuration.
+
+Declaring configuration
+^^^^^^^^^^^^^^^^^^^^^^^
+Configuration values are declared in a header file with macros. If the macro
+value is not already defined, a default definition is provided. Otherwise,
+nothing is done. Configuration headers may include ``static_assert`` statements
+to validate configuration values.
+
+.. code-block:: c++
+
+  // Example configuration header
+
+  #ifndef PW_FOO_INPUT_BUFFER_SIZE_BYTES
+  #define PW_FOO_INPUT_BUFFER_SIZE_BYTES 128
+  #endif  // PW_FOO_INPUT_BUFFER_SIZE_BYTES
+
+  static_assert(PW_FOO_INPUT_BUFFER_SIZE_BYTES >= 64);
+
+The configuration header may go in one of three places in the module, depending
+on whether the header should be exposed by the module or not.
+
+.. code-block::
+
+  pw_foo/...
+
+    # Publicly accessible configuration header
+    public/pw_foo/config.h
+
+    # Internal configuration header that is included by other module headers
+    public/pw_foo/internal/config.h
+
+    # Internal configuration header
+    pw_foo_private/config.h
+
+The configuration header is provided by a build system library. This library
+acts as a :ref:`facade<docs-module-structure-facades>`. The facade uses a
+variable such as ``pw_foo_CONFIG``. In upstream Pigweed, all config facades
+default to the ``pw_build_DEFAULT_MODULE_CONFIG`` backend. In the GN build
+system, the config facade is declared as follows:
+
+.. code-block::
+
+  declare_args() {
+    # The build target that overrides the default configuration options for this
+    # module. This should point to a source set that provides defines through a
+    # public config (which may -include a file or add defines directly).
+    pw_foo_CONFIG = pw_build_DEFAULT_MODULE_CONFIG
+  }
+
+  # Publicly accessible configuration header (most common)
+  pw_source_set("config") {
+    public = [ "public/pw_foo/config.h" ]
+    public_configs = [ ":public_include_path" ]
+    public_deps = [ pw_foo_CONFIG ]
+  }
+
+  # Internal configuration header that is included by other module headers
+  pw_source_set("config") {
+    sources = [ "public/pw_foo/internal/config.h" ]
+    public_configs = [ ":public_include_path" ]
+    public_deps = [ pw_foo_CONFIG ]
+    visibility = [":*"]  # Only allow this module to depend on ":config"
+    friend = [":*"]  # Allow this module to access the config.h header.
+  }
+
+  # Internal configuration header
+  pw_source_set("config") {
+    public = [ "pw_foo_private/config.h" ]
+    public_deps = [ pw_foo_CONFIG ]
+    visibility = [":*"]  # Only allow this module to depend on ":config"
+  }
+
+Overriding configuration
+^^^^^^^^^^^^^^^^^^^^^^^^
+As noted above, all module configuration facades default to the same backend
+(``pw_build_DEFAULT_MODULE_CONFIG``). This allows projects to override
+configuration values for multiple modules from a single configuration backend,
+if desired. The configuration values may also be overridden individually by
+setting backends for the individual module configurations (e.g. in GN,
+``pw_foo_CONFIG = "//configuration:my_foo_config"``).
+
+Configurations are overridden by setting compilation options in the config
+backend. These options could be set through macro definitions, such as
+``-DPW_FOO_INPUT_BUFFER_SIZE_BYTES=256``, or in a header file included with the
+``-include`` option.
+
+This example shows how two ways to configure a module in the GN build system.
+
+.. code-block::
+
+  # In the toolchain, set either pw_build_DEFAULT_MODULE_CONFIG or pw_foo_CONFIG
+  pw_build_DEFAULT_MODULE_CONFIG = get_path_info(":define_overrides", "abspath")
+
+  # This configuration sets PW_FOO_INPUT_BUFFER_SIZE_BYTES using the -D macro.
+  pw_source_set("define_overrides") {
+    public_configs = [ ":define_options" ]
+  }
+
+  config("define_options") {
+    defines = [ "-DPW_FOO_INPUT_BUFFER_SIZE_BYTES=256" ]
+  }
+
+  # This configuration sets PW_FOO_INPUT_BUFFER_SIZE_BYTES with a header file.
+  pw_source_set("include_overrides") {
+    public_configs = [ ":header_options" ]
+
+    # Header file with #define PW_FOO_INPUT_BUFFER_SIZE_BYTES 256
+    sources = [ "my_config_overrides.h" ]
+  }
+
+  config("header_options") {
+    cflags = [
+      "-include",
+      "my_config_overrides.h",
+    ]
+  }
+
+.. _docs-module-structure-facades:
+
+Facades
+-------
+In Pigweed, facades represent a dependency that can be swapped at compile time.
+Facades are similar in concept to a virtual interface, but the implementation is
+set by the build system. Runtime polymorphism with facades is not
+possible, and each facade may only have one implementation (backend) per
+toolchain compilation.
+
+In the simplest sense, a facade is just a dependency represented by a variable.
+For example, the ``pw_log`` facade is represented by the ``pw_log_BACKEND``
+build variable. Facades typically are bundled with a build system library that
+depends on the backend.
+
+Modules should only use facades when necessary. Since they are fixed at compile
+time, runtime dependency injection is not possible. Where appropriate, modules
+should use other mechanisms, such as virtual interfaces or callbacks, in place
+of facades.
+
+Facades are essential in some circumstances:
+
+* Low-level, platform-specific features (:ref:`module-pw_cpu_exception`).
+* Features that require a macro or non-virtual function interface
+  (:ref:`module-pw_tokenizer`),
+* Highly leveraged code where a virtual interface or callback is too costly or
+  cumbersome (:ref:`module-pw_log`, :ref:`module-pw_assert`).
+
+The GN build system provides the
+:ref:`pw_facade template<module-pw_build-facade>` as a convenient way to declare
+facades.
+
 Documentation
 -------------
 Documentation should go in the root module folder, typically in the