aboutsummaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/BUILD.gn46
-rw-r--r--docs/build_system.rst454
-rw-r--r--docs/embedded_cpp_guide.rst6
-rw-r--r--docs/faq.rst4
-rw-r--r--docs/getting_started.md30
-rw-r--r--docs/images/pw_presubmit_demo.gifbin384285 -> 0 bytes
-rw-r--r--docs/index.rst2
-rw-r--r--docs/module_guides.rst2
-rw-r--r--docs/module_structure.rst209
-rw-r--r--docs/style_guide.rst6
-rw-r--r--docs/targets.rst111
11 files changed, 743 insertions, 127 deletions
diff --git a/docs/BUILD.gn b/docs/BUILD.gn
index caac88337..50abaccb7 100644
--- a/docs/BUILD.gn
+++ b/docs/BUILD.gn
@@ -12,14 +12,13 @@
# License for the specific language governing permissions and limitations under
# the License.
-# gn-format disable
import("//build_overrides/pigweed.gni")
import("$dir_pw_docgen/docs.gni")
+
pw_doc_group("core_docs") {
inputs = [
"images/pw_env_setup_demo.gif",
- "images/pw_presubmit_demo.gif",
"images/pw_status_test.png",
"images/pw_watch_build_demo.gif",
"images/pw_watch_on_device_demo.gif",
@@ -38,6 +37,7 @@ pw_doc_group("core_docs") {
# Documentation for upstream Pigweed targets.
group("target_docs") {
deps = [
+ "$dir_pigweed/targets/arduino:target_docs",
"$dir_pigweed/targets/docs:target_docs",
"$dir_pigweed/targets/host:target_docs",
"$dir_pigweed/targets/lm3s6965evb-qemu:target_docs",
@@ -45,25 +45,14 @@ group("target_docs") {
]
}
-pw_doc_gen("docs") {
- conf = "conf.py"
- sources = [
- "../CODE_OF_CONDUCT.md",
- "../CONTRIBUTING.md",
- "../README.md",
- "build_system.rst",
- "index.rst",
- "module_guides.rst",
- "targets.rst",
- ]
- output_directory = target_gen_dir
+group("module_docs") {
deps = [
- ":core_docs",
- ":target_docs",
"$dir_docker:docs",
"$dir_pw_allocator:docs",
+ "$dir_pw_arduino_build:docs",
"$dir_pw_assert:docs",
"$dir_pw_assert_basic:docs",
+ "$dir_pw_assert_log:docs",
"$dir_pw_base64:docs",
"$dir_pw_bloat:docs",
"$dir_pw_blob_store:docs",
@@ -79,13 +68,18 @@ pw_doc_gen("docs") {
"$dir_pw_doctor:docs",
"$dir_pw_env_setup:docs",
"$dir_pw_fuzzer:docs",
+ "$dir_pw_hdlc_lite:docs",
"$dir_pw_hex_dump:docs",
"$dir_pw_kvs:docs",
"$dir_pw_log:docs",
"$dir_pw_log_basic:docs",
+ "$dir_pw_log_null:docs",
+ "$dir_pw_log_rpc:docs",
"$dir_pw_log_tokenized:docs",
+ "$dir_pw_metric:docs",
"$dir_pw_minimal_cpp_stdlib:docs",
"$dir_pw_module:docs",
+ "$dir_pw_package:docs",
"$dir_pw_polyfill:docs",
"$dir_pw_preprocessor:docs",
"$dir_pw_presubmit:docs",
@@ -100,6 +94,7 @@ pw_doc_gen("docs") {
"$dir_pw_stream:docs",
"$dir_pw_string:docs",
"$dir_pw_sys_io:docs",
+ "$dir_pw_sys_io_arduino:docs",
"$dir_pw_sys_io_baremetal_stm32f429:docs",
"$dir_pw_sys_io_stdio:docs",
"$dir_pw_target_runner:docs",
@@ -113,3 +108,22 @@ pw_doc_gen("docs") {
"$dir_pw_web_ui:docs",
]
}
+
+pw_doc_gen("docs") {
+ conf = "conf.py"
+ sources = [
+ "../CODE_OF_CONDUCT.md",
+ "../CONTRIBUTING.md",
+ "../README.md",
+ "build_system.rst",
+ "index.rst",
+ "module_guides.rst",
+ "targets.rst",
+ ]
+ output_directory = target_gen_dir
+ deps = [
+ ":core_docs",
+ ":module_docs",
+ ":target_docs",
+ ]
+}
diff --git a/docs/build_system.rst b/docs/build_system.rst
index a9d465c4f..6938d190c 100644
--- a/docs/build_system.rst
+++ b/docs/build_system.rst
@@ -1,17 +1,188 @@
-.. _chapter-build-system:
+.. _docs-build-system:
============
Build system
============
+Building software for embedded devices is a complex process. Projects often have
+custom toolchains, target different hardware platforms, and require additional
+configuration and post-processing of artifacts.
+
+As a modern embedded framework, Pigweed's goal is to collect these embedded use
+cases into a powerful and flexible build system, then extend it with support for
+modern software development practices.
+
+What's in a build system?
+=========================
+A quality build system provides a variety of features beyond compiling code.
+Throughout our experience with embedded development, we've found several build
+features to be especially useful, and designed Pigweed's build system with them
+in mind.
+
+Simple toolchain configuration
+------------------------------
+Embedded projects often use custom build toolchains for their specific hardware.
+Configuring these should be a simple process, both in their initial setup and
+later adjustments.
+
+Multi-target builds
+-------------------
+Virtually every consumer product has firmware that targets different boards or
+MCUs during development. While building for a single board is simple enough, the
+complexity of supporting different targets ranges from changing compiler flags
+to swapping out entire libraries of firmware and drivers. This is often done by
+running multiple builds, configuring each one accordingly. In Pigweed, we've
+designed our build system with first-class multi-target support in mind,
+allowing any number of target configurations to be built simultaneously.
+
+Multi-language support
+----------------------
+Embedded projects are typically written in C, C++, and assembly. However, it is
+possible to have firmware written in other languages, such as Rust.
+Additionally, projects may have host-side tooling written in a wide variety of
+languages. Having all of these build together proves to be a large time saver.
+
+Custom scripting
+----------------
+Embedded projects often require post-processing of build artifacts; these may
+include:
+
+* Extracting ELF sections into a different container
+* Injecting metadata into firmware images
+* Image signing
+* Creating databases of symbols for debugging
+* Extracting string tokens into a database (for example, with
+ :ref:`module-pw_tokenizer`)
+
+These are run as steps during a build, facilitated by the build system.
+
+See also
+^^^^^^^^
+
+* :ref:`module-pw_build-python-action`
+
+Python packaging
+----------------
+Python is a favorite scripting language of many development teams, and here at
+Pigweed, we're no exception. Much of Pigweed's host-side tooling is written in
+Python. While Python works great for local development, problems can arise when
+scripts need to be packaged and distributed for vendors or factory teams. Having
+proper support for packaging Python within a build system allows teams to focus
+on writing code instead of worrying about distribution.
+
+Size reporting
+--------------
+On embedded devices, memory is everything. Most projects have some sort of
+custom tooling to determine how much flash and RAM space their firmware uses.
+Being able to run size reports as part of a build ensures that they are always
+up-to-date and allows space usage to be tracked over time.
+
+See also
+^^^^^^^^
+
+* :ref:`module-pw_bloat`
+
+Documentation
+-------------
+An oft-neglected part of software development, documentation is invaluable for
+future maintainers of a project. As such, Pigweed has integrated documentation
+which builds alongside its code and combines with other build features, such as
+size reports, to provide high quality, up-to-date references for developers.
+
+See also
+^^^^^^^^
+
+* :ref:`module-pw_docgen`
+
+Unit testing
+------------
+Unit tests are essential to ensure that the functionality of code remains
+consistent as changes are made to avoid accidental regressions. Running unit
+tests as part of a build keeps developers constantly aware of the impact of
+their changes.
+
+Host-side unit tests
+^^^^^^^^^^^^^^^^^^^^
+Though Pigweed targets embedded devices, a lot of its code can be run and tested
+on a host desktop by swapping out backends to host platform libraries. This is
+highly beneficial during development, as it allows tests to consistently run
+without having to go through the process of flashing a device.
+
+Device-side unit tests
+^^^^^^^^^^^^^^^^^^^^^^
+As useful as host-side tests are, they are not sufficient for developing actual
+firmware, and it is critical to run tests on the actual hardware. Pigweed has
+invested into creating a test framework and build integration for running tests
+across physical devices as part of a build.
+
+See also
+^^^^^^^^
+
+* :ref:`module-pw_unit_test`
+* :ref:`module-pw_target_runner`
+
+Bonus: pw watch
+---------------
+In web development, it is common to have a file system watcher listening for
+source file changes and triggering a build for quick iteration. When combined
+with a fast incremental build system, this becomes a powerful feature, allowing
+things such as unit tests and size reports to re-run whenever any dependent
+code is modified.
+
+While initially seen as somewhat of a gimmick, Pigweed's watcher has become a
+staple of Pigweed development, with most Pigweed users having it permanently
+running in a terminal window.
+
+See also
+^^^^^^^^
+
+* :ref:`module-pw_watch`
+
+Pigweed's build systems
+=======================
+Pigweed can be used either as a monolith or à la carte, slotting into an
+existing project. To this end, Pigweed supports multiple build systems, allowing
+Pigweed-based projects to choose the most suitable one for them.
+
+Of the supported build systems, GN is the most full-featured, followed by CMake,
+and finally Bazel.
+
+CMake
+-----
+A well-known name in C/C++ development, `CMake`_ is widely used by all kinds of
+projects, including embedded devices. Pigweed's CMake support is provided
+primarily for projects that have an existing CMake build and wish to integrate
+Pigweed modules.
+
+Bazel
+-----
+The open source version of Google's internal build system. `Bazel`_ has been
+growing in popularity within the open source world, as well as being adopted by
+various proprietary projects. Its modular structure makes it a great fit for
+à la carte usage.
+
+GN
+--
+A perhaps unfamiliar name, `GN (Generate Ninja)`_ is a meta-build system that
+outputs `Ninja`_ build files, originally designed for use in Chromium. Pigweed
+first experimented with GN after hearing about it from another team, and we
+quickly came to appreciate its speed and simplicity. GN has become Pigweed's
+primary build system; it is used for all upstream development and strongly
+recommended for Pigweed-based projects where possible.
+
+.. _CMake: https://cmake.org/
+.. _Bazel: https://bazel.build/
+.. _GN (Generate Ninja): https://gn.googlesource.com/gn
+.. _Ninja: https://ninja-build.org/
+
+The GN build
+============
+This section describes Pigweed's GN build structure, how it is used upstream,
+build conventions, and recommendations for Pigweed-based projects. While
+containing some details about how GN works in general, this section is not
+intended to be a guide on how to use GN. To learn more about the tool itself,
+refer to the official `GN reference`_.
-Pigweed's primary build system is `GN`_, which is used for all upstream
-development. Some other common build systems are supported for integration into
-existing project, which are described in :ref:`chapter-pw-build`. We recommend
-using GN where possible.
-
-.. _GN: https://gn.googlesource.com/gn/
-
-This document describes Pigweed's upstream build structure.
+.. _GN reference: https://gn.googlesource.com/gn/+/master/docs/reference.md
.. note::
A quick note on terminology: the word "target" is overloaded within GN (and
@@ -22,44 +193,149 @@ This document describes Pigweed's upstream build structure.
To avoid confusing the two, we refer to the former as "GN targets" and the
latter as "Pigweed targets".
-.gn
-===
-The entrypoint to the GN build is the ``.gn`` file, which defines the project's
-root directory (henceforth ``//``). In Pigweed, its only purpose is to point GN
-to the location of the BUILDCONFIG file.
-
-BUILDCONFIG.gn
-==============
-``//BUILDCONFIG.gn`` configures the GN build by defining global configuration
-options. Most of Pigweed's configuration is left to individual build targets,
-so the BUILDCONFIG file is relatively empty. It sets Pigweed's default
-toolchain, which GN requires before evaluating any BUILD files.
-
-//BUILD.gn
-==========
+Entrypoint: .gn
+---------------
+The entrypoint to a GN build is the ``.gn`` file, which defines a project's root
+directory (henceforth ``//``).
+
+``.gn`` must point to the location of a ``BUILDCONFIG.gn`` file for the project.
+In Pigweed upstream, this is its only purpose.
+
+Downstream projects may additionally use ``.gn`` to set global overrides for
+Pigweed's build arguments, which apply across all Pigweed targets. For example,
+a project could configure the protobuf libraries that it uses. This is done by
+defining a ``default_args`` scope containing the overrides.
+
+.. code::
+
+ # The location of the BUILDCONFIG file.
+ buildconfig = "//BUILDCONFIG.gn"
+
+ # Build arguments set across all Pigweed targets.
+ default_args = {
+ dir_pw_third_party_nanopb = "//third_party/nanopb-0.4.2"
+ }
+
+Configuration: BUILDCONFIG.gn
+-----------------------------
+The file ``BUILDCONFIG.gn`` configures the GN build by defining any desired
+global variables/options. It can be located anywhere in the build tree, but is
+conventionally placed at the root. ``.gn`` points GN to this file.
+
+``BUILDCONFIG.gn`` is evaluated before any other GN files, and variables defined
+within it are placed into GN's global scope, becoming available in every file
+without requiring imports.
+
+The options configured in this file differ from those in ``.gn`` in two ways:
+
+1. ``BUILDCONFIG.gn`` is evaluated for every GN toolchain (and Pigweed target),
+ whereas ``.gn`` is only evaluated once. This allows ``BUILDCONFIG.gn`` to set
+ different options for each Pigweed target.
+2. In ``.gn``, only GN build arguments can be overridden. ``BUILDCONFIG.gn``
+ allows defining arbitrary variables.
+
+Generally, it is preferable to expose configuration options through build args
+instead of globals in ``BUILDCONFIG.gn`` (something Pigweed's build previously
+did), as they are more flexible, greppable, and easier to manage. However, it
+may make sense to define project-specific constants in ``BUILDCONFIG.gn``.
+
+Pigweed's upstream ``BUILDCONFIG.gn`` does not define any variables; it just
+sets Pigweed's default toolchain, which GN requires.
+
+.. _top-level-build:
+
+Top-level GN targets: //BUILD.gn
+--------------------------------
The root ``BUILD.gn`` file defines all of the libraries, images, tests, and
-binaries built within Pigweed. These are split across a few logical groups,
-which are described below. In order to build a GN target, it *must* be listed in
-one of the groups in this file.
+binaries built by a Pigweed project. This file is evaluated immediately after
+``BUILDCONFIG.gn``, with the active toolchain (which is the default toolchain
+at the start of a build).
+
+``//BUILD.gn`` is responsible for enumerating each of the Pigweed targets built
+by a project. This is done by instantiating a version of each of the project's
+GN target groups with each Pigweed target's toolchain. For example, in upstream,
+all of Pigweed's GN targets are contained within the ``pigweed_default`` group.
+This group is instantiated multiple times, with different Pigweed target
+toolchains.
+
+These groups include the following:
+
+* ``host`` -- builds ``pigweed_default`` with Clang or GCC, depending on the
+ platform
+* ``host_clang`` -- builds ``pigweed_default`` for the host with Clang
+* ``host_gcc`` -- builds ``pigweed_default`` for the host with GCC
+* ``stm32f429i`` -- builds ``pigweed_default`` for STM32F429i Discovery board
+* ``docs`` -- builds the Pigweed documentation and size reports
-``//BUILD.gn`` is also responsible for enumerating each of the Pigweed targets
-that Pigweed supports. These targets are defined as toolchains providing their
-custom configuration options. ``/BUILD.gn`` instantiates a version of its GN
-target groups for each of these toolchains.
+Pigweed projects are recommended to follow this pattern, creating a top-level
+group for each of their Pigweed targets that builds a common GN target with the
+appropriate toolchain.
+
+It is important that no dependencies are listed under the default toolchain
+within ``//BUILD.gn``, as it does not configure any build parameters, and
+therefore should not evaluate any other GN files. The pattern that Pigweed uses
+to achieve this is to wrap all dependencies within a condition checking the
+toolchain.
+
+.. code::
+
+ group("my_application_images") {
+ deps = [] # Empty in the default toolchain.
+
+ if (current_toolchain != default_toolchain) {
+ # This is only evaluated by Pigweed target toolchains, which configure
+ # all of the required options to build Pigweed code.
+ deps += [ "//images:evt" ]
+ }
+ }
+
+ # The images group is instantiated for each of the project's Pigweed targets.
+ group("my_pigweed_target") {
+ deps = [ ":my_application_images(//toolchains:my_pigweed_target)" ]
+ }
.. warning::
Pigweed's default toolchain is never used, so it is set to a dummy toolchain
which doesn't define any tools. ``//BUILD.gn`` contains conditions which check
that the current toolchain is not the default before declaring any GN target
dependencies to prevent the default toolchain from evaluating any other BUILD
- files. All GN targets added to the build must be placed in one of these
+ files. All GN targets added to the build must be placed under one of these
conditional scopes.
-Groups
-------
+"default" group
+^^^^^^^^^^^^^^^
+The root ``BUILD.gn`` file can define a special group named ``default``. If
+present, Ninja will build this group when invoked without arguments.
+
+.. tip::
+ Defining a ``default`` group makes using ``pw watch`` simple!
+
+Optimization levels
+^^^^^^^^^^^^^^^^^^^
+Pigweed's ``//BUILD.gn`` defines the ``pw_default_optimization_level`` build
+arg, which specifies the optimization level to use for the default groups
+(``host``, ``stm32f429i``, etc.). The supported values for
+``pw_default_optimization_level`` are:
+
+* ``debug`` -- create debugging-friendly binaries (``-Og``)
+* ``size_optimized`` -- optimize for size (``-Os``)
+* ``speed_optimized`` -- optimized for speed, without increasing code size
+ (``-O2``)
+
+Pigweed defines versions of its groups in ``//BUILD.gn`` for each optimization
+level. Rather than relying on ``pw_default_optimization_level``, you may
+directly build a group at the desired optimization level:
+``<group>_<optimization>``. Examples include ``host_clang_debug``,
+``host_gcc_size_optimized``, and ``stm32f429i_speed_optimized``.
+
+Upstream GN target groups
+^^^^^^^^^^^^^^^^^^^^^^^^^
+In upstream, Pigweed splits its top-level GN targets into a few logical groups,
+which are described below. In order to build a GN target, it *must* be listed in
+one of the groups in this file.
apps
-^^^^
+~~~~
This group defines the application images built in Pigweed. It lists all of the
common images built across all Pigweed targets, such as modules' example
executables. Each Pigweed target can additionally provide its own specific
@@ -67,44 +343,112 @@ images through the ``pw_TARGET_APPLICATIONS`` build arg, which is included by
this group.
host_tools
-^^^^^^^^^^
+~~~~~~~~~~
This group defines host-side tooling binaries built for Pigweed.
pw_modules
-^^^^^^^^^^
+~~~~~~~~~~
This group lists the main libraries for all of Pigweed's modules.
pw_module_tests
-^^^^^^^^^^^^^^^
+~~~~~~~~~~~~~~~
All modules' unit tests are collected here, so that they can all be run at once.
pigweed_default
-^^^^^^^^^^^^^^^
+~~~~~~~~~~~~~~~
This group defines everything built in a Pigweed build invocation by collecting
-the above groups and conditionally adding them, based on the Pigweed target
-configuration. Generally, new dependencies should not be added here; instead use
-one of the groups listed above.
+the above groups and conditionally depending on them based on the active Pigweed
+target's configuration. Generally, new dependencies should not be added here;
+instead, use one of the groups listed above.
-The ``pigweed_default`` group is instantiated for each of the Pigweed target
-toolchains.
+The ``pigweed_default`` group is instantiated for each upstream Pigweed target's
+toolchain.
Pigweed target instantiations
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
These groups wrap ``pigweed_default`` with a specific target toolchain. They are
named after the Pigweed target, e.g. ``host_clang``, ``stm32f429i``, etc.
-Pigweed targets
-===============
-Each Pigweed target is defined as a GN toolchain which provides its own build
-tool and output binary configs, and custom overrides for Pigweed's build
-configuration arguments. For more information on Pigweed's target system, as
-well as each of the supported targets, refer to :ref:`chapter-targets`.
+Other BUILD files: //\*\*/BUILD.gn
+----------------------------------
+The rest of the ``BUILD.gn`` files in the tree define libraries, configs, and
+build args for each of the modules in a Pigweed project.
+
+Project configuration: //build_overrides/pigweed.gni
+----------------------------------------------------
+Each Pigweed project must contain a Pigweed configuration file at a known
+location in the GN build tree. Currently, this file only contains a single build
+argument, which must be set to the GN build path to the root of the Pigweed
+repository within the project.
+
+Module variables
+----------------
+As Pigweed is inteded to be a subcomponent of a larger project, it cannot assume
+where it or its modules is located. Therefore, Pigweed's upstream BUILD.gn files
+do not use absolute paths; instead, variables are defined pointing to each of
+Pigweed's modules, set relative to a project-specific ``dir_pigweed``.
+
+To depend on Pigweed modules from GN code, import Pigweed's overrides file and
+reference these module variables.
+
+.. code::
-Usage examples
-==============
+ # This must be imported before .gni files from any other Pigweed modules. To
+ # prevent gn format from reordering this import, it must be separated by a
+ # blank line from other imports.
-Building a custom executable
-----------------------------
+ import("//build_overrides/pigweed.gni")
+
+GN target type wrappers
+-----------------------
+To faciliate injecting global configuration options, Pigweed defines wrappers
+around builtin GN target types such as ``source_set`` and ``executable``. These
+are defined within ``$dir_pw_build/target_types.gni``.
+
+.. note::
+ To take advantage of Pigweed's flexible target configuration system, use
+ ``pw_*`` target types (e.g. ``pw_source_set``) in your BUILD.gn files instead
+ of GN builtins.
+
+Pigweed targets
+---------------
+To build for a specific hardware platform, builds define Pigweed targets. These
+are essentially GN toolchains which set special arguments telling Pigweed how to
+build. For information on Pigweed's target system, refer to
+:ref:`docs-targets`.
+
+The dummy toolchain
+-------------------
+Pigweed's ``BUILDCONFIG.gn`` sets the project's default toolchain to a "dummy"
+toolchain which does not specify any compilers or override any build arguments.
+Downstream projects are recommended to do the same, following the steps
+described in :ref:`top-level-build` to configure builds for each of their
+Pigweed targets.
+
+.. admonition:: Why use a dummy?
+
+ To support some of its advanced (and useful!) build features, Pigweed requires
+ the ability to generate new toolchains on the fly. This requires having
+ knowledge of the full configuration of the current toolchain (which is easy if
+ it's all defined within a scope), something which is impractical to achieve
+ using the default toolchain.
+
+ Additionally, there are some cases where GN treats default and non-default
+ toolchains differently. By not using the default toolchain, we avoid having
+ to deal with these inconsistencies.
+
+ It is possible to build Pigweed using only the default toolchain, but it
+ requires a more complicated setup to get everything working and should be
+ avoided unless necessary (for example, when integrating with a large existing
+ GN-based project).
+
+Upstream development examples
+-----------------------------
+If developing for upstream Pigweed, some common build use cases are described
+below.
+
+Building a custom executable/app image
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1. Define your executable GN target using the ``pw_executable`` template.
diff --git a/docs/embedded_cpp_guide.rst b/docs/embedded_cpp_guide.rst
index b05832c5e..4d7a66906 100644
--- a/docs/embedded_cpp_guide.rst
+++ b/docs/embedded_cpp_guide.rst
@@ -1,8 +1,4 @@
-.. _chapter-embedded-cpp:
-
-.. default-domain:: cpp
-
-.. highlight:: sh
+.. _docs-embedded-cpp:
==================
Embedded C++ Guide
diff --git a/docs/faq.rst b/docs/faq.rst
index 090c08efc..3b51b4a0c 100644
--- a/docs/faq.rst
+++ b/docs/faq.rst
@@ -1,4 +1,4 @@
-.. _chapter-faq:
+.. _docs-faq:
--------------------------
Frequently Asked Questions
@@ -33,7 +33,7 @@ So, to answer the question:
Isn't C++ bloated and slow?
---------------------------
In general, no, but it is important to follow some guidelines as discussed in
-the :ref:`Embedded C++ Guide <chapter-embedded-cpp>`.
+the :ref:`Embedded C++ Guide <docs-embedded-cpp>`.
At Google, we have made some quantitative analysis of various common embedded
patterns in C++ to evaluate the cost of various constructs. We will open source
diff --git a/docs/getting_started.md b/docs/getting_started.md
index 4a968c012..59e17def7 100644
--- a/docs/getting_started.md
+++ b/docs/getting_started.md
@@ -43,7 +43,7 @@ Done. Made 1047 targets from 91 files in 114ms
(4) Start the watcher. The watcher will invoke Ninja to build all the targets
```bash
-$ pw watch out default stm32f429i
+$ pw watch out default
▒█████▄ █▓ ▄███▒ ▒█ ▒█ ░▓████▒ ░▓████▒ ▒▓████▄
▒█░ █░ ░█▒ ██▒ ▀█▒ ▒█░ █ ▒█ ▒█ ▀ ▒█ ▀ ▒█ ▀█▌
@@ -52,7 +52,7 @@ $ pw watch out default stm32f429i
▒█ ░█░ ░▓███▀ ▒█▓▀▓█░ ░▓████▒ ░▓████▒ ▒▓████▀
20200707 17:24:06 INF Starting Pigweed build watcher
-20200707 17:24:06 INF Will build [1/1]: out default stm32f429i
+20200707 17:24:06 INF Will build [1/1]: out default
20200707 17:24:06 INF Attaching filesystem watcher to $HOME/wrk/pigweed/...
20200707 17:24:06 INF Triggering initial build...
...
@@ -232,32 +232,24 @@ Depending on your host OS, the compiler will default to either `clang` or `gcc`.
## Building for a Device
-As mentioned previously, Pigweed builds for host by default. In the context of
-Pigweed, a Pigweed "target" is a build configuration that includes a toolchain,
-default library configurations, and more to result in binaries that run
-natively on the target.
+A Pigweed "target" is a build configuration that includes a toolchain, default
+library configurations, and more to result in binaries that run natively on the
+target. With the default build invocation, you're already building for a device
+target (the STMicroelectronics STM32F429I-DISC1) in parallel with the host
+build!
-Switch to the window running `pw_watch`, and quit using `ctrl+c`. To get
-`pw_watch` to build the new STM32F429I-DISC1 target, re-launch by specifying
-which Ninja targets to build:
+If you want to build JUST for the device, you can kick of watch with:
```bash
-$ pw watch out default stm32f429i
+$ pw watch out stm32f429i
```
This is equivalent to the following Ninja invocation:
```bash
-$ ninja -C out default stm32f429i
+$ ninja -C out stm32f429i
```
-Or since the "default" target builds host and docs,
-
-```bash
-$ ninja -C out host docs stm32f429i
-```
-
-Now `pw_watch` is building for host and a device!
## Running Tests on a Device
@@ -273,7 +265,7 @@ USB port on the board (**not** the micro USB). Pigweed will automatically detect
the boards and distribute the tests across the devices. More boards = faster
tests! Keep in mind that you may have to make some environment specific updates
to ensure you have permissions to use the USB device. For example, on Linux you
-may need to update your udev rules and ensure you're in the plugdev and dailout
+may need to update your udev rules and ensure you're in the plugdev and dialout
groups.
![development boards connected via USB](images/stm32f429i-disc1_connected.jpg)
diff --git a/docs/images/pw_presubmit_demo.gif b/docs/images/pw_presubmit_demo.gif
deleted file mode 100644
index 5b460393f..000000000
--- a/docs/images/pw_presubmit_demo.gif
+++ /dev/null
Binary files differ
diff --git a/docs/index.rst b/docs/index.rst
index a7230ed02..9a02eca5d 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -1,5 +1,3 @@
-.. _chapter-home:
-
.. highlight:: sh
.. mdinclude:: README.md
diff --git a/docs/module_guides.rst b/docs/module_guides.rst
index 728deff9a..f45131e85 100644
--- a/docs/module_guides.rst
+++ b/docs/module_guides.rst
@@ -1,3 +1,5 @@
+.. _docs-module-guides:
+
=============
Module Guides
=============
diff --git a/docs/module_structure.rst b/docs/module_structure.rst
index 6774ffdf7..586fca09d 100644
--- a/docs/module_structure.rst
+++ b/docs/module_structure.rst
@@ -1,8 +1,4 @@
-.. default-domain:: cpp
-
-.. highlight:: sh
-
-.. _chapter-module-guide:
+.. _docs-module-structure:
----------------
Module Structure
@@ -31,7 +27,7 @@ Example module structure
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
@@ -100,8 +96,8 @@ whatever name they like, but we suggest picking a short prefix to namespace
your product (e.g. for an Internet of Toast project, perhaps the prefix could
be ``it_``).
-C++ file and directory locations
---------------------------------
+C++ module structure
+--------------------
C++ public headers
~~~~~~~~~~~~~~~~~~
@@ -142,8 +138,8 @@ the public interface, but are not intended for use), place the headers in a
These headers must not override headers from other modules. For
that, there is the ``public_overrides/`` directory.
-Public override headers
-~~~~~~~~~~~~~~~~~~~~~~~
+C++ public override headers
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
Located ``{pw_module_dir}/public_overrides/<module>``. In general, the Pigweed
philosophy is to avoid having "things hiding under rocks", and having header
files with the same name that can override each other is considered a rock
@@ -190,8 +186,177 @@ Example:
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.
+ This makes testing modules with compile-time configuration 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
+ }
+
+ # An example source set for each potential config header location follows.
+
+ # 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 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.
+
+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_log`, :ref:`module-pw_assert`).
+* Highly leveraged code where a virtual interface or callback is too costly or
+ cumbersome (:ref:`module-pw_tokenizer`).
+
+.. caution::
+
+ Modules should only use facades when necessary. Facades are permanently locked
+ to a particular implementation at compile time. Multpile backends cannot be
+ used in one build, and runtime dependency injection is not possible, which
+ makes testing difficult. Where appropriate, modules should use other
+ mechanisms, such as virtual interfaces, callbacks, or templates, in place of
+ facades.
+
+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
``docs.rst`` file. There must be a docgen entry for the documentation in the
``BUILD.gn`` file with the target name ``docs``; so the full target for the
@@ -217,13 +382,18 @@ related files (like images and diagrams) there.
docs/image/screenshot.png
docs/image/diagram.svg
-Steps to create a new module for a Pigweed project
---------------------------------------------------
-These instructions are for creating a new module for contribution to the
-Pigweed project. See below for an `example`__ of what the new module folder
-might look like.
+Creating a new Pigweed module
+-----------------------------
+To create a new Pigweed module, follow the below steps.
+
+.. tip::
-__ `Example module structure`_
+ Connect with the Pigweed community (by `mailing the Pigweed list
+ <https://groups.google.com/forum/#!forum/pigweed>`_ or `raising your idea
+ in the Pigweed chat <https://discord.gg/M9NSeTA>`_) to discuss your module
+ idea before getting too far into the implementation. This can prevent
+ accidentally duplicating work, or avoiding writing code that won't get
+ accepted.
1. Create module folder following `Module name`_ guidelines
2. Add `C++ public headers`_ files in
@@ -243,7 +413,7 @@ __ `Example module structure`_
6. Add folder alias for new module variable in ``/modules.gni``
- - dir_pw_new = "$dir_pigweed/pw_new"
+ - ``dir_pw_new = get_path_info("pw_new", "abspath")``
7. Add new module to main GN build
@@ -259,7 +429,8 @@ __ `Example module structure`_
- Add in ``docs/BUILD.gn`` to ``pw_doc_gen("docs")``
-11. Run :ref:`chapter-module-module-check`
+11. Run :ref:`module-pw_module-module-check`
- ``$ pw module-check {pw_module_dir}``
+12. Contribute your module to upstream Pigweed (optional but encouraged!)
diff --git a/docs/style_guide.rst b/docs/style_guide.rst
index 104fe73d7..320aac33d 100644
--- a/docs/style_guide.rst
+++ b/docs/style_guide.rst
@@ -1,8 +1,4 @@
-.. _chapter-style:
-
-.. default-domain:: cpp
-
-.. highlight:: sh
+.. _docs-pw-style:
===========================
Style Guide and Conventions
diff --git a/docs/targets.rst b/docs/targets.rst
index 22784ce1e..21f4ccc77 100644
--- a/docs/targets.rst
+++ b/docs/targets.rst
@@ -1,11 +1,114 @@
-.. _chapter-targets:
+.. _docs-targets:
=======
Targets
=======
-Pigweed is designed to support many 32-bit targets. This section contains
-documentation for the targets used for upstream Pigweed development,
-though more may exist outside the main Pigweed repository.
+Pigweed is designed to be portable to many different hardware platforms.
+Pigweed's GN build comes with an extensible target system that allows it to be
+configured to build for any number of platforms, which all build simultaneously.
+
+Defining a target
+=================
+Each Pigweed target built by a project is defined within the GN build as a
+toolchain providing the target's build parameters.
+
+In Pigweed, these target toolchains are defined as GN scopes, which are fed into
+a ``generate_toolchain`` template to create the complete GN toolchain.
+
+Hierarchical target structure
+-----------------------------
+The rationale for scope-based toolchains is to make Pigweed targets extensible.
+Variables from a toolchain can be forwarded into new scopes and then extended
+or overriden. This facilitates the sharing of common configuration options
+between toolchains, and allows for hierarchical structures. Upstream Pigweed
+makes use of this heavily; it defines basic compiler-only configurations, uses
+these as a base for board-specific toolchains, then creates its final targets on
+top of those.
+
+.. blockdiag::
+
+ blockdiag {
+ default_fontsize = 14;
+ orientation = portrait;
+
+ arm_gcc [label = "arm_gcc"];
+ arm_gcc_cortex_m4 [label = "cortex_m4"];
+ arm_gcc_cortex_m4f [label = "cortex_m4f"];
+ arm_gcc_cortex_m4f_debug [label = "cortex_m4f_debug"];
+ arm_gcc_cortex_m4f_size_optimized [label = "cortex_m4f_size_optimized"];
+ stm32f429i_disc1_debug [label = "stm32f429i_disc1_debug"];
+ arm_gcc -> arm_gcc_cortex_m4
+ arm_gcc -> arm_gcc_cortex_m4f
+ arm_gcc_cortex_m4f -> arm_gcc_cortex_m4f_debug
+ arm_gcc_cortex_m4f -> arm_gcc_cortex_m4f_size_optimized
+ arm_gcc_cortex_m4f_debug -> stm32f429i_disc1_debug
+ }
+
+Toolchain target variables
+--------------------------
+The core of a toolchain is defining the tools it uses. This is done by setting
+the variables ``ar``, ``cc``, and ``cxx`` to the appropirate compilers. Pigweed
+provides many commonly used compiler configurations in the ``pw_toolchain``
+module.
+
+The rest of the a Pigweed target's configuration is listed within a ``defaults``
+scope in its toolchain. Every variable in this scope is an override of a GN
+build argument defined in Pigweed. Some notable arguments include:
+
+* ``default_configs``: A list of GN configs to apply to every ``pw_*`` GN
+ template. This is typically used to set compiler flags, optimization levels,
+ global #defines, etc.
+* ``default_public_deps``: List of GN targets which are added as a dependency
+ to all ``pw_*`` GN targets. This is used to add global module dependencies;
+ for example, in upstream, ``pw_polyfill`` is added here to provide C++17
+ features in C++11/C++14 code.
+* Facade backends: Pigweed defines facades to provide a common interface for
+ core system features such as logging without assuming an implementation.
+ When building a Pigweed target, the implementations for each of these must be
+ chosen. The ``*_BACKEND`` build args that Pigweed defines are used to set
+ these.
+
+There are many other build arguments that can be set, some of which are
+module-specific. A full list can be seen by running ``gn args --list out``,
+and further documentation can be found within their respective modules.
+
+Example Pigweed target
+======================
+The code below demonstrates how a project might configure one of its Pigweed
+targets.
+
+.. code::
+
+ # Prevent gn format from reordering this import.
+ import("//build_overrides/pigweed.gni")
+
+ import("$dir_pw_toolchain/arm_gcc/toolchains.gni")
+ import("$dir_pw_toolchain/generate_toolchain.gni")
+
+ my_target_scope = {
+ # Use Pigweed's Cortex M4 toolchain as a base.
+ _toolchain_base = pw_toolchain_arm_gcc.cortex_m4f_debug
+
+ # Forward everything except the defaults scope from that toolchain.
+ forward_variables_from(_toolchain_base, "*", [ "defaults" ])
+
+ defaults = {
+ # Forward everything from the base toolchain's defaults.
+ forward_variables_from(_toolchain_base.defaults, "*")
+
+ # Extend with custom build arguments for the target.
+ pw_log_BACKEND = dir_pw_log_tokenized
+ }
+ }
+
+ # Create the actual GN toolchain from the scope.
+ generate_toolchain("my_target") {
+ forward_variables_from(my_target_scope, "*")
+ }
+
+Upstream targets
+================
+The following is a list of targets used for upstream Pigweed development.
.. toctree::
:maxdepth: 1