• 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
40Build system philosophies
41-------------------------
42While Pigweed's GN build is not hermetic, it strives to adhere to principles of
43`hermeticity <https://bazel.build/concepts/hermeticity>`_. Some guidelines to
44move towards the ideal of hermeticity include:
45
46* Only rely on pre-compiled tools provided by CIPD (or some other versioned,
47  pre-compiled binary distribution mechanism). This eliminates build artifact
48  differences caused by different tool versions or variations (e.g. same tool
49  version built with slightly different compilation flags).
50* Do not use absolute paths in Ninja commands. Typically, these appear when
51  using ``rebase_path("//path/to/my_script.py")``. Most of the time, Ninja
52  steps should be passed paths rebased relative to the build directory (i.e.
53  ``rebase_path("//path/to/my_script.py", root_build_dir)``). This ensures build
54  commands are the same across different machines.
55* Prevent produced artifacts from relying on or referencing system state. This
56  includes time stamps, writing absolute paths to generated artifacts, or
57  producing artifacts that reference system state in a way that prevents them
58  from working the same way on a different machine.
59* Isolate build actions to the build directory. In general, the build system
60  should not add or modify files outside of the build directory. This can cause
61  confusion to users, and makes the concept of a clean build more ambiguous.
62
63Target types
64------------
65.. code-block::
66
67  import("$dir_pw_build/target_types.gni")
68
69  pw_source_set("my_library") {
70    sources = [ "lib.cc" ]
71  }
72
73Pigweed defines wrappers around the four basic GN binary types ``source_set``,
74``executable``, ``static_library``, and ``shared_library``. These templates
75do several things:
76
77#. **Add default configs/deps**
78
79  Rather than binding the majority of compiler flags related to C++ standard,
80  cross-compilation, warning/error policy, etc. directly to toolchain
81  invocations, these flags are applied as configs to all ``pw_*`` C/C++ target
82  types. The primary motivations for this are to allow some targets to modify
83  the default set of flags when needed by specifying ``remove_configs``, and to
84  reduce the complexity of building novel toolchains.
85
86  Pigweed's global default configs are set in ``pw_build/default.gni``, and
87  individual platform-specific toolchains extend the list by appending to the
88  ``default_configs`` build argument.
89
90  Default deps were added to support polyfill, which has since been
91  deprecated. Default dependency functionality continues to exist for
92  backwards compatibility.
93
94#. **Optionally add link-time binding**
95
96  Some libraries like pw_assert and pw_log are borderline impossible to
97  implement well without introducing circular dependencies. One solution for
98  addressing this is to break apart the libraries into an interface with
99  minimal dependencies, and an implementation with the bulk of the
100  dependencies that would typically create dependency cycles. In order for the
101  implementation to be linked in, it must be added to the dependency tree of
102  linked artifacts (e.g. ``pw_executable``, ``pw_static_library``). Since
103  there's no way for the libraries themselves to just happily pull in the
104  implementation if someone depends on the interface, the implementation is
105  instead late-bound by adding it as a direct dependency of the final linked
106  artifact. This is all managed through ``pw_build_LINK_DEPS``, which is global
107  for each toolchain and applied to every ``pw_executable``,
108  ``pw_static_library``, and ``pw_shared_library``.
109
110#. **Apply a default visibility policy**
111
112  Projects can globally control the default visibility of pw_* target types by
113  specifying ``pw_build_DEFAULT_VISIBILITY``. This template applies that as the
114  default visibility for any pw_* targets that do not explicitly specify
115  a visibility.
116
117#. **Add source file names as metadata**
118
119  All source file names are collected as
120  `GN metadata <https://gn.googlesource.com/gn/+/main/docs/reference.md#metadata_collection>`_.
121  This list can be writen to a file at build time using ``generated_file``. The
122  primary use case for this is to generate a token database containing all the
123  source files. This allows PW_ASSERT to emit filename tokens even though it
124  can't add them to the elf file because of the reasons described at
125  :ref:`module-pw_assert-assert-api`.
126
127  .. note::
128    ``pw_source_files``, if not rebased will default to outputing module
129    relative paths from a ``generated_file`` target.  This is likely not
130    useful. Adding a ``rebase`` argument to ``generated_file`` such as
131    ``rebase = root_build_dir`` will result in usable paths.  For an example,
132    see ``//pw_tokenizer/database.gni``'s ``pw_tokenizer_filename_database``
133    template.
134
135The ``pw_executable`` template provides additional functionality around building
136complete binaries. As Pigweed is a collection of libraries, it does not know how
137its final targets are built. ``pw_executable`` solves this by letting each user
138of Pigweed specify a global executable template for their target, and have
139Pigweed build against it. This is controlled by the build variable
140``pw_executable_config.target_type``, specifying the name of the executable
141template for a project.
142
143In some uncommon cases, a project's ``pw_executable`` template definition may
144need to stamp out some ``pw_source_set``\s. Since a pw_executable template can't
145import ``$dir_pw_build/target_types.gni`` due to circular imports, it should
146import ``$dir_pw_build/cc_library.gni`` instead.
147
148.. tip::
149
150  Prefer to use ``pw_executable`` over plain ``executable`` targets to allow
151  cleanly building the same code for multiple target configs.
152
153**Arguments**
154
155All of the ``pw_*`` target type overrides accept any arguments supported by
156the underlying native types, as they simply forward them through to the
157underlying target.
158
159Additionally, the following arguments are also supported:
160
161* **remove_configs**: (optional) A list of configs / config patterns to remove
162  from the set of default configs specified by the current toolchain
163  configuration.
164* **remove_public_deps**: (optional) A list of targets to remove from the set of
165  default public_deps specified by the current toolchain configuration.
166
167.. _module-pw_build-link-deps:
168
169Link-only deps
170--------------
171It may be necessary to specify additional link-time dependencies that may not be
172explicitly depended on elsewhere in the build. One example of this is a
173``pw_assert`` backend, which may need to leave out dependencies to avoid
174circular dependencies. Its dependencies need to be linked for executables and
175libraries, even if they aren't pulled in elsewhere.
176
177The ``pw_build_LINK_DEPS`` build arg is a list of dependencies to add to all
178``pw_executable``, ``pw_static_library``, and ``pw_shared_library`` targets.
179This should only be used as a last resort when dependencies cannot be properly
180expressed in the build.
181
182Python packages
183---------------
184GN templates for :ref:`Python build automation <docs-python-build>` are
185described in :ref:`module-pw_build-python`.
186
187.. toctree::
188  :hidden:
189
190  python
191
192
193.. _module-pw_build-cc_blob_library:
194
195pw_cc_blob_library
196------------------
197The ``pw_cc_blob_library`` template is useful for embedding binary data into a
198program. The template takes in a mapping of symbol names to file paths, and
199generates a set of C++ source and header files that embed the contents of the
200passed-in files as arrays of ``std::byte``.
201
202The blob byte arrays are constant initialized and are safe to access at any
203time, including before ``main()``.
204
205``pw_cc_blob_library`` is also available in the CMake build. It is provided by
206``pw_build/cc_blob_library.cmake``.
207
208**Arguments**
209
210* ``blobs``: A list of GN scopes, where each scope corresponds to a binary blob
211  to be transformed from file to byte array. This is a required field. Blob
212  fields include:
213
214  * ``symbol_name``: The C++ symbol for the byte array.
215  * ``file_path``: The file path for the binary blob.
216  * ``linker_section``: If present, places the byte array in the specified
217    linker section.
218  * ``alignas``: If present, uses the specified string or integer verbatim in
219    the ``alignas()`` specifier for the byte array.
220
221* ``out_header``: The header file to generate. Users will include this file
222  exactly as it is written here to reference the byte arrays.
223* ``namespace``: An optional (but highly recommended!) C++ namespace to place
224  the generated blobs within.
225
226Example
227^^^^^^^
228
229**BUILD.gn**
230
231.. code-block::
232
233  pw_cc_blob_library("foo_bar_blobs") {
234    blobs: [
235      {
236        symbol_name: "kFooBlob"
237        file_path: "${target_out_dir}/stuff/bin/foo.bin"
238      },
239      {
240        symbol_name: "kBarBlob"
241        file_path: "//stuff/bin/bar.bin"
242        linker_section: ".bar_section"
243      },
244    ]
245    out_header: "my/stuff/foo_bar_blobs.h"
246    namespace: "my::stuff"
247    deps = [ ":generate_foo_bin" ]
248  }
249
250.. note:: If the binary blobs are generated as part of the build, be sure to
251          list them as deps to the pw_cc_blob_library target.
252
253**Generated Header**
254
255.. code-block::
256
257  #pragma once
258
259  #include <array>
260  #include <cstddef>
261
262  namespace my::stuff {
263
264  extern const std::array<std::byte, 100> kFooBlob;
265
266  extern const std::array<std::byte, 50> kBarBlob;
267
268  }  // namespace my::stuff
269
270**Generated Source**
271
272.. code-block::
273
274  #include "my/stuff/foo_bar_blobs.h"
275
276  #include <array>
277  #include <cstddef>
278
279  #include "pw_preprocessor/compiler.h"
280
281  namespace my::stuff {
282
283  const std::array<std::byte, 100> kFooBlob = { ... };
284
285  PW_PLACE_IN_SECTION(".bar_section")
286  const std::array<std::byte, 50> kBarBlob = { ... };
287
288  }  // namespace my::stuff
289
290.. _module-pw_build-facade:
291
292pw_facade
293---------
294In their simplest form, a :ref:`facade<docs-module-structure-facades>` is a GN
295build arg used to change a dependency at compile time. Pigweed targets configure
296these facades as needed.
297
298The ``pw_facade`` template bundles a ``pw_source_set`` with a facade build arg.
299This allows the facade to provide header files, compilation options or anything
300else a GN ``source_set`` provides.
301
302The ``pw_facade`` template declares two targets:
303
304* ``$target_name``: the public-facing ``pw_source_set``, with a ``public_dep``
305  on the backend
306* ``$target_name.facade``: target used by the backend to avoid circular
307  dependencies
308
309.. code-block::
310
311  # Declares ":foo" and ":foo.facade" GN targets
312  pw_facade("foo") {
313    backend = pw_log_BACKEND
314    public_configs = [ ":public_include_path" ]
315    public = [ "public/pw_foo/foo.h" ]
316  }
317
318Low-level facades like ``pw_assert`` cannot express all of their dependencies
319due to the potential for dependency cycles. Facades with this issue may require
320backends to place their implementations in a separate build target to be listed
321in ``pw_build_LINK_DEPS`` (see :ref:`module-pw_build-link-deps`). The
322``require_link_deps`` variable in ``pw_facade`` asserts that all specified build
323targets are present in ``pw_build_LINK_DEPS`` if the facade's backend variable
324is set.
325
326.. _module-pw_build-python-action:
327
328pw_python_action
329----------------
330The ``pw_python_action`` template is a convenience wrapper around GN's `action
331function <https://gn.googlesource.com/gn/+/main/docs/reference.md#func_action>`_
332for running Python scripts. The main benefit it provides is resolution of GN
333target labels to compiled binary files. This allows Python scripts to be written
334independently of GN, taking only filesystem paths as arguments.
335
336Another convenience provided by the template is to allow running scripts without
337any outputs. Sometimes scripts run in a build do not directly produce output
338files, but GN requires that all actions have an output. ``pw_python_action``
339solves this by accepting a boolean ``stamp`` argument which tells it to create a
340placeholder output file for the action.
341
342**Arguments**
343
344``pw_python_action`` accepts all of the arguments of a regular ``action``
345target. Additionally, it has some of its own arguments:
346
347* ``module``: Run the specified Python module instead of a script. Either
348  ``script`` or ``module`` must be specified, but not both.
349* ``capture_output``: Optional boolean. If true, script output is hidden unless
350  the script fails with an error. Defaults to true.
351* ``stamp``: Optional variable indicating whether to automatically create a
352  placeholder output file for the script. This allows running scripts without
353  specifying ``outputs``. If ``stamp`` is true, a generic output file is
354  used. If ``stamp`` is a file path, that file is used as a stamp file. Like any
355  output file, ``stamp`` must be in the build directory. Defaults to false.
356* ``environment``: Optional list of strings. Environment variables to set,
357  passed as NAME=VALUE strings.
358* ``working_directory``: Optional file path. When provided the current working
359  directory will be set to this location before the Python module or script is
360  run.
361* ``command_launcher``: Optional string. Arguments to prepend to the Python
362  command, e.g. ``'/usr/bin/fakeroot --'`` will run the Python script within a
363  fakeroot environment.
364* ``venv``: Optional gn target of the pw_python_venv that should be used to run
365  this action.
366
367.. _module-pw_build-python-action-expressions:
368
369Expressions
370^^^^^^^^^^^
371
372``pw_python_action`` evaluates expressions in ``args``, the arguments passed to
373the script. These expressions function similarly to generator expressions in
374CMake. Expressions may be passed as a standalone argument or as part of another
375argument. A single argument may contain multiple expressions.
376
377Generally, these expressions are used within templates rather than directly in
378BUILD.gn files. This allows build code to use GN labels without having to worry
379about converting them to files.
380
381.. note::
382
383  We intend to replace these expressions with native GN features when possible.
384  See `b/234886742 <http://issuetracker.google.com/234886742>`_.
385
386The following expressions are supported:
387
388.. describe:: <TARGET_FILE(gn_target)>
389
390  Evaluates to the output file of the provided GN target. For example, the
391  expression
392
393  .. code-block::
394
395    "<TARGET_FILE(//foo/bar:static_lib)>"
396
397  might expand to
398
399  .. code-block::
400
401    "/home/User/project_root/out/obj/foo/bar/static_lib.a"
402
403  ``TARGET_FILE`` parses the ``.ninja`` file for the GN target, so it should
404  always find the correct output file, regardless of the toolchain's or target's
405  configuration. Some targets, such as ``source_set`` and ``group`` targets, do
406  not have an output file, and attempting to use ``TARGET_FILE`` with them
407  results in an error.
408
409  ``TARGET_FILE`` only resolves GN target labels to their outputs. To resolve
410  paths generally, use the standard GN approach of applying the
411  ``rebase_path(path, root_build_dir)`` function. This function
412  converts the provided GN path or list of paths to be relative to the build
413  directory, from which all build commands and scripts are executed.
414
415.. describe:: <TARGET_FILE_IF_EXISTS(gn_target)>
416
417  ``TARGET_FILE_IF_EXISTS`` evaluates to the output file of the provided GN
418  target, if the output file exists. If the output file does not exist, the
419  entire argument that includes this expression is omitted, even if there is
420  other text or another expression.
421
422  For example, consider this expression:
423
424  .. code-block::
425
426    "--database=<TARGET_FILE_IF_EXISTS(//alpha/bravo)>"
427
428  If the ``//alpha/bravo`` target file exists, this might expand to the
429  following:
430
431  .. code-block::
432
433    "--database=/home/User/project/out/obj/alpha/bravo/bravo.elf"
434
435  If the ``//alpha/bravo`` target file does not exist, the entire
436  ``--database=`` argument is omitted from the script arguments.
437
438.. describe:: <TARGET_OBJECTS(gn_target)>
439
440  Evaluates to the object files of the provided GN target. Expands to a separate
441  argument for each object file. If the target has no object files, the argument
442  is omitted entirely. Because it does not expand to a single expression, the
443  ``<TARGET_OBJECTS(...)>`` expression may not have leading or trailing text.
444
445  For example, the expression
446
447  .. code-block::
448
449    "<TARGET_OBJECTS(//foo/bar:a_source_set)>"
450
451  might expand to multiple separate arguments:
452
453  .. code-block::
454
455    "/home/User/project_root/out/obj/foo/bar/a_source_set.file_a.cc.o"
456    "/home/User/project_root/out/obj/foo/bar/a_source_set.file_b.cc.o"
457    "/home/User/project_root/out/obj/foo/bar/a_source_set.file_c.cc.o"
458
459**Example**
460
461.. code-block::
462
463  import("$dir_pw_build/python_action.gni")
464
465  pw_python_action("postprocess_main_image") {
466    script = "py/postprocess_binary.py"
467    args = [
468      "--database",
469      rebase_path("my/database.csv", root_build_dir),
470      "--binary=<TARGET_FILE(//firmware/images:main)>",
471    ]
472    stamp = true
473  }
474
475.. _module-pw_build-evaluate-path-expressions:
476
477pw_evaluate_path_expressions
478----------------------------
479It is not always feasible to pass information to a script through command line
480arguments. If a script requires a large amount of input data, writing to a file
481is often more convenient. However, doing so bypasses ``pw_python_action``'s GN
482target label resolution, preventing such scripts from working with build
483artifacts in a build system-agnostic manner.
484
485``pw_evaluate_path_expressions`` is designed to address this use case. It takes
486a list of input files and resolves target expressions within them, modifying the
487files in-place.
488
489Refer to ``pw_python_action``'s :ref:`module-pw_build-python-action-expressions`
490section for the list of supported expressions.
491
492.. note::
493
494  ``pw_evaluate_path_expressions`` is typically used as an intermediate
495  sub-target of a larger template, rather than a standalone build target.
496
497**Arguments**
498
499* ``files``: A list of scopes, each containing a ``source`` file to process and
500  a ``dest`` file to which to write the result.
501
502**Example**
503
504The following template defines an executable target which additionally outputs
505the list of object files from which it was compiled, making use of
506``pw_evaluate_path_expressions`` to resolve their paths.
507
508.. code-block::
509
510  import("$dir_pw_build/evaluate_path_expressions.gni")
511
512  template("executable_with_artifacts") {
513    executable("${target_name}.exe") {
514      sources = invoker.sources
515      if defined(invoker.deps) {
516        deps = invoker.deps
517      }
518    }
519
520    _artifacts_input = "$target_gen_dir/${target_name}_artifacts.json.in"
521    _artifacts_output = "$target_gen_dir/${target_name}_artifacts.json"
522    _artifacts = {
523      binary = "<TARGET_FILE(:${target_name}.exe)>"
524      objects = "<TARGET_OBJECTS(:${target_name}.exe)>"
525    }
526    write_file(_artifacts_input, _artifacts, "json")
527
528    pw_evaluate_path_expressions("${target_name}.evaluate") {
529      files = [
530        {
531          source = _artifacts_input
532          dest = _artifacts_output
533        },
534      ]
535    }
536
537    group(target_name) {
538      deps = [
539        ":${target_name}.exe",
540        ":${target_name}.evaluate",
541      ]
542    }
543  }
544
545.. _module-pw_build-pw_exec:
546
547pw_exec
548-------
549``pw_exec`` allows for execution of arbitrary programs. It is a wrapper around
550``pw_python_action`` but allows for specifying the program to execute.
551
552.. note:: Prefer to use ``pw_python_action`` instead of calling out to shell
553  scripts, as the python will be more portable. ``pw_exec`` should generally
554  only be used for interacting with legacy/existing scripts.
555
556**Arguments**
557
558* ``program``: The program to run. Can be a full path or just a name (in which
559  case $PATH is searched).
560* ``args``: Optional list of arguments to the program.
561* ``deps``: Dependencies for this target.
562* ``public_deps``: Public dependencies for this target. In addition to outputs
563  from this target, outputs generated by public dependencies can be used as
564  inputs from targets that depend on this one. This is not the case for private
565  deps.
566* ``inputs``: Optional list of build inputs to the program.
567* ``outputs``: Optional list of artifacts produced by the program's execution.
568* ``env``: Optional list of key-value pairs defining environment variables for
569  the program.
570* ``env_file``: Optional path to a file containing a list of newline-separated
571  key-value pairs defining environment variables for the program.
572* ``args_file``: Optional path to a file containing additional positional
573  arguments to the program. Each line of the file is appended to the
574  invocation. Useful for specifying arguments from GN metadata.
575* ``skip_empty_args``: If args_file is provided, boolean indicating whether to
576  skip running the program if the file is empty. Used to avoid running
577  commands which error when called without arguments.
578* ``capture_output``: If true, output from the program is hidden unless the
579  program exits with an error. Defaults to true.
580* ``working_directory``: The working directory to execute the subprocess with.
581  If not specified it will not be set and the subprocess will have whatever
582  the parent current working directory is.
583* ``visibility``: GN visibility to apply to the underlying target.
584
585**Example**
586
587.. code-block::
588
589  import("$dir_pw_build/exec.gni")
590
591  pw_exec("hello_world") {
592    program = "/bin/sh"
593    args = [
594      "-c",
595      "echo hello \$WORLD",
596    ]
597    env = [
598      "WORLD=world",
599    ]
600  }
601
602pw_input_group
603--------------
604``pw_input_group`` defines a group of input files which are not directly
605processed by the build but are still important dependencies of later build
606steps. This is commonly used alongside metadata to propagate file dependencies
607through the build graph and force rebuilds on file modifications.
608
609For example ``pw_docgen`` defines a ``pw_doc_group`` template which outputs
610metadata from a list of input files. The metadata file is not actually part of
611the build, and so changes to any of the input files do not trigger a rebuild.
612This is problematic, as targets that depend on the metadata should rebuild when
613the inputs are modified but GN cannot express this dependency.
614
615``pw_input_group`` solves this problem by allowing a list of files to be listed
616in a target that does not output any build artifacts, causing all dependent
617targets to correctly rebuild.
618
619**Arguments**
620
621``pw_input_group`` accepts all arguments that can be passed to a ``group``
622target, as well as requiring one extra:
623
624* ``inputs``: List of input files.
625
626**Example**
627
628.. code-block::
629
630  import("$dir_pw_build/input_group.gni")
631
632  pw_input_group("foo_metadata") {
633    metadata = {
634      files = [
635        "x.foo",
636        "y.foo",
637        "z.foo",
638      ]
639    }
640    inputs = metadata.files
641  }
642
643Targets depending on ``foo_metadata`` will rebuild when any of the ``.foo``
644files are modified.
645
646pw_zip
647------
648``pw_zip`` is a target that allows users to zip up a set of input files and
649directories into a single output ``.zip`` file—a simple automation of a
650potentially repetitive task.
651
652**Arguments**
653
654* ``inputs``: List of source files as well as the desired relative zip
655  destination. See below for the input syntax.
656* ``dirs``: List of entire directories to be zipped as well as the desired
657  relative zip destination. See below for the input syntax.
658* ``output``: Filename of output ``.zip`` file.
659* ``deps``: List of dependencies for the target.
660
661**Input Syntax**
662
663Inputs all need to follow the correct syntax:
664
665#. Path to source file or directory. Directories must end with a ``/``.
666#. The delimiter (defaults to ``>``).
667#. The desired destination of the contents within the ``.zip``. Must start
668   with ``/`` to indicate the zip root. Any number of subdirectories are
669   allowed. If the source is a file it can be put into any subdirectory of the
670   root. If the source is a file, the zip copy can also be renamed by ending
671   the zip destination with a filename (no trailing ``/``).
672
673Thus, it should look like the following: ``"[source file or dir] > /"``.
674
675**Example**
676
677Let's say we have the following structure for a ``//source/`` directory:
678
679.. code-block::
680
681  source/
682  ├── file1.txt
683  ├── file2.txt
684  ├── file3.txt
685  └── some_dir/
686      ├── file4.txt
687      └── some_other_dir/
688          └── file5.txt
689
690And we create the following build target:
691
692.. code-block::
693
694  import("$dir_pw_build/zip.gni")
695
696  pw_zip("target_name") {
697    inputs = [
698      "//source/file1.txt > /",             # Copied to the zip root dir.
699      "//source/file2.txt > /renamed.txt",  # File renamed.
700      "//source/file3.txt > /bar/",         # File moved to the /bar/ dir.
701    ]
702
703    dirs = [
704      "//source/some_dir/ > /bar/some_dir/",  # All /some_dir/ contents copied
705                                              # as /bar/some_dir/.
706    ]
707
708    # Note on output: if the specific output directory isn't defined
709    # (such as output = "zoo.zip") then the .zip will output to the
710    # same directory as the BUILD.gn file that called the target.
711    output = "//$target_out_dir/foo.zip"  # Where the foo.zip will end up
712  }
713
714This will result in a ``.zip`` file called ``foo.zip`` stored in
715``//$target_out_dir`` with the following structure:
716
717.. code-block::
718
719  foo.zip
720  ├── bar/
721  │   ├── file3.txt
722  │   └── some_dir/
723  │       ├── file4.txt
724  │       └── some_other_dir/
725  │           └── file5.txt
726  ├── file1.txt
727  └── renamed.txt
728
729.. _module-pw_build-relative-source-file-names:
730
731pw_relative_source_file_names
732-----------------------------
733This template recursively walks the listed dependencies and collects the names
734of all the headers and source files required by the targets, and then transforms
735them such that they reflect the ``__FILE__`` when pw_build's ``relative_paths``
736config is applied. This is primarily intended for side-band generation of
737pw_tokenizer tokens so file name tokens can be utilized in places where
738pw_tokenizer is unable to embed token information as part of C/C++ compilation.
739
740This template produces a JSON file containing an array of strings (file paths
741with ``-ffile-prefix-map``-like transformations applied) that can be used to
742:ref:`generate a token database <module-pw_tokenizer-database-creation>`.
743
744**Arguments**
745
746* ``deps``: A required list of targets to recursively extract file names from.
747* ``outputs``: A required array with a single element: the path to write the
748  final JSON file to.
749
750**Example**
751
752Let's say we have the following project structure:
753
754.. code-block::
755
756  project root
757  ├── foo/
758  │   ├── foo.h
759  │   └── foo.cc
760  ├── bar/
761  │   ├── bar.h
762  │   └── bar.cc
763  ├── unused/
764  │   ├── unused.h
765  │   └── unused.cc
766  └── main.cc
767
768And a BUILD.gn at the root:
769
770.. code-block::
771
772  pw_source_set("bar") {
773    public_configs = [ ":bar_headers" ]
774    public = [ "bar/bar.h" ]
775    sources = [ "bar/bar.cc" ]
776  }
777
778  pw_source_set("foo") {
779    public_configs = [ ":foo_headers" ]
780    public = [ "foo/foo.h" ]
781    sources = [ "foo/foo.cc" ]
782    deps = [ ":bar" ]
783  }
784
785
786  pw_source_set("unused") {
787    public_configs = [ ":unused_headers" ]
788    public = [ "unused/unused.h" ]
789    sources = [ "unused/unused.cc" ]
790    deps = [ ":bar" ]
791  }
792
793  pw_executable("main") {
794    sources = [ "main.cc" ]
795    deps = [ ":foo" ]
796  }
797
798  pw_relative_source_file_names("main_source_files") {
799    deps = [ ":main" ]
800    outputs = [ "$target_gen_dir/main_source_files.json" ]
801  }
802
803The json file written to `out/gen/main_source_files.json` will contain:
804
805.. code-block::
806
807  [
808    "bar/bar.cc",
809    "bar/bar.h",
810    "foo/foo.cc",
811    "foo/foo.h",
812    "main.cc"
813  ]
814
815Since ``unused`` isn't a transitive dependency of ``main``, its source files
816are not included. Similarly, even though ``bar`` is not a direct dependency of
817``main``, its source files *are* included because ``foo`` brings in ``bar`` as
818a transitive dependency.
819
820Note how the file paths in this example are relative to the project root rather
821than being absolute paths (e.g. ``/home/user/ralph/coding/my_proj/main.cc``).
822This is a result of transformations applied to strip absolute pathing prefixes,
823matching the behavior of pw_build's ``$dir_pw_build:relative_paths`` config.
824
825Build time errors: pw_error and pw_build_assert
826-----------------------------------------------
827In Pigweed's complex, multi-toolchain GN build it is not possible to build every
828target in every configuration. GN's ``assert`` statement is not ideal for
829enforcing the correct configuration because it may prevent the GN build files or
830targets from being referred to at all, even if they aren't used.
831
832The ``pw_error`` GN template results in an error if it is executed during the
833build. These error targets can exist in the build graph, but cannot be depended
834on without an error.
835
836``pw_build_assert`` evaluates to a ``pw_error`` if a condition fails or nothing
837(an empty group) if the condition passes. Targets can add a dependency on a
838``pw_build_assert`` to enforce a condition at build time.
839
840The templates for build time errors are defined in ``pw_build/error.gni``.
841
842Improved Ninja interface
843------------------------
844Ninja includes a basic progress display, showing in a single line the number of
845targets finished, the total number of targets, and the name of the most recent
846target it has either started or finished.
847
848For additional insight into the status of the build, Pigweed includes a Ninja
849wrapper, ``pw-wrap-ninja``, that displays additional real-time information about
850the progress of the build. The wrapper is invoked the same way you'd normally
851invoke Ninja:
852
853.. code-block:: sh
854
855  pw-wrap-ninja -C out
856
857The script lists the progress of the build, as well as the list of targets that
858Ninja is currently building, along with a timer that measures how long each
859target has been building for:
860
861.. code-block::
862
863  [51.3s] Building [8924/10690] ...
864    [10.4s] c++ pw_strict_host_clang_debug/obj/pw_string/string_test.lib.string_test.cc.o
865    [ 9.5s] ACTION //pw_console/py:py.lint.mypy(//pw_build/python_toolchain:python)
866    [ 9.4s] ACTION //pw_console/py:py.lint.pylint(//pw_build/python_toolchain:python)
867    [ 6.1s] clang-tidy ../pw_log_rpc/log_service.cc
868    [ 6.1s] clang-tidy ../pw_log_rpc/log_service_test.cc
869    [ 6.1s] clang-tidy ../pw_log_rpc/rpc_log_drain.cc
870    [ 6.1s] clang-tidy ../pw_log_rpc/rpc_log_drain_test.cc
871    [ 5.4s] c++ pw_strict_host_clang_debug/obj/BUILD_DIR/pw_strict_host_clang_debug/gen/pw...
872    ... and 109 more
873
874This allows you to, at a glance, know what Ninja's currently building, which
875targets are bottlenecking the rest of the build, and which targets are taking
876an unusually long time to complete.
877
878``pw-wrap-ninja`` includes other useful functionality as well. The
879``--write-trace`` option writes a build trace to the specified path, which can
880be viewed in the `Perfetto UI <https://ui.perfetto.dev/>`_, or via Chrome's
881built-in ``chrome://tracing`` tool.
882
883CMake
884=====
885Pigweed's `CMake`_ support is provided primarily for projects that have an
886existing CMake build and wish to integrate Pigweed without switching to a new
887build system.
888
889The following command generates Ninja build files for a host build in the
890``out/cmake_host`` directory:
891
892.. code-block:: sh
893
894  cmake -B out/cmake_host -S "$PW_ROOT" -G Ninja -DCMAKE_TOOLCHAIN_FILE=$PW_ROOT/pw_toolchain/host_clang/toolchain.cmake
895
896The ``PW_ROOT`` environment variable must point to the root of the Pigweed
897directory. This variable is set by Pigweed's environment setup.
898
899Tests can be executed with the ``pw_run_tests.GROUP`` targets. To run Pigweed
900module tests, execute ``pw_run_tests.modules``:
901
902.. code-block:: sh
903
904  ninja -C out/cmake_host pw_run_tests.modules
905
906:ref:`module-pw_watch` supports CMake, so you can also run
907
908.. code-block:: sh
909
910  pw watch -C out/cmake_host pw_run_tests.modules
911
912CMake functions
913---------------
914CMake convenience functions are defined in ``pw_build/pigweed.cmake``.
915
916* ``pw_add_library_generic`` -- The base helper used to instantiate CMake
917  libraries. This is meant for use in downstream projects as upstream Pigweed
918  modules are expected to use ``pw_add_library``.
919* ``pw_add_library`` -- Add an upstream Pigweed library.
920* ``pw_add_facade_generic`` -- The base helper used to instantiate facade
921  libraries. This is meant for use in downstream projects as upstream Pigweed
922  modules are expected to use ``pw_add_facade``.
923* ``pw_add_facade`` -- Declare an upstream Pigweed facade.
924* ``pw_set_backend`` -- Set the backend library to use for a facade.
925* ``pw_add_test_generic`` -- The base helper used to instantiate test targets.
926  This is meant for use in downstrema projects as upstream Pigweed modules are
927  expected to use ``pw_add_test``.
928* ``pw_add_test`` -- Declare an upstream Pigweed test target.
929* ``pw_add_test_group`` -- Declare a target to group and bundle test targets.
930* ``pw_target_link_targets`` -- Helper wrapper around ``target_link_libraries``
931  which only supports CMake targets and detects when the target does not exist.
932  Note that generator expressions are not supported.
933* ``pw_add_global_compile_options`` -- Applies compilation options to all
934  targets in the build. This should only be used to add essential compilation
935  options, such as those that affect the ABI. Use ``pw_add_library`` or
936  ``target_compile_options`` to apply other compile options.
937* ``pw_add_error_target`` -- Declares target which reports a message and causes
938  a build failure only when compiled. This is useful when ``FATAL_ERROR``
939  messages cannot be used to catch problems during the CMake configuration
940  phase.
941* ``pw_parse_arguments`` -- Helper to parse CMake function arguments.
942
943See ``pw_build/pigweed.cmake`` for the complete documentation of these
944functions.
945
946Special libraries that do not fit well with these functions are created with the
947standard CMake functions, such as ``add_library`` and ``target_link_libraries``.
948
949Facades and backends
950--------------------
951The CMake build uses CMake cache variables for configuring
952:ref:`facades<docs-module-structure-facades>` and backends. Cache variables are
953similar to GN's build args set with ``gn args``. Unlike GN, CMake does not
954support multi-toolchain builds, so these variables have a single global value
955per build directory.
956
957The ``pw_add_module_facade`` function declares a cache variable named
958``<module_name>_BACKEND`` for each facade. Cache variables can be awkward to
959work with, since their values only change when they're assigned, but then
960persist accross CMake invocations. These variables should be set in one of the
961following ways:
962
963* Prior to setting a backend, your application should include
964  ``$ENV{PW_ROOT}/backends.cmake``. This file will setup all the backend targets
965  such that any misspelling of a facade or backend will yield a warning.
966
967  .. note::
968    Zephyr developers do not need to do this, backends can be set automatically
969    by enabling the appropriate Kconfig options.
970
971* Call ``pw_set_backend`` to set backends appropriate for the target in the
972  target's toolchain file. The toolchain file is provided to ``cmake`` with
973  ``-DCMAKE_TOOLCHAIN_FILE=<toolchain file>``.
974* Call ``pw_set_backend`` in the top-level ``CMakeLists.txt`` before other
975  CMake code executes.
976* Set the backend variable at the command line with the ``-D`` option.
977
978  .. code-block:: sh
979
980    cmake -B out/cmake_host -S "$PW_ROOT" -G Ninja \
981        -DCMAKE_TOOLCHAIN_FILE=$PW_ROOT/pw_toolchain/host_clang/toolchain.cmake \
982        -Dpw_log_BACKEND=pw_log_basic
983
984* Temporarily override a backend by setting it interactively with ``ccmake`` or
985  ``cmake-gui``.
986
987If the backend is set to a build target that does not exist, there will be an
988error message like the following:
989
990.. code-block::
991
992  CMake Error at pw_build/pigweed.cmake:257 (message):
993    my_module.my_facade's INTERFACE dep "my_nonexistent_backend" is not
994    a target.
995  Call Stack (most recent call first):
996    pw_build/pigweed.cmake:238:EVAL:1 (_pw_target_link_targets_deferred_check)
997    CMakeLists.txt:DEFERRED
998
999
1000Toolchain setup
1001---------------
1002In CMake, the toolchain is configured by setting CMake variables, as described
1003in the `CMake documentation <https://cmake.org/cmake/help/latest/manual/cmake-toolchains.7.html>`_.
1004These variables are typically set in a toolchain CMake file passed to ``cmake``
1005with the ``-D`` option (``-DCMAKE_TOOLCHAIN_FILE=path/to/file.cmake``).
1006For Pigweed embedded builds, set ``CMAKE_SYSTEM_NAME`` to the empty string
1007(``""``).
1008
1009Toolchains may set the ``pw_build_WARNINGS`` variable to a list of ``INTERFACE``
1010libraries with compilation options for Pigweed's upstream libraries. This
1011defaults to a strict set of warnings. Projects may need to use less strict
1012compilation warnings to compile backends exposed to Pigweed code (such as
1013``pw_log``) that cannot compile with Pigweed's flags. If desired, Projects can
1014access these warnings by depending on ``pw_build.warnings``.
1015
1016Third party libraries
1017---------------------
1018The CMake build includes third-party libraries similarly to the GN build. A
1019``dir_pw_third_party_<library>`` cache variable is defined for each third-party
1020dependency. The variable must be set to the absolute path of the library in
1021order to use it. If the variable is empty
1022(``if("${dir_pw_third_party_<library>}" STREQUAL "")``), the dependency is not
1023available.
1024
1025Third-party dependencies are not automatically added to the build. They can be
1026manually added with ``add_subdirectory`` or by setting the
1027``pw_third_party_<library>_ADD_SUBDIRECTORY`` option to ``ON``.
1028
1029Third party variables are set like any other cache global variable in CMake. It
1030is recommended to set these in one of the following ways:
1031
1032* Set with the CMake ``set`` function in the toolchain file or a
1033  ``CMakeLists.txt`` before other CMake code executes.
1034
1035  .. code-block:: cmake
1036
1037    set(dir_pw_third_party_nanopb ${CMAKE_CURRENT_SOURCE_DIR}/external/nanopb CACHE PATH "" FORCE)
1038
1039* Set the variable at the command line with the ``-D`` option.
1040
1041  .. code-block:: sh
1042
1043    cmake -B out/cmake_host -S "$PW_ROOT" -G Ninja \
1044        -DCMAKE_TOOLCHAIN_FILE=$PW_ROOT/pw_toolchain/host_clang/toolchain.cmake \
1045        -Ddir_pw_third_party_nanopb=/path/to/nanopb
1046
1047* Set the variable interactively with ``ccmake`` or ``cmake-gui``.
1048
1049Use Pigweed from an existing CMake project
1050------------------------------------------
1051To use Pigweed libraries form a CMake-based project, simply include the Pigweed
1052repository from a ``CMakeLists.txt``.
1053
1054.. code-block:: cmake
1055
1056  add_subdirectory(path/to/pigweed pigweed)
1057
1058All module libraries will be available as ``module_name`` or
1059``module_name.sublibrary``.
1060
1061If desired, modules can be included individually.
1062
1063.. code-block:: cmake
1064
1065  add_subdirectory(path/to/pigweed/pw_some_module pw_some_module)
1066  add_subdirectory(path/to/pigweed/pw_another_module pw_another_module)
1067
1068Bazel
1069=====
1070Bazel is currently very experimental, and only builds for host and ARM Cortex-M
1071microcontrollers.
1072
1073The common configuration for Bazel for all modules is in the ``pigweed.bzl``
1074file. The built-in Bazel rules ``cc_binary``, ``cc_library``, and ``cc_test``
1075are wrapped with ``pw_cc_binary``, ``pw_cc_library``, and ``pw_cc_test``.
1076These wrappers add parameters to calls to the compiler and linker.
1077
1078In addition to wrapping the built-in rules, Pigweed also provides a custom
1079rule for handling linker scripts with Bazel. e.g.
1080
1081.. code-block:: python
1082
1083  pw_linker_script(
1084    name = "some_linker_script",
1085    linker_script = ":some_configurable_linker_script.ld",
1086    defines = [
1087        "PW_BOOT_FLASH_BEGIN=0x08000200",
1088        "PW_BOOT_FLASH_SIZE=1024K",
1089        "PW_BOOT_HEAP_SIZE=112K",
1090        "PW_BOOT_MIN_STACK_SIZE=1K",
1091        "PW_BOOT_RAM_BEGIN=0x20000000",
1092        "PW_BOOT_RAM_SIZE=192K",
1093        "PW_BOOT_VECTOR_TABLE_BEGIN=0x08000000",
1094        "PW_BOOT_VECTOR_TABLE_SIZE=512",
1095    ],
1096  )
1097
1098  pw_cc_binary(
1099    name = "some_binary",
1100    srcs = ["some_source.c"],
1101    additional_linker_inputs = [":some_linker_script"],
1102    linkopts = ["-T $(location :some_linker_script)"],
1103  )
1104
1105Currently Pigweed is making use of a set of
1106`open source <https://github.com/silvergasp/bazel-embedded>`_ toolchains. The
1107host builds are only supported on Linux/Mac based systems. Additionally the
1108host builds are not entirely hermetic, and will make use of system
1109libraries and headers. This is close to the default configuration for Bazel,
1110though slightly more hermetic. The host toolchain is based around clang-11 which
1111has a system dependency on 'libtinfo.so.5' which is often included as part of
1112the libncurses packages. On Debian based systems this can be installed using the
1113command below:
1114
1115.. code-block:: sh
1116
1117  sudo apt install libncurses5
1118
1119The host toolchain does not currently support native Windows, though using WSL
1120is a viable alternative.
1121
1122The ARM Cortex-M Bazel toolchains are based around gcc-arm-non-eabi and are
1123entirely hermetic. You can target Cortex-M, by using the platforms command line
1124option. This set of toolchains is supported from hosts; Windows, Mac and Linux.
1125The platforms that are currently supported are listed below:
1126
1127.. code-block:: sh
1128
1129  bazel build //:your_target --platforms=@pigweed//pw_build/platforms:cortex_m0
1130  bazel build //:your_target --platforms=@pigweed//pw_build/platforms:cortex_m1
1131  bazel build //:your_target --platforms=@pigweed//pw_build/platforms:cortex_m3
1132  bazel build //:your_target --platforms=@pigweed//pw_build/platforms:cortex_m4
1133  bazel build //:your_target --platforms=@pigweed//pw_build/platforms:cortex_m7
1134  bazel build //:your_target \
1135    --platforms=@pigweed//pw_build/platforms:cortex_m4_fpu
1136  bazel build //:your_target \
1137    --platforms=@pigweed//pw_build/platforms:cortex_m7_fpu
1138
1139
1140The above examples are cpu/fpu oriented platforms and can be used where
1141applicable for your application. There some more specific platforms for the
1142types of boards that are included as examples in Pigweed. It is strongly
1143encouraged that you create your own set of platforms specific for your project,
1144that implement the constraint_settings in this repository. e.g.
1145
1146New board constraint_value:
1147
1148.. code-block:: python
1149
1150  #your_repo/build_settings/constraints/board/BUILD
1151  constraint_value(
1152    name = "nucleo_l432kc",
1153    constraint_setting = "@pigweed//pw_build/constraints/board",
1154  )
1155
1156New chipset constraint_value:
1157
1158.. code-block:: python
1159
1160  # your_repo/build_settings/constraints/chipset/BUILD
1161  constraint_value(
1162    name = "stm32l432kc",
1163    constraint_setting = "@pigweed//pw_build/constraints/chipset",
1164  )
1165
1166New platforms for chipset and board:
1167
1168.. code-block:: python
1169
1170  #your_repo/build_settings/platforms/BUILD
1171  # Works with all stm32l432kc
1172  platforms(
1173    name = "stm32l432kc",
1174    parents = ["@pigweed//pw_build/platforms:cortex_m4"],
1175    constraint_values =
1176      ["@your_repo//build_settings/constraints/chipset:stm32l432kc"],
1177  )
1178
1179  # Works with only the nucleo_l432kc
1180  platforms(
1181    name = "nucleo_l432kc",
1182    parents = [":stm32l432kc"],
1183    constraint_values =
1184      ["@your_repo//build_settings/constraints/board:nucleo_l432kc"],
1185  )
1186
1187In the above example you can build your code with the command line:
1188
1189.. code-block:: python
1190
1191  bazel build //:your_target_for_nucleo_l432kc \
1192    --platforms=@your_repo//build_settings:nucleo_l432kc
1193
1194
1195You can also specify that a specific target is only compatible with one
1196platform:
1197
1198.. code-block:: python
1199
1200  cc_library(
1201    name = "compatible_with_all_stm32l432kc",
1202    srcs = ["tomato_src.c"],
1203    target_compatible_with =
1204      ["@your_repo//build_settings/constraints/chipset:stm32l432kc"],
1205  )
1206
1207  cc_library(
1208    name = "compatible_with_only_nucleo_l432kc",
1209    srcs = ["bbq_src.c"],
1210    target_compatible_with =
1211      ["@your_repo//build_settings/constraints/board:nucleo_l432kc"],
1212  )
1213
1214