• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1.. _module-pw_build:
2
3--------
4pw_build
5--------
6Pigweed's modules aim to be easily integratable into both new and existing
7embedded projects. To that goal, the ``pw_build`` module provides support for
8multiple build systems. Our personal favorite is `GN`_/`Ninja`_, which is used
9by upstream developers for its speed and flexibility. `CMake`_ and `Bazel`_
10build files are also provided by all modules, allowing Pigweed to be added to a
11project with minimal effort.
12
13.. _GN: https://gn.googlesource.com/gn/
14.. _Ninja: https://ninja-build.org/
15.. _CMake: https://cmake.org/
16.. _Bazel: https://bazel.build/
17
18Beyond just compiling code, Pigweed’s GN build system can also:
19
20* Generate HTML documentation, via our Sphinx integration (with ``pw_docgen``)
21* Display memory usage report cards (with ``pw_bloat``)
22* Incrementally run unit tests after code changes (with ``pw_target_runner``)
23* And more!
24
25These are only supported in the GN build, so we recommend using it if possible.
26
27GN / Ninja
28==========
29The GN / Ninja build system is the primary build system used for upstream
30Pigweed development, and is the most tested and feature-rich build system
31Pigweed offers.
32
33This module's ``build.gn`` file contains a number of C/C++ ``config``
34declarations that are used by upstream Pigweed to set some architecture-agnostic
35compiler defaults. (See Pigweed's ``//BUILDCONFIG.gn``)
36
37``pw_build`` also provides several useful GN templates that are used throughout
38Pigweed.
39
40Target types
41------------
42.. code-block::
43
44  import("$dir_pw_build/target_types.gni")
45
46  pw_source_set("my_library") {
47    sources = [ "lib.cc" ]
48  }
49
50Pigweed defines wrappers around the four basic GN binary types ``source_set``,
51``executable``, ``static_library``, and ``shared_library``. These wrappers apply
52default arguments to each target, as defined in ``pw_build/default.gni``.
53Arguments may be added or removed globally using the ``default_configs``,
54``default_public_deps``, and ``remove_default_configs`` build args.
55Additionally, arguments may be removed on a per-target basis with the
56``remove_configs`` and ``remove_public_deps`` variables.
57
58The ``pw_executable`` template provides additional functionality around building
59complete binaries. As Pigweed is a collection of libraries, it does not know how
60its final targets are built. ``pw_executable`` solves this by letting each user
61of Pigweed specify a global executable template for their target, and have
62Pigweed build against it. This is controlled by the build variable
63``pw_executable_config.target_type``, specifying the name of the executable
64template for a project.
65
66In some uncommon cases, a project's ``pw_executable`` template definition may
67need to stamp out some ``pw_source_set``s. Since a pw_executable template can't
68import ``$dir_pw_build/target_types.gni`` due to circular imports, it should
69import ``$dir_pw_build/cc_library.gni`` instead.
70
71Additionally ``pw_executable``, ``pw_source_set``, ``pw_static_library``, and
72``pw_shared_library`` track source files via the ``pw_source_files`` field the
73target's
74`GN metadata <https://gn.googlesource.com/gn/+/main/docs/reference.md#metadata_collection>`_.
75This list can be writen to a file at build time using ``generated_file``.  The
76primary use case for this is to generate a token database containing all the
77source files.  This allows PW_ASSERT to emit filename tokens even though it
78can't add them to the elf file because of the resons described at
79:ref:`module-pw_assert-assert-api`.
80
81.. note::
82  ``pw_source_files``, if not rebased will default to outputing module relative
83  paths from a ``generated_file`` target.  This is likely not useful.  Adding
84  a ``rebase`` argument to ``generated_file`` such as
85  ``rebase = root_build_dir`` will result in usable paths.  For an example,
86  see `//pw_tokenizer/database.gni`'s `pw_tokenizer_filename_database` template.
87
88.. tip::
89
90  Prefer to use ``pw_executable`` over plain ``executable`` targets to allow
91  cleanly building the same code for multiple target configs.
92
93**Arguments**
94
95All of the ``pw_*`` target type overrides accept any arguments, as they simply
96forward them through to the underlying target.
97
98.. _module-pw_build-link-deps:
99
100Link-only deps
101--------------
102It may be necessary to specify additional link-time dependencies that may not be
103explicitly depended on elsewhere in the build. One example of this is a
104``pw_assert`` backend, which may need to leave out dependencies to avoid
105circular dependencies. Its dependencies need to be linked for executables and
106libraries, even if they aren't pulled in elsewhere.
107
108The ``pw_build_LINK_DEPS`` build arg is a list of dependencies to add to all
109``pw_executable``, ``pw_static_library``, and ``pw_shared_library`` targets.
110This should only be used as a last resort when dependencies cannot be properly
111expressed in the build.
112
113Python packages
114---------------
115GN templates for :ref:`Python build automation <docs-python-build>` are
116described in :ref:`module-pw_build-python`.
117
118.. toctree::
119  :hidden:
120
121  python
122
123
124.. _module-pw_build-cc_blob_library:
125
126pw_cc_blob_library
127------------------
128The ``pw_cc_blob_library`` template is useful for embedding binary data into a
129program. The template takes in a mapping of symbol names to file paths, and
130generates a set of C++ source and header files that embed the contents of the
131passed-in files as arrays.
132
133**Arguments**
134
135* ``blobs``: A list of GN scopes, where each scope corresponds to a binary blob
136  to be transformed from file to byte array. This is a required field. Blob
137  fields include:
138
139  * ``symbol_name``: The C++ symbol for the byte array.
140  * ``file_path``: The file path for the binary blob.
141  * ``linker_section``: If present, places the byte array in the specified
142    linker section.
143
144* ``out_header``: The header file to generate. Users will include this file
145  exactly as it is written here to reference the byte arrays.
146* ``namespace``: An optional (but highly recommended!) C++ namespace to place
147  the generated blobs within.
148
149Example
150^^^^^^^
151
152**BUILD.gn**
153
154.. code-block::
155
156  pw_cc_blob_library("foo_bar_blobs") {
157    blobs: [
158      {
159        symbol_name: "kFooBlob"
160        file_path: "${target_out_dir}/stuff/bin/foo.bin"
161      },
162      {
163        symbol_name: "kBarBlob"
164        file_path: "//stuff/bin/bar.bin"
165        linker_section: ".bar_section"
166      },
167    ]
168    out_header: "my/stuff/foo_bar_blobs.h"
169    namespace: "my::stuff"
170    deps = [ ":generate_foo_bin" ]
171  }
172
173.. note:: If the binary blobs are generated as part of the build, be sure to
174          list them as deps to the pw_cc_blob_library target.
175
176**Generated Header**
177
178.. code-block::
179
180  #pragma once
181
182  #include <array>
183  #include <cstddef>
184
185  namespace my::stuff {
186
187  extern const std::array<std::byte, 100> kFooBlob;
188
189  extern const std::array<std::byte, 50> kBarBlob;
190
191  }  // namespace my::stuff
192
193**Generated Source**
194
195.. code-block::
196
197  #include "my/stuff/foo_bar_blobs.h"
198
199  #include <array>
200  #include <cstddef>
201
202  #include "pw_preprocessor/compiler.h"
203
204  namespace my::stuff {
205
206  const std::array<std::byte, 100> kFooBlob = { ... };
207
208  PW_PLACE_IN_SECTION(".bar_section")
209  const std::array<std::byte, 50> kBarBlob = { ... };
210
211  }  // namespace my::stuff
212
213.. _module-pw_build-facade:
214
215pw_facade
216---------
217In their simplest form, a :ref:`facade<docs-module-structure-facades>` is a GN
218build arg used to change a dependency at compile time. Pigweed targets configure
219these facades as needed.
220
221The ``pw_facade`` template bundles a ``pw_source_set`` with a facade build arg.
222This allows the facade to provide header files, compilation options or anything
223else a GN ``source_set`` provides.
224
225The ``pw_facade`` template declares two targets:
226
227* ``$target_name``: the public-facing ``pw_source_set``, with a ``public_dep``
228  on the backend
229* ``$target_name.facade``: target used by the backend to avoid circular
230  dependencies
231
232.. code-block::
233
234  # Declares ":foo" and ":foo.facade" GN targets
235  pw_facade("foo") {
236    backend = pw_log_BACKEND
237    public_configs = [ ":public_include_path" ]
238    public = [ "public/pw_foo/foo.h" ]
239  }
240
241Low-level facades like ``pw_assert`` cannot express all of their dependencies
242due to the potential for dependency cycles. Facades with this issue may require
243backends to place their implementations in a separate build target to be listed
244in ``pw_build_LINK_DEPS`` (see :ref:`module-pw_build-link-deps`). The
245``require_link_deps`` variable in ``pw_facade`` asserts that all specified build
246targets are present in ``pw_build_LINK_DEPS`` if the facade's backend variable
247is set.
248
249.. _module-pw_build-python-action:
250
251pw_python_action
252----------------
253The ``pw_python_action`` template is a convenience wrapper around ``action`` for
254running Python scripts. The main benefit it provides is resolution of GN target
255labels to compiled binary files. This allows Python scripts to be written
256independently of GN, taking only filesystem paths as arguments.
257
258Another convenience provided by the template is to allow running scripts without
259any outputs. Sometimes scripts run in a build do not directly produce output
260files, but GN requires that all actions have an output. ``pw_python_action``
261solves this by accepting a boolean ``stamp`` argument which tells it to create a
262placeholder output file for the action.
263
264**Arguments**
265
266``pw_python_action`` accepts all of the arguments of a regular ``action``
267target. Additionally, it has some of its own arguments:
268
269* ``module``: Run the specified Python module instead of a script. Either
270  ``script`` or ``module`` must be specified, but not both.
271* ``capture_output``: Optional boolean. If true, script output is hidden unless
272  the script fails with an error. Defaults to true.
273* ``stamp``: Optional variable indicating whether to automatically create a
274  placeholder output file for the script. This allows running scripts without
275  specifying ``outputs``. If ``stamp`` is true, a generic output file is
276  used. If ``stamp`` is a file path, that file is used as a stamp file. Like any
277  output file, ``stamp`` must be in the build directory. Defaults to false.
278* ``environment``: Optional list of strings. Environment variables to set,
279  passed as NAME=VALUE strings.
280* ``working_directory``: Optional file path. When provided the current working
281  directory will be set to this location before the Python module or script is
282  run.
283
284**Expressions**
285
286``pw_python_action`` evaluates expressions in ``args``, the arguments passed to
287the script. These expressions function similarly to generator expressions in
288CMake. Expressions may be passed as a standalone argument or as part of another
289argument. A single argument may contain multiple expressions.
290
291Generally, these expressions are used within templates rather than directly in
292BUILD.gn files. This allows build code to use GN labels without having to worry
293about converting them to files.
294
295.. note::
296
297  We intend to replace these expressions with native GN features when possible.
298  See `pwbug/347 <http://bugs.pigweed.dev/347>`_.
299
300The following expressions are supported:
301
302.. describe:: <TARGET_FILE(gn_target)>
303
304  Evaluates to the output file of the provided GN target. For example, the
305  expression
306
307  .. code-block::
308
309    "<TARGET_FILE(//foo/bar:static_lib)>"
310
311  might expand to
312
313  .. code-block::
314
315    "/home/User/project_root/out/obj/foo/bar/static_lib.a"
316
317  ``TARGET_FILE`` parses the ``.ninja`` file for the GN target, so it should
318  always find the correct output file, regardless of the toolchain's or target's
319  configuration. Some targets, such as ``source_set`` and ``group`` targets, do
320  not have an output file, and attempting to use ``TARGET_FILE`` with them
321  results in an error.
322
323  ``TARGET_FILE`` only resolves GN target labels to their outputs. To resolve
324  paths generally, use the standard GN approach of applying the
325  ``rebase_path(path, root_build_dir)`` function. This function
326  converts the provided GN path or list of paths to be relative to the build
327  directory, from which all build commands and scripts are executed.
328
329.. describe:: <TARGET_FILE_IF_EXISTS(gn_target)>
330
331  ``TARGET_FILE_IF_EXISTS`` evaluates to the output file of the provided GN
332  target, if the output file exists. If the output file does not exist, the
333  entire argument that includes this expression is omitted, even if there is
334  other text or another expression.
335
336  For example, consider this expression:
337
338  .. code-block::
339
340    "--database=<TARGET_FILE_IF_EXISTS(//alpha/bravo)>"
341
342  If the ``//alpha/bravo`` target file exists, this might expand to the
343  following:
344
345  .. code-block::
346
347    "--database=/home/User/project/out/obj/alpha/bravo/bravo.elf"
348
349  If the ``//alpha/bravo`` target file does not exist, the entire
350  ``--database=`` argument is omitted from the script arguments.
351
352.. describe:: <TARGET_OBJECTS(gn_target)>
353
354  Evaluates to the object files of the provided GN target. Expands to a separate
355  argument for each object file. If the target has no object files, the argument
356  is omitted entirely. Because it does not expand to a single expression, the
357  ``<TARGET_OBJECTS(...)>`` expression may not have leading or trailing text.
358
359  For example, the expression
360
361  .. code-block::
362
363    "<TARGET_OBJECTS(//foo/bar:a_source_set)>"
364
365  might expand to multiple separate arguments:
366
367  .. code-block::
368
369    "/home/User/project_root/out/obj/foo/bar/a_source_set.file_a.cc.o"
370    "/home/User/project_root/out/obj/foo/bar/a_source_set.file_b.cc.o"
371    "/home/User/project_root/out/obj/foo/bar/a_source_set.file_c.cc.o"
372
373**Example**
374
375.. code-block::
376
377  import("$dir_pw_build/python_action.gni")
378
379  pw_python_action("postprocess_main_image") {
380    script = "py/postprocess_binary.py"
381    args = [
382      "--database",
383      rebase_path("my/database.csv", root_build_dir),
384      "--binary=<TARGET_FILE(//firmware/images:main)>",
385    ]
386    stamp = true
387  }
388
389.. _module-pw_build-pw_exec:
390
391pw_exec
392-------
393``pw_exec`` allows for execution of arbitrary programs. It is a wrapper around
394``pw_python_action`` but allows for specifying the program to execute.
395
396.. note:: Prefer to use ``pw_python_action`` instead of calling out to shell
397  scripts, as the python will be more portable. ``pw_exec`` should generally
398  only be used for interacting with legacy/existing scripts.
399
400**Arguments**
401
402* ``program``: The program to run. Can be a full path or just a name (in which
403  case $PATH is searched).
404* ``args``: Optional list of arguments to the program.
405* ``deps``: Dependencies for this target.
406* ``public_deps``: Public dependencies for this target. In addition to outputs
407  from this target, outputs generated by public dependencies can be used as
408  inputs from targets that depend on this one. This is not the case for private
409  deps.
410* ``inputs``: Optional list of build inputs to the program.
411* ``outputs``: Optional list of artifacts produced by the program's execution.
412* ``env``: Optional list of key-value pairs defining environment variables for
413  the program.
414* ``env_file``: Optional path to a file containing a list of newline-separated
415  key-value pairs defining environment variables for the program.
416* ``args_file``: Optional path to a file containing additional positional
417  arguments to the program. Each line of the file is appended to the
418  invocation. Useful for specifying arguments from GN metadata.
419* ``skip_empty_args``: If args_file is provided, boolean indicating whether to
420  skip running the program if the file is empty. Used to avoid running
421  commands which error when called without arguments.
422* ``capture_output``: If true, output from the program is hidden unless the
423  program exits with an error. Defaults to true.
424* ``working_directory``: The working directory to execute the subprocess with.
425  If not specified it will not be set and the subprocess will have whatever
426  the parent current working directory is.
427
428**Example**
429
430.. code-block::
431
432  import("$dir_pw_build/exec.gni")
433
434  pw_exec("hello_world") {
435    program = "/bin/sh"
436    args = [
437      "-c",
438      "echo hello \$WORLD",
439    ]
440    env = [
441      "WORLD=world",
442    ]
443  }
444
445pw_input_group
446--------------
447``pw_input_group`` defines a group of input files which are not directly
448processed by the build but are still important dependencies of later build
449steps. This is commonly used alongside metadata to propagate file dependencies
450through the build graph and force rebuilds on file modifications.
451
452For example ``pw_docgen`` defines a ``pw_doc_group`` template which outputs
453metadata from a list of input files. The metadata file is not actually part of
454the build, and so changes to any of the input files do not trigger a rebuild.
455This is problematic, as targets that depend on the metadata should rebuild when
456the inputs are modified but GN cannot express this dependency.
457
458``pw_input_group`` solves this problem by allowing a list of files to be listed
459in a target that does not output any build artifacts, causing all dependent
460targets to correctly rebuild.
461
462**Arguments**
463
464``pw_input_group`` accepts all arguments that can be passed to a ``group``
465target, as well as requiring one extra:
466
467* ``inputs``: List of input files.
468
469**Example**
470
471.. code-block::
472
473  import("$dir_pw_build/input_group.gni")
474
475  pw_input_group("foo_metadata") {
476    metadata = {
477      files = [
478        "x.foo",
479        "y.foo",
480        "z.foo",
481      ]
482    }
483    inputs = metadata.files
484  }
485
486Targets depending on ``foo_metadata`` will rebuild when any of the ``.foo``
487files are modified.
488
489pw_zip
490------
491``pw_zip`` is a target that allows users to zip up a set of input files and
492directories into a single output ``.zip`` file—a simple automation of a
493potentially repetitive task.
494
495**Arguments**
496
497* ``inputs``: List of source files as well as the desired relative zip
498  destination. See below for the input syntax.
499* ``dirs``: List of entire directories to be zipped as well as the desired
500  relative zip destination. See below for the input syntax.
501* ``output``: Filename of output ``.zip`` file.
502* ``deps``: List of dependencies for the target.
503
504**Input Syntax**
505
506Inputs all need to follow the correct syntax:
507
508#. Path to source file or directory. Directories must end with a ``/``.
509#. The delimiter (defaults to ``>``).
510#. The desired destination of the contents within the ``.zip``. Must start
511   with ``/`` to indicate the zip root. Any number of subdirectories are
512   allowed. If the source is a file it can be put into any subdirectory of the
513   root. If the source is a file, the zip copy can also be renamed by ending
514   the zip destination with a filename (no trailing ``/``).
515
516Thus, it should look like the following: ``"[source file or dir] > /"``.
517
518**Example**
519
520Let's say we have the following structure for a ``//source/`` directory:
521
522.. code-block::
523
524  source/
525  ├── file1.txt
526  ├── file2.txt
527  ├── file3.txt
528  └── some_dir/
529      ├── file4.txt
530      └── some_other_dir/
531          └── file5.txt
532
533And we create the following build target:
534
535.. code-block::
536
537  import("$dir_pw_build/zip.gni")
538
539  pw_zip("target_name") {
540    inputs = [
541      "//source/file1.txt > /",             # Copied to the zip root dir.
542      "//source/file2.txt > /renamed.txt",  # File renamed.
543      "//source/file3.txt > /bar/",         # File moved to the /bar/ dir.
544    ]
545
546    dirs = [
547      "//source/some_dir/ > /bar/some_dir/",  # All /some_dir/ contents copied
548                                              # as /bar/some_dir/.
549    ]
550
551    # Note on output: if the specific output directory isn't defined
552    # (such as output = "zoo.zip") then the .zip will output to the
553    # same directory as the BUILD.gn file that called the target.
554    output = "//$target_out_dir/foo.zip"  # Where the foo.zip will end up
555  }
556
557This will result in a ``.zip`` file called ``foo.zip`` stored in
558``//$target_out_dir`` with the following structure:
559
560.. code-block::
561
562  foo.zip
563  ├── bar/
564  │   ├── file3.txt
565  │   └── some_dir/
566  │       ├── file4.txt
567  │       └── some_other_dir/
568  │           └── file5.txt
569  ├── file1.txt
570  └── renamed.txt
571
572.. _module-pw_build-relative-source-file-names:
573
574pw_relative_source_file_names
575-----------------------------
576This template recursively walks the listed dependencies and collects the names
577of all the headers and source files required by the targets, and then transforms
578them such that they reflect the ``__FILE__`` when pw_build's ``relative_paths``
579config is applied. This is primarily intended for side-band generation of
580pw_tokenizer tokens so file name tokens can be utilized in places where
581pw_tokenizer is unable to embed token information as part of C/C++ compilation.
582
583This template produces a JSON file containing an array of strings (file paths
584with ``-ffile-prefix-map``-like transformations applied) that can be used to
585:ref:`generate a token database <module-pw_tokenizer-database-creation>`.
586
587**Arguments**
588
589* ``deps``: A required list of targets to recursively extract file names from.
590* ``outputs``: A required array with a single element: the path to write the
591  final JSON file to.
592
593**Example**
594
595Let's say we have the following project structure:
596
597.. code-block::
598
599  project root
600  ├── foo/
601  │   ├── foo.h
602  │   └── foo.cc
603  ├── bar/
604  │   ├── bar.h
605  │   └── bar.cc
606  ├── unused/
607  │   ├── unused.h
608  │   └── unused.cc
609  └── main.cc
610
611And a BUILD.gn at the root:
612
613.. code-block::
614
615  pw_source_set("bar") {
616    public_configs = [ ":bar_headers" ]
617    public = [ "bar/bar.h" ]
618    sources = [ "bar/bar.cc" ]
619  }
620
621  pw_source_set("foo") {
622    public_configs = [ ":foo_headers" ]
623    public = [ "foo/foo.h" ]
624    sources = [ "foo/foo.cc" ]
625    deps = [ ":bar" ]
626  }
627
628
629  pw_source_set("unused") {
630    public_configs = [ ":unused_headers" ]
631    public = [ "unused/unused.h" ]
632    sources = [ "unused/unused.cc" ]
633    deps = [ ":bar" ]
634  }
635
636  pw_executable("main") {
637    sources = [ "main.cc" ]
638    deps = [ ":foo" ]
639  }
640
641  pw_relative_source_file_names("main_source_files") {
642    deps = [ ":main" ]
643    outputs = [ "$target_gen_dir/main_source_files.json" ]
644  }
645
646The json file written to `out/gen/main_source_files.json` will contain:
647
648.. code-block::
649
650  [
651    "bar/bar.cc",
652    "bar/bar.h",
653    "foo/foo.cc",
654    "foo/foo.h",
655    "main.cc"
656  ]
657
658Since ``unused`` isn't a transitive dependency of ``main``, its source files
659are not included. Similarly, even though ``bar`` is not a direct dependency of
660``main``, its source files *are* included because ``foo`` brings in ``bar`` as
661a transitive dependency.
662
663Note how the file paths in this example are relative to the project root rather
664than being absolute paths (e.g. ``/home/user/ralph/coding/my_proj/main.cc``).
665This is a result of transformations applied to strip absolute pathing prefixes,
666matching the behavior of pw_build's ``$dir_pw_build:relative_paths`` config.
667
668Build time errors: pw_error and pw_build_assert
669-----------------------------------------------
670In Pigweed's complex, multi-toolchain GN build it is not possible to build every
671target in every configuration. GN's ``assert`` statement is not ideal for
672enforcing the correct configuration because it may prevent the GN build files or
673targets from being referred to at all, even if they aren't used.
674
675The ``pw_error`` GN template results in an error if it is executed during the
676build. These error targets can exist in the build graph, but cannot be depended
677on without an error.
678
679``pw_build_assert`` evaluates to a ``pw_error`` if a condition fails or nothing
680(an empty group) if the condition passes. Targets can add a dependency on a
681``pw_build_assert`` to enforce a condition at build time.
682
683The templates for build time errors are defined in ``pw_build/error.gni``.
684
685CMake
686=====
687Pigweed's `CMake`_ support is provided primarily for projects that have an
688existing CMake build and wish to integrate Pigweed without switching to a new
689build system.
690
691The following command generates Ninja build files for a host build in the
692``out/cmake_host`` directory:
693
694.. code-block:: sh
695
696  cmake -B out/cmake_host -S "$PW_ROOT" -G Ninja -DCMAKE_TOOLCHAIN_FILE=$PW_ROOT/pw_toolchain/host_clang/toolchain.cmake
697
698The ``PW_ROOT`` environment variable must point to the root of the Pigweed
699directory. This variable is set by Pigweed's environment setup.
700
701Tests can be executed with the ``pw_run_tests.GROUP`` targets. To run Pigweed
702module tests, execute ``pw_run_tests.modules``:
703
704.. code-block:: sh
705
706  ninja -C out/cmake_host pw_run_tests.modules
707
708:ref:`module-pw_watch` supports CMake, so you can also run
709
710.. code-block:: sh
711
712  pw watch -C out/cmake_host pw_run_tests.modules
713
714CMake functions
715---------------
716CMake convenience functions are defined in ``pw_build/pigweed.cmake``.
717
718* ``pw_auto_add_simple_module`` -- For modules with only one library,
719  automatically declare the library and its tests.
720* ``pw_auto_add_module_tests`` -- Create test targets for all tests in a module.
721* ``pw_add_facade`` -- Declare a module facade.
722* ``pw_set_backend`` -- Set the backend library to use for a facade.
723* ``pw_add_module_library`` -- Add a library that is part of a module.
724* ``pw_add_test`` -- Declare a test target.
725
726See ``pw_build/pigweed.cmake`` for the complete documentation of these
727functions.
728
729Special libraries that do not fit well with these functions are created with the
730standard CMake functions, such as ``add_library`` and ``target_link_libraries``.
731
732Facades and backends
733--------------------
734The CMake build uses CMake cache variables for configuring
735:ref:`facades<docs-module-structure-facades>` and backends. Cache variables are
736similar to GN's build args set with ``gn args``. Unlike GN, CMake does not
737support multi-toolchain builds, so these variables have a single global value
738per build directory.
739
740The ``pw_add_facade`` function declares a cache variable named
741``<module_name>_BACKEND`` for each facade. Cache variables can be awkward to
742work with, since their values only change when they're assigned, but then
743persist accross CMake invocations. These variables should be set in one of the
744following ways:
745
746* Call ``pw_set_backend`` to set backends appropriate for the target in the
747  target's toolchain file. The toolchain file is provided to ``cmake`` with
748  ``-DCMAKE_TOOLCHAIN_FILE=<toolchain file>``.
749* Call ``pw_set_backend`` in the top-level ``CMakeLists.txt`` before other
750  CMake code executes.
751* Set the backend variable at the command line with the ``-D`` option.
752
753  .. code-block:: sh
754
755    cmake -B out/cmake_host -S "$PW_ROOT" -G Ninja \
756        -DCMAKE_TOOLCHAIN_FILE=$PW_ROOT/pw_toolchain/host_clang/toolchain.cmake \
757        -Dpw_log_BACKEND=pw_log_basic
758
759* Temporarily override a backend by setting it interactively with ``ccmake`` or
760  ``cmake-gui``.
761
762If the backend is set to a build target that does not exist, there will be an
763error message like the following:
764
765.. code-block::
766
767  CMake Error at pw_build/pigweed.cmake:244 (add_custom_target):
768  Error evaluating generator expression:
769
770    $<TARGET_PROPERTY:my_backend_that_does_not_exist,TYPE>
771
772  Target "my_backend_that_does_not_exist" not found.
773
774Toolchain setup
775---------------
776In CMake, the toolchain is configured by setting CMake variables, as described
777in the `CMake documentation <https://cmake.org/cmake/help/latest/manual/cmake-toolchains.7.html>`_.
778These variables are typically set in a toolchain CMake file passed to ``cmake``
779with the ``-D`` option (``-DCMAKE_TOOLCHAIN_FILE=path/to/file.cmake``).
780For Pigweed embedded builds, set ``CMAKE_SYSTEM_NAME`` to the empty string
781(``""``).
782
783Toolchains may set the ``pw_build_WARNINGS`` variable to a list of ``INTERFACE``
784libraries with compilation options for Pigweed's upstream libraries. This
785defaults to a strict set of warnings. Projects may need to use less strict
786compilation warnings to compile backends exposed to Pigweed code (such as
787``pw_log``) that cannot compile with Pigweed's flags. If desired, Projects can
788access these warnings by depending on ``pw_build.warnings``.
789
790Third party libraries
791---------------------
792The CMake build includes third-party libraries similarly to the GN build. A
793``dir_pw_third_party_<library>`` cache variable is defined for each third-party
794dependency. The variable must be set to the absolute path of the library in
795order to use it. If the variable is empty
796(``if("${dir_pw_third_party_<library>}" STREQUAL "")``), the dependency is not
797available.
798
799Third-party dependencies are not automatically added to the build. They can be
800manually added with ``add_subdirectory`` or by setting the
801``pw_third_party_<library>_ADD_SUBDIRECTORY`` option to ``ON``.
802
803Third party variables are set like any other cache global variable in CMake. It
804is recommended to set these in one of the following ways:
805
806* Set with the CMake ``set`` function in the toolchain file or a
807  ``CMakeLists.txt`` before other CMake code executes.
808
809  .. code-block:: cmake
810
811    set(dir_pw_third_party_nanopb ${CMAKE_CURRENT_SOURCE_DIR}/external/nanopb CACHE PATH "" FORCE)
812
813* Set the variable at the command line with the ``-D`` option.
814
815  .. code-block:: sh
816
817    cmake -B out/cmake_host -S "$PW_ROOT" -G Ninja \
818        -DCMAKE_TOOLCHAIN_FILE=$PW_ROOT/pw_toolchain/host_clang/toolchain.cmake \
819        -Ddir_pw_third_party_nanopb=/path/to/nanopb
820
821* Set the variable interactively with ``ccmake`` or ``cmake-gui``.
822
823Use Pigweed from an existing CMake project
824------------------------------------------
825To use Pigweed libraries form a CMake-based project, simply include the Pigweed
826repository from a ``CMakeLists.txt``.
827
828.. code-block:: cmake
829
830  add_subdirectory(path/to/pigweed pigweed)
831
832All module libraries will be available as ``module_name`` or
833``module_name.sublibrary``.
834
835If desired, modules can be included individually.
836
837.. code-block:: cmake
838
839  add_subdirectory(path/to/pigweed/pw_some_module pw_some_module)
840  add_subdirectory(path/to/pigweed/pw_another_module pw_another_module)
841
842Bazel
843=====
844Bazel is currently very experimental, and only builds for host and ARM Cortex-M
845microcontrollers.
846
847The common configuration for Bazel for all modules is in the ``pigweed.bzl``
848file. The built-in Bazel rules ``cc_binary``, ``cc_library``, and ``cc_test``
849are wrapped with ``pw_cc_binary``, ``pw_cc_library``, and ``pw_cc_test``.
850These wrappers add parameters to calls to the compiler and linker.
851
852In addition to wrapping the built-in rules, Pigweed also provides a custom
853rule for handling linker scripts with Bazel. e.g.
854
855.. code-block:: python
856
857  pw_linker_script(
858    name = "some_linker_script",
859    linker_script = ":some_configurable_linker_script.ld",
860    defines = [
861        "PW_BOOT_FLASH_BEGIN=0x08000200",
862        "PW_BOOT_FLASH_SIZE=1024K",
863        "PW_BOOT_HEAP_SIZE=112K",
864        "PW_BOOT_MIN_STACK_SIZE=1K",
865        "PW_BOOT_RAM_BEGIN=0x20000000",
866        "PW_BOOT_RAM_SIZE=192K",
867        "PW_BOOT_VECTOR_TABLE_BEGIN=0x08000000",
868        "PW_BOOT_VECTOR_TABLE_SIZE=512",
869    ],
870  )
871
872  pw_cc_binary(
873    name = "some_binary",
874    srcs = ["some_source.c"],
875    additional_linker_inputs = [":some_linker_script"],
876    linkopts = ["-T $(location :some_linker_script)"],
877  )
878
879Currently Pigweed is making use of a set of
880`open source <https://github.com/silvergasp/bazel-embedded>`_ toolchains. The
881host builds are only supported on Linux/Mac based systems. Additionally the
882host builds are not entirely hermetic, and will make use of system
883libraries and headers. This is close to the default configuration for Bazel,
884though slightly more hermetic. The host toolchain is based around clang-11 which
885has a system dependency on 'libtinfo.so.5' which is often included as part of
886the libncurses packages. On Debian based systems this can be installed using the
887command below:
888
889.. code-block:: sh
890
891  sudo apt install libncurses5
892
893The host toolchain does not currently support native Windows, though using WSL
894is a viable alternative.
895
896The ARM Cortex-M Bazel toolchains are based around gcc-arm-non-eabi and are
897entirely hermetic. You can target Cortex-M, by using the platforms command line
898option. This set of toolchains is supported from hosts; Windows, Mac and Linux.
899The platforms that are currently supported are listed below:
900
901.. code-block:: sh
902
903  bazel build //:your_target --platforms=@pigweed//pw_build/platforms:cortex_m0
904  bazel build //:your_target --platforms=@pigweed//pw_build/platforms:cortex_m1
905  bazel build //:your_target --platforms=@pigweed//pw_build/platforms:cortex_m3
906  bazel build //:your_target --platforms=@pigweed//pw_build/platforms:cortex_m4
907  bazel build //:your_target --platforms=@pigweed//pw_build/platforms:cortex_m7
908  bazel build //:your_target \
909    --platforms=@pigweed//pw_build/platforms:cortex_m4_fpu
910  bazel build //:your_target \
911    --platforms=@pigweed//pw_build/platforms:cortex_m7_fpu
912
913
914The above examples are cpu/fpu oriented platforms and can be used where
915applicable for your application. There some more specific platforms for the
916types of boards that are included as examples in Pigweed. It is strongly
917encouraged that you create your own set of platforms specific for your project,
918that implement the constraint_settings in this repository. e.g.
919
920New board constraint_value:
921
922.. code-block:: python
923
924  #your_repo/build_settings/constraints/board/BUILD
925  constraint_value(
926    name = "nucleo_l432kc",
927    constraint_setting = "@pigweed//pw_build/constraints/board",
928  )
929
930New chipset constraint_value:
931
932.. code-block:: python
933
934  # your_repo/build_settings/constraints/chipset/BUILD
935  constraint_value(
936    name = "stm32l432kc",
937    constraint_setting = "@pigweed//pw_build/constraints/chipset",
938  )
939
940New platforms for chipset and board:
941
942.. code-block:: python
943
944  #your_repo/build_settings/platforms/BUILD
945  # Works with all stm32l432kc
946  platforms(
947    name = "stm32l432kc",
948    parents = ["@pigweed//pw_build/platforms:cortex_m4"],
949    constraint_values =
950      ["@your_repo//build_settings/constraints/chipset:stm32l432kc"],
951  )
952
953  # Works with only the nucleo_l432kc
954  platforms(
955    name = "nucleo_l432kc",
956    parents = [":stm32l432kc"],
957    constraint_values =
958      ["@your_repo//build_settings/constraints/board:nucleo_l432kc"],
959  )
960
961In the above example you can build your code with the command line:
962
963.. code-block:: python
964
965  bazel build //:your_target_for_nucleo_l432kc \
966    --platforms=@your_repo//build_settings:nucleo_l432kc
967
968
969You can also specify that a specific target is only compatible with one
970platform:
971
972.. code-block:: python
973
974  cc_library(
975    name = "compatible_with_all_stm32l432kc",
976    srcs = ["tomato_src.c"],
977    target_compatible_with =
978      ["@your_repo//build_settings/constraints/chipset:stm32l432kc"],
979  )
980
981  cc_library(
982    name = "compatible_with_only_nucleo_l432kc",
983    srcs = ["bbq_src.c"],
984    target_compatible_with =
985      ["@your_repo//build_settings/constraints/board:nucleo_l432kc"],
986  )
987
988