• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1.. _module-pw_build-gn:
2
3GN / Ninja
4==========
5.. pigweed-module-subpage::
6   :name: pw_build
7
8The GN / Ninja build system is the primary build system used for upstream
9Pigweed development, and is the most tested and feature-rich build system
10Pigweed offers.
11
12This module's ``build.gn`` file contains a number of C/C++ ``config``
13declarations that are used by upstream Pigweed to set some architecture-agnostic
14compiler defaults. (See Pigweed's ``//BUILDCONFIG.gn``)
15
16``pw_build`` also provides several useful GN templates that are used throughout
17Pigweed.
18
19Building upstream Pigweed
20-------------------------
21See Pigweed's :ref:`docs-get-started-upstream` guide for a high-level introduction
22to using the GN build.
23
24Pigweed's root ``BUILD.gn`` file contains a variety of groups to help you
25control what parts of the project you'd like to build.
26
27* ``default``: Same as just calling ``ninja -C out``. Builds Pigweed's
28  documentation, recommended tests, and python linting, and static analysis.
29* ``extended_default``: Everything in ``default``, plus some other useful
30  configurations that are tested in CQ.
31* ``all``: Attempts to build everything in Pigweed. Note that ``pw package`` may
32  need to be used to enable some branches of the build.
33* ``docs``: Only build Pigweed's documentation.
34* ``stm32f429i``: Only build for the STMicroelectronics STM32F429I-DISC1 board.
35* ``host``: Only build for the host.
36
37There are a variety of other groups in the root ``BUILD.gn`` file that may be
38helpful for covering more areas of the build, or for reducing iteration time
39by only building a subset of the default build.
40
41Some currently broken groups are gated behind the ``pw_BUILD_BROKEN_GROUPS``
42build argument. You can set this to ``true`` using ``gn args out`` to try to
43build and debug known broken build configurations.
44
45Build system philosophies
46-------------------------
47While Pigweed's GN build is not hermetic, it strives to adhere to principles of
48`hermeticity <https://bazel.build/concepts/hermeticity>`_. Some guidelines to
49move towards the ideal of hermeticity include:
50
51* Only rely on pre-compiled tools provided by CIPD (or some other versioned,
52  pre-compiled binary distribution mechanism). This eliminates build artifact
53  differences caused by different tool versions or variations (e.g. same tool
54  version built with slightly different compilation flags).
55* Do not use absolute paths in Ninja commands. Typically, these appear when
56  using ``rebase_path("//path/to/my_script.py")``. Most of the time, Ninja
57  steps should be passed paths rebased relative to the build directory (i.e.
58  ``rebase_path("//path/to/my_script.py", root_build_dir)``). This ensures build
59  commands are the same across different machines.
60* Prevent produced artifacts from relying on or referencing system state. This
61  includes time stamps, writing absolute paths to generated artifacts, or
62  producing artifacts that reference system state in a way that prevents them
63  from working the same way on a different machine.
64* Isolate build actions to the build directory. In general, the build system
65  should not add or modify files outside of the build directory. This can cause
66  confusion to users, and makes the concept of a clean build more ambiguous.
67
68Target types
69------------
70.. code-block::
71
72   import("$dir_pw_build/target_types.gni")
73
74   pw_source_set("my_library") {
75     sources = [ "lib.cc" ]
76   }
77
78Pigweed defines wrappers around the four basic GN binary types ``source_set``,
79``executable``, ``static_library``, and ``shared_library``. These templates
80do several things:
81
82#. **Add default configs/deps**
83
84   Rather than binding the majority of compiler flags related to C++ standard,
85   cross-compilation, warning/error policy, etc.  directly to toolchain
86   invocations, these flags are applied as configs to all ``pw_*`` C/C++ target
87   types. The primary motivations for this are to allow some targets to modify
88   the default set of flags when needed by specifying ``remove_configs``, and to
89   reduce the complexity of building novel toolchains.
90
91   Pigweed's global default configs are set in ``pw_build/default.gni``, and
92   individual platform-specific toolchains extend the list by appending to the
93   ``default_configs`` build argument.
94
95   Default deps were added to support polyfill, which has since been deprecated.
96   Default dependency functionality continues to exist for backwards
97   compatibility.
98
99#. **Optionally add link-time binding**
100
101   Some libraries like pw_assert and pw_log are borderline impossible to
102   implement well without introducing circular dependencies. One solution for
103   addressing this is to break apart the libraries into an interface with
104   minimal dependencies, and an implementation with the bulk of the
105   dependencies that would typically create dependency cycles. In order for the
106   implementation to be linked in, it must be added to the dependency tree of
107   linked artifacts (e.g. ``pw_executable``, ``pw_static_library``). Since
108   there's no way for the libraries themselves to just happily pull in the
109   implementation if someone depends on the interface, the implementation is
110   instead late-bound by adding it as a direct dependency of the final linked
111   artifact. This is all managed through ``pw_build_LINK_DEPS``, which is global
112   for each toolchain and applied to every ``pw_executable``,
113   ``pw_static_library``, and ``pw_shared_library``.
114
115#. **Apply a default visibility policy**
116
117   Projects can globally control the default visibility of pw_* target types by
118   specifying ``pw_build_DEFAULT_VISIBILITY``. This template applies that as the
119   default visibility for any pw_* targets that do not explicitly specify a
120   visibility.
121
122#. **Add source file names as metadata**
123
124   All source file names are collected as
125   `GN metadata <https://gn.googlesource.com/gn/+/main/docs/reference.md#metadata_collection>`_.
126   This list can be writen to a file at build time using ``generated_file``. The
127   primary use case for this is to generate a token database containing all the
128   source files. This allows :c:macro:`PW_ASSERT` to emit filename tokens even
129   though it can't add them to the elf file because of the reasons described at
130   :ref:`module-pw_assert-assert-api`.
131
132   .. note::
133      ``pw_source_files``, if not rebased will default to outputing module
134      relative paths from a ``generated_file`` target.  This is likely not
135      useful. Adding a ``rebase`` argument to ``generated_file`` such as
136      ``rebase = root_build_dir`` will result in usable paths.  For an example,
137      see ``//pw_tokenizer/database.gni``'s ``pw_tokenizer_filename_database``
138      template.
139
140The ``pw_executable`` template provides additional functionality around building
141complete binaries. As Pigweed is a collection of libraries, it does not know how
142its final targets are built. ``pw_executable`` solves this by letting each user
143of Pigweed specify a global executable template for their target, and have
144Pigweed build against it. This is controlled by the build variable
145``pw_executable_config.target_type``, specifying the name of the executable
146template for a project.
147
148In some uncommon cases, a project's ``pw_executable`` template definition may
149need to stamp out some ``pw_source_set``\s. Since a pw_executable template can't
150import ``$dir_pw_build/target_types.gni`` due to circular imports, it should
151import ``$dir_pw_build/cc_library.gni`` instead.
152
153.. tip::
154
155  Prefer to use ``pw_executable`` over plain ``executable`` targets to allow
156  cleanly building the same code for multiple target configs.
157
158Arguments
159^^^^^^^^^
160All of the ``pw_*`` target type overrides accept any arguments supported by
161the underlying native types, as they simply forward them through to the
162underlying target.
163
164Additionally, the following arguments are also supported:
165
166* **remove_configs**: (optional) A list of configs / config patterns to remove
167  from the set of default configs specified by the current toolchain
168  configuration.
169* **remove_public_deps**: (optional) A list of targets to remove from the set of
170  default public_deps specified by the current toolchain configuration.
171
172.. _module-pw_build-link-deps:
173
174Link-only deps
175--------------
176It may be necessary to specify additional link-time dependencies that may not be
177explicitly depended on elsewhere in the build. One example of this is a
178``pw_assert`` backend, which may need to leave out dependencies to avoid
179circular dependencies. Its dependencies need to be linked for executables and
180libraries, even if they aren't pulled in elsewhere.
181
182The ``pw_build_LINK_DEPS`` build arg is a list of dependencies to add to all
183``pw_executable``, ``pw_static_library``, and ``pw_shared_library`` targets.
184This should only be used as a last resort when dependencies cannot be properly
185expressed in the build.
186
187.. _module-pw_build-third-party:
188
189Third party libraries
190---------------------
191Pigweed includes build files for a selection of third-party libraries. For a
192given library, these include:
193
194* ``third_party/<library>/library.gni``: Declares build arguments like
195  ``dir_pw_third_party_<library>`` that default to ``""`` but can be set to the
196  absolute path of the library in order to use it.
197* ``third_party/<library>/BUILD.gn``: Describes how to build the library. This
198  should import ``third_party/<library>/library.gni`` and refer to source paths
199  relative to ``dir_pw_third_party_<library>``.
200
201To add or update GN build files for libraries that only offer Bazel build files,
202the Python script at ``pw_build/py/pw_build/generate_3p_gn.py`` may be used.
203
204.. note::
205   The ``generate_3p_gn.py`` script is experimental, and may not work on an
206   arbitrary Bazel library.
207
208To generate or update the GN offered by Pigweed from an Bazel upstream project,
209first create a ``third_party/<library>/repo.json`` file. This file should
210describe a single JSON object, with the following fields:
211
212* ``name``: String containg the project name.
213
214  .. code-block::
215
216     "name": "FuzzTest"
217
218* ``repos``: Object mapping Bazel repositories to library names.
219
220  .. code-block::
221
222     "repos": { "com_google_absl": "abseil-cpp" }
223
224* ``aliases``: Object mapping GN labels to other GN labels. In some cases, a
225  third party library may have a dependency on another library already supported
226  by Pigweed, but with a label that differs from what the script would generate.
227  This field allows those labels to be rewritten.
228
229  .. code-block::
230
231     "aliases": {
232       "$dir_pw_third_party/googletest:gtest": "$dir_pw_third_party/googletest"
233     }
234
235* ``add``: List of labels to existing GN configs. These will be added to every
236  target in the library.
237
238  .. code-block::
239
240     "add": [ "$dir_pw_third_party/re2/configs:disabled_warnings" ]
241
242* ``remove``: List of labels to default GN configs. These will be removed from
243  every target.
244
245  .. code-block::
246
247     "remove" = [ "$dir_pw_fuzzer:instrumentation" ]
248
249* ``allow_testonly``: Boolean indicating whether to generate GN for Bazel
250  targets marked test-only. Defaults to false.
251
252  .. code-block::
253
254     "allow_testonly": true
255
256* ``no_gn_check``: List of Bazel targets that violate ``gn check``'s
257  `rules`__. Third-party targets that do not conform can be excluded.
258
259  .. code-block::
260
261     "no_gn_check": [ "//fuzztest:regexp_dfa" ]
262
263* ``extra_files``: Object mapping additional files to create to Bazel targets
264  that create them. These targets will be passed to ``bazel run`` and their
265  output saved to the named file within ``third_party/<library>``. For example:
266
267  .. code-block::
268
269     "extra_files": {
270       "fuzztest.bazelrc": "@com_google_fuzztest//bazel:setup_configs"
271     }
272
273.. __: https://gn.googlesource.com/gn/+/main/docs/reference.md#cmd_check
274
275Python packages
276---------------
277GN templates for :ref:`Python build automation <docs-python-build>` are
278described in :ref:`module-pw_build-python`.
279
280.. toctree::
281  :hidden:
282
283  python
284
285
286.. _module-pw_build-cc_blob_library:
287
288pw_cc_blob_library
289------------------
290The ``pw_cc_blob_library`` template is useful for embedding binary data into a
291program. The template takes in a mapping of symbol names to file paths, and
292generates a set of C++ source and header files that embed the contents of the
293passed-in files as arrays of ``std::byte``.
294
295The blob byte arrays are constant initialized and are safe to access at any
296time, including before ``main()``.
297
298``pw_cc_blob_library`` is also available in the CMake build. It is provided by
299``pw_build/cc_blob_library.cmake``.
300
301Arguments
302^^^^^^^^^
303* ``blobs``: A list of GN scopes, where each scope corresponds to a binary blob
304  to be transformed from file to byte array. This is a required field. Blob
305  fields include:
306
307  * ``symbol_name``: The C++ symbol for the byte array.
308  * ``file_path``: The file path for the binary blob.
309  * ``linker_section``: If present, places the byte array in the specified
310    linker section.
311  * ``alignas``: If present, uses the specified string or integer verbatim in
312    the ``alignas()`` specifier for the byte array.
313
314* ``out_header``: The header file to generate. Users will include this file
315  exactly as it is written here to reference the byte arrays.
316* ``namespace``: An optional (but highly recommended!) C++ namespace to place
317  the generated blobs within.
318
319Example
320^^^^^^^
321**BUILD.gn**
322
323.. code-block::
324
325   pw_cc_blob_library("foo_bar_blobs") {
326     blobs: [
327       {
328         symbol_name: "kFooBlob"
329         file_path: "${target_out_dir}/stuff/bin/foo.bin"
330       },
331       {
332         symbol_name: "kBarBlob"
333         file_path: "//stuff/bin/bar.bin"
334         linker_section: ".bar_section"
335       },
336     ]
337     out_header: "my/stuff/foo_bar_blobs.h"
338     namespace: "my::stuff"
339     deps = [ ":generate_foo_bin" ]
340   }
341
342.. note:: If the binary blobs are generated as part of the build, be sure to
343          list them as deps to the pw_cc_blob_library target.
344
345**Generated Header**
346
347.. code-block::
348
349   #pragma once
350
351   #include <array>
352   #include <cstddef>
353
354   namespace my::stuff {
355
356   extern const std::array<std::byte, 100> kFooBlob;
357
358   extern const std::array<std::byte, 50> kBarBlob;
359
360   }  // namespace my::stuff
361
362**Generated Source**
363
364.. code-block::
365
366   #include "my/stuff/foo_bar_blobs.h"
367
368   #include <array>
369   #include <cstddef>
370
371   #include "pw_preprocessor/compiler.h"
372
373   namespace my::stuff {
374
375   const std::array<std::byte, 100> kFooBlob = { ... };
376
377   PW_PLACE_IN_SECTION(".bar_section")
378   const std::array<std::byte, 50> kBarBlob = { ... };
379
380   }  // namespace my::stuff
381
382.. _module-pw_build-facade:
383
384pw_facade
385---------
386In their simplest form, a :ref:`facade<docs-module-structure-facades>` is a GN
387build arg used to change a dependency at compile time. Pigweed targets configure
388these facades as needed.
389
390The ``pw_facade`` template bundles a ``pw_source_set`` with a facade build arg.
391This allows the facade to provide header files, compilation options or anything
392else a GN ``source_set`` provides.
393
394The ``pw_facade`` template declares two targets:
395
396* ``$target_name``: the public-facing ``pw_source_set``, with a ``public_dep``
397  on the backend
398* ``$target_name.facade``: target used by the backend to avoid circular
399  dependencies
400
401.. code-block::
402
403   # Declares ":foo" and ":foo.facade" GN targets
404   pw_facade("foo") {
405     backend = pw_log_BACKEND
406     public_configs = [ ":public_include_path" ]
407     public = [ "public/pw_foo/foo.h" ]
408   }
409
410Low-level facades like ``pw_assert`` cannot express all of their dependencies
411due to the potential for dependency cycles. Facades with this issue may require
412backends to place their implementations in a separate build target to be listed
413in ``pw_build_LINK_DEPS`` (see :ref:`module-pw_build-link-deps`). The
414``require_link_deps`` variable in ``pw_facade`` asserts that all specified build
415targets are present in ``pw_build_LINK_DEPS`` if the facade's backend variable
416is set.
417
418.. _module-pw_build-python-action:
419
420pw_python_action
421----------------
422.. seealso::
423   - :ref:`module-pw_build-python` for all of Pigweed's Python build GN templates.
424   - :ref:`docs-python-build` for details on how the GN Python build works.
425
426The ``pw_python_action`` template is a convenience wrapper around GN's `action
427function <https://gn.googlesource.com/gn/+/main/docs/reference.md#func_action>`_
428for running Python scripts. The main benefit it provides is resolution of GN
429target labels to compiled binary files. This allows Python scripts to be written
430independently of GN, taking only filesystem paths as arguments.
431
432Another convenience provided by the template is to allow running scripts without
433any outputs. Sometimes scripts run in a build do not directly produce output
434files, but GN requires that all actions have an output. ``pw_python_action``
435solves this by accepting a boolean ``stamp`` argument which tells it to create a
436placeholder output file for the action.
437
438Arguments
439^^^^^^^^^
440``pw_python_action`` accepts all of the arguments of a regular ``action``
441target. Additionally, it has some of its own arguments:
442
443* ``module``: Run the specified Python module instead of a script. Either
444  ``script`` or ``module`` must be specified, but not both.
445* ``capture_output``: Optional boolean. If true, script output is hidden unless
446  the script fails with an error. Defaults to true.
447* ``stamp``: Optional variable indicating whether to automatically create a
448  placeholder output file for the script. This allows running scripts without
449  specifying ``outputs``. If ``stamp`` is true, a generic output file is
450  used. If ``stamp`` is a file path, that file is used as a stamp file. Like any
451  output file, ``stamp`` must be in the build directory. Defaults to false.
452* ``environment``: Optional list of strings. Environment variables to set,
453  passed as NAME=VALUE strings.
454* ``working_directory``: Optional file path. When provided the current working
455  directory will be set to this location before the Python module or script is
456  run.
457* ``command_launcher``: Optional string. Arguments to prepend to the Python
458  command, e.g. ``'/usr/bin/fakeroot --'`` will run the Python script within a
459  fakeroot environment.
460* ``venv``: Optional gn target of the pw_python_venv that should be used to run
461  this action.
462* ``python_deps``: Extra dependencies that are required for running the Python
463  script for the ``action``. This must be used with ``module`` to specify the
464  build dependency of the ``module`` if it is user-defined code.
465* ``python_metadata_deps``: Extra dependencies that are ensured completed before
466  generating a Python package metadata manifest, not the overall Python script
467  ``action``. This should rarely be used by non-Pigweed code.
468
469.. _module-pw_build-python-action-test:
470
471pw_python_action_test
472---------------------
473The ``pw_python_action_test`` extends :ref:`module-pw_build-python-action` to
474create a test that is run by a Python script, and its associated test metadata.
475
476Include action tests in the :ref:`module-pw_unit_test-pw_test_group` to produce
477the JSON metadata that :ref:`module-pw_build-test-info` adds.
478
479This template derives several additional targets:
480
481* ``<target_name>.metadata`` produces the test metadata when included in a
482  ``pw_test_group``. This metadata includes the Ninja target that runs the test.
483* If``action`` is not provided as a label, ``<target_name>.script`` wraps a
484  ``pw_python_action`` to run the test as a standalone ``pw_python_package``.
485* ``<target_name>.group`` creates a ``pw_python_group`` in order to apply tools,
486  e.g. linters, to the standalone package.
487* ``<target_name>.lib`` is an empty group for compatibility with
488  ``pw_test_group``.
489* ``<target_name>.run`` invokes the test.
490
491Targets defined using this template will produce test metadata with a
492``test_type`` of "action_test" and a ``ninja_target`` value that will invoke the
493test when passed to Ninja, i.e. ``ninja -C out <ninja_target>``.
494
495Arguments
496^^^^^^^^^
497``pw_python_action_test`` accepts the following arguments:
498
499* All of the arguments of :ref:`module-pw_unit_test-pw_test`.
500* ``action``: An optional string or scope. If a string, this should be a label
501  to a ``pw_python_action`` target that performs the test. If a scope, this has
502  the same meaning as for ``pw_python_script``.
503* Optionally, the ``test_type`` and ``extra_metadata`` arguments of the
504  :ref:`module-pw_build-test-info` template.
505* Optionally, all of the arguments of the :ref:`module-pw_build-python-action`
506  template except ``module``, ``capture_output``, ``stamp``, and
507  ``python_metadata_deps``.
508* Optionally, all of the arguments of the ``pw_python_package`` template except
509  ``setup``, ``generate_setup``, ``tests``, ``python_test_deps``, and
510  ``proto_library``.
511
512.. _module-pw_build-test-info:
513
514pw_test_info
515------------
516``pw_test_info`` generates metadata describing tests. To produce a JSON file
517containing this metadata:
518
519#. For new modules, add a :ref:`module-pw_unit_test-pw_test_group` to the
520   BUILD.gn file. All modules are required to have a ``tests`` target.
521#. Include one or more tests or test groups via ``tests`` or ``group_deps``,
522   respectively, in the ``pw_test_group``.
523#. Set ``output_metadata`` to ``true`` in the ``pw_test_group`` definition.
524
525This template does not typically need to be used directly, unless adding new
526types of tests. It is typically used by other templates, such as the
527:ref:`module-pw_unit_test-pw_test` and the
528:ref:`module-pw_unit_test-pw_test_group`.
529
530Arguments
531^^^^^^^^^
532* ``test_type``: One of "test_group", "unit_test", "action_test", "perf_test",
533  or "fuzz_test".
534* ``test_name``: Name of the test. Defaults to the target name.
535* ``build_label``: GN label for the test. Defaults to the test name.
536* ``extra_metadata``: Additional variables to add to the metadata.
537
538Specific test templates add additional details using ``extra_metadata``. For
539example:
540
541* The :ref:`module-pw_unit_test-pw_test_group` includes its collected list of
542  tests and test groups as ``deps``.
543* The :ref:`module-pw_unit_test-pw_test` and the
544  :ref:`module-pw_perf_test-pw_perf_test` includes the ``test_directory``
545  that contains the test executable.
546* The :ref:`module-pw_build-python-action-test` includes the Ninja target that
547  can be used to invoke the Python action and run the test.
548
549Example
550^^^^^^^
551Let ``//my_module/BUILD.gn`` contain the following:
552
553.. code-block::
554
555   import("$dir_pw_build/python_action_test.gni")
556   import("$dir_pw_perf_test/perf_test.gni")
557   import("$dir_pw_unit_test/test.gni")
558
559   pw_test("my_unit_test") {
560     sources = [ ... ]
561     deps = [ ... ]
562   }
563
564   pw_python_action_test("my_action_test") {
565     script = [ ... ]
566     args = [ ... ]
567     deps = [ ... ]
568   }
569
570   pw_python_action_test("my_integration_test") {
571     script = [ ... ]
572     args = [ ... ]
573     deps = [ ... ]
574     tags = [ "integration" ]
575   }
576
577   pw_perf_test("my_perf_test") {
578     sources = [ ... ]
579     deps = [ ... ]
580   }
581
582   pw_test_group("tests") {
583     tests = [
584      ":my_unit_test",
585      ":my_action_test",
586      ":my_integration_test",
587     ]
588   }
589
590Let `//BUILD.gn`` contain the following:
591
592.. code-block::
593
594   import("$dir_pw_unit_test/test.gni")
595
596   group("run_tests") {
597     deps = [ ":my_module_tests(//targets/my_targets:my_toolchain)" ]
598   }
599
600   pw_test_group("my_module_tests") {
601     group_deps = [ "//my_module:tests" ]
602     output_metadata = true
603   }
604
605Then running ``gn gen out`` will produce the following JSON file at
606``out/my_toolchain/my_module_tests.testinfo.json``:
607
608.. code-block:: json
609
610   [
611     {
612       "build_label": "//my_module:my_unit_test",
613       "test_directory": "my_toolchain/obj/my_module/test",
614       "test_name": "my_unit_test",
615       "test_type": "unit_test"
616     },
617     {
618       "build_label": "//my_module:my_action_test",
619       "ninja_target": "my_toolchain/obj/my_module/my_action_test.run.stamp",
620       "test_name": "my_action_test",
621       "test_type": "action_test"
622     },
623     {
624       "build_label": "//my_module:my_integration_test",
625       "ninja_target": "my_toolchain/obj/my_module/my_integration_test.run.stamp",
626       "tags": [
627         "integration"
628       ],
629       "test_name": "my_integration_test",
630       "test_type": "action_test"
631     },
632     {
633       "build_label": "//my_module:my_perf_test",
634       "test_directory": "my_toolchain/obj/my_module/test",
635       "test_name": "my_perf_test",
636       "test_type": "perf_test"
637     },
638     {
639       "build_label": "//my_module:tests",
640       "deps": [
641         "//my_module:my_unit_test",
642         "//my_module:my_action_test",
643         "//my_module:my_integration_test",
644       ],
645       "test_name": "my_module/tests",
646       "test_type": "test_group"
647     },
648     {
649       "build_label": "//:my_module_tests",
650       "deps": [
651         "//my_module:tests",
652       ],
653       "test_name": "my_module_tests",
654       "test_type": "test_group"
655     }
656   ]
657
658.. _module-pw_build-python-action-expressions:
659
660Expressions
661^^^^^^^^^^^
662``pw_python_action`` evaluates expressions in ``args``, the arguments passed to
663the script. These expressions function similarly to generator expressions in
664CMake. Expressions may be passed as a standalone argument or as part of another
665argument. A single argument may contain multiple expressions.
666
667Generally, these expressions are used within templates rather than directly in
668BUILD.gn files. This allows build code to use GN labels without having to worry
669about converting them to files.
670
671.. note::
672
673  We intend to replace these expressions with native GN features when possible.
674  See `b/234886742 <http://issuetracker.google.com/234886742>`_.
675
676The following expressions are supported:
677
678.. describe:: <TARGET_FILE(gn_target)>
679
680  Evaluates to the output file of the provided GN target. For example, the
681  expression
682
683  .. code-block::
684
685     "<TARGET_FILE(//foo/bar:static_lib)>"
686
687  might expand to
688
689  .. code-block::
690
691     "/home/User/project_root/out/obj/foo/bar/static_lib.a"
692
693  ``TARGET_FILE`` parses the ``.ninja`` file for the GN target, so it should
694  always find the correct output file, regardless of the toolchain's or target's
695  configuration. Some targets, such as ``source_set`` and ``group`` targets, do
696  not have an output file, and attempting to use ``TARGET_FILE`` with them
697  results in an error.
698
699  ``TARGET_FILE`` only resolves GN target labels to their outputs. To resolve
700  paths generally, use the standard GN approach of applying the
701  ``rebase_path(path, root_build_dir)`` function. This function
702  converts the provided GN path or list of paths to be relative to the build
703  directory, from which all build commands and scripts are executed.
704
705.. describe:: <TARGET_FILE_IF_EXISTS(gn_target)>
706
707  ``TARGET_FILE_IF_EXISTS`` evaluates to the output file of the provided GN
708  target, if the output file exists. If the output file does not exist, the
709  entire argument that includes this expression is omitted, even if there is
710  other text or another expression.
711
712  For example, consider this expression:
713
714  .. code-block::
715
716     "--database=<TARGET_FILE_IF_EXISTS(//alpha/bravo)>"
717
718  If the ``//alpha/bravo`` target file exists, this might expand to the
719  following:
720
721  .. code-block::
722
723     "--database=/home/User/project/out/obj/alpha/bravo/bravo.elf"
724
725  If the ``//alpha/bravo`` target file does not exist, the entire
726  ``--database=`` argument is omitted from the script arguments.
727
728.. describe:: <TARGET_OBJECTS(gn_target)>
729
730  Evaluates to the object files of the provided GN target. Expands to a separate
731  argument for each object file. If the target has no object files, the argument
732  is omitted entirely. Because it does not expand to a single expression, the
733  ``<TARGET_OBJECTS(...)>`` expression may not have leading or trailing text.
734
735  For example, the expression
736
737  .. code-block::
738
739     "<TARGET_OBJECTS(//foo/bar:a_source_set)>"
740
741  might expand to multiple separate arguments:
742
743  .. code-block::
744
745     "/home/User/project_root/out/obj/foo/bar/a_source_set.file_a.cc.o"
746     "/home/User/project_root/out/obj/foo/bar/a_source_set.file_b.cc.o"
747     "/home/User/project_root/out/obj/foo/bar/a_source_set.file_c.cc.o"
748
749Example
750^^^^^^^
751.. code-block::
752
753   import("$dir_pw_build/python_action.gni")
754
755   pw_python_action("postprocess_main_image") {
756     script = "py/postprocess_binary.py"
757     args = [
758       "--database",
759       rebase_path("my/database.csv", root_build_dir),
760       "--binary=<TARGET_FILE(//firmware/images:main)>",
761     ]
762     stamp = true
763   }
764
765.. _module-pw_build-evaluate-path-expressions:
766
767pw_evaluate_path_expressions
768----------------------------
769It is not always feasible to pass information to a script through command line
770arguments. If a script requires a large amount of input data, writing to a file
771is often more convenient. However, doing so bypasses ``pw_python_action``'s GN
772target label resolution, preventing such scripts from working with build
773artifacts in a build system-agnostic manner.
774
775``pw_evaluate_path_expressions`` is designed to address this use case. It takes
776a list of input files and resolves target expressions within them, modifying the
777files in-place.
778
779Refer to ``pw_python_action``'s :ref:`module-pw_build-python-action-expressions`
780section for the list of supported expressions.
781
782.. note::
783
784  ``pw_evaluate_path_expressions`` is typically used as an intermediate
785  sub-target of a larger template, rather than a standalone build target.
786
787Arguments
788^^^^^^^^^
789* ``files``: A list of scopes, each containing a ``source`` file to process and
790  a ``dest`` file to which to write the result.
791
792Example
793^^^^^^^
794The following template defines an executable target which additionally outputs
795the list of object files from which it was compiled, making use of
796``pw_evaluate_path_expressions`` to resolve their paths.
797
798.. code-block::
799
800   import("$dir_pw_build/evaluate_path_expressions.gni")
801
802   template("executable_with_artifacts") {
803     executable("${target_name}.exe") {
804       sources = invoker.sources
805       if defined(invoker.deps) {
806         deps = invoker.deps
807       }
808     }
809
810     _artifacts_input = "$target_gen_dir/${target_name}_artifacts.json.in"
811     _artifacts_output = "$target_gen_dir/${target_name}_artifacts.json"
812     _artifacts = {
813       binary = "<TARGET_FILE(:${target_name}.exe)>"
814       objects = "<TARGET_OBJECTS(:${target_name}.exe)>"
815     }
816     write_file(_artifacts_input, _artifacts, "json")
817
818     pw_evaluate_path_expressions("${target_name}.evaluate") {
819       files = [
820         {
821           source = _artifacts_input
822           dest = _artifacts_output
823         },
824       ]
825     }
826
827     group(target_name) {
828       deps = [
829         ":${target_name}.exe",
830         ":${target_name}.evaluate",
831       ]
832     }
833   }
834
835.. _module-pw_build-pw_exec:
836
837pw_exec
838-------
839``pw_exec`` allows for execution of arbitrary programs. It is a wrapper around
840``pw_python_action`` but allows for specifying the program to execute.
841
842.. note::
843
844   Prefer to use ``pw_python_action`` instead of calling out to shell
845   scripts, as the Python will be more portable. ``pw_exec`` should generally
846   only be used for interacting with legacy/existing scripts.
847
848Arguments
849^^^^^^^^^
850* ``program``: The program to run. Can be a full path or just a name (in which
851  case $PATH is searched).
852* ``args``: Optional list of arguments to the program.
853* ``deps``: Dependencies for this target.
854* ``public_deps``: Public dependencies for this target. In addition to outputs
855  from this target, outputs generated by public dependencies can be used as
856  inputs from targets that depend on this one. This is not the case for private
857  deps.
858* ``inputs``: Optional list of build inputs to the program.
859* ``outputs``: Optional list of artifacts produced by the program's execution.
860* ``env``: Optional list of key-value pairs defining environment variables for
861  the program.
862* ``env_file``: Optional path to a file containing a list of newline-separated
863  key-value pairs defining environment variables for the program.
864* ``args_file``: Optional path to a file containing additional positional
865  arguments to the program. Each line of the file is appended to the
866  invocation. Useful for specifying arguments from GN metadata.
867* ``skip_empty_args``: If args_file is provided, boolean indicating whether to
868  skip running the program if the file is empty. Used to avoid running
869  commands which error when called without arguments.
870* ``capture_output``: If true, output from the program is hidden unless the
871  program exits with an error. Defaults to true.
872* ``working_directory``: The working directory to execute the subprocess with.
873  If not specified it will not be set and the subprocess will have whatever
874  the parent current working directory is.
875* ``venv``: Python virtualenv to pass along to the underlying
876  :ref:`module-pw_build-pw_python_action`.
877* ``visibility``: GN visibility to apply to the underlying target.
878
879Example
880^^^^^^^
881.. code-block::
882
883   import("$dir_pw_build/exec.gni")
884
885   pw_exec("hello_world") {
886     program = "/bin/sh"
887     args = [
888       "-c",
889       "echo hello \$WORLD",
890     ]
891     env = [
892       "WORLD=world",
893     ]
894   }
895
896pw_input_group
897--------------
898``pw_input_group`` defines a group of input files which are not directly
899processed by the build but are still important dependencies of later build
900steps. This is commonly used alongside metadata to propagate file dependencies
901through the build graph and force rebuilds on file modifications.
902
903For example ``pw_docgen`` defines a ``pw_doc_group`` template which outputs
904metadata from a list of input files. The metadata file is not actually part of
905the build, and so changes to any of the input files do not trigger a rebuild.
906This is problematic, as targets that depend on the metadata should rebuild when
907the inputs are modified but GN cannot express this dependency.
908
909``pw_input_group`` solves this problem by allowing a list of files to be listed
910in a target that does not output any build artifacts, causing all dependent
911targets to correctly rebuild.
912
913Arguments
914^^^^^^^^^
915``pw_input_group`` accepts all arguments that can be passed to a ``group``
916target, as well as requiring one extra:
917
918* ``inputs``: List of input files.
919
920Example
921^^^^^^^
922.. code-block::
923
924   import("$dir_pw_build/input_group.gni")
925
926   pw_input_group("foo_metadata") {
927     metadata = {
928       files = [
929         "x.foo",
930         "y.foo",
931         "z.foo",
932       ]
933     }
934     inputs = metadata.files
935   }
936
937Targets depending on ``foo_metadata`` will rebuild when any of the ``.foo``
938files are modified.
939
940pw_zip
941------
942``pw_zip`` is a target that allows users to zip up a set of input files and
943directories into a single output ``.zip`` file—a simple automation of a
944potentially repetitive task.
945
946Arguments
947^^^^^^^^^
948* ``inputs``: List of source files as well as the desired relative zip
949  destination. See below for the input syntax.
950* ``dirs``: List of entire directories to be zipped as well as the desired
951  relative zip destination. See below for the input syntax.
952* ``output``: Filename of output ``.zip`` file.
953* ``deps``: List of dependencies for the target.
954
955Input Syntax
956^^^^^^^^^^^^
957Inputs all need to follow the correct syntax:
958
959#. Path to source file or directory. Directories must end with a ``/``.
960#. The delimiter (defaults to ``>``).
961#. The desired destination of the contents within the ``.zip``. Must start
962   with ``/`` to indicate the zip root. Any number of subdirectories are
963   allowed. If the source is a file it can be put into any subdirectory of the
964   root. If the source is a file, the zip copy can also be renamed by ending
965   the zip destination with a filename (no trailing ``/``).
966
967Thus, it should look like the following: ``"[source file or dir] > /"``.
968
969Example
970^^^^^^^
971Let's say we have the following structure for a ``//source/`` directory:
972
973.. code-block::
974
975   source/
976   ├── file1.txt
977   ├── file2.txt
978   ├── file3.txt
979   └── some_dir/
980       ├── file4.txt
981       └── some_other_dir/
982           └── file5.txt
983
984And we create the following build target:
985
986.. code-block::
987
988   import("$dir_pw_build/zip.gni")
989
990   pw_zip("target_name") {
991     inputs = [
992       "//source/file1.txt > /",             # Copied to the zip root dir.
993       "//source/file2.txt > /renamed.txt",  # File renamed.
994       "//source/file3.txt > /bar/",         # File moved to the /bar/ dir.
995     ]
996
997     dirs = [
998       "//source/some_dir/ > /bar/some_dir/",  # All /some_dir/ contents copied
999                                               # as /bar/some_dir/.
1000     ]
1001
1002     # Note on output: if the specific output directory isn't defined
1003     # (such as output = "zoo.zip") then the .zip will output to the
1004     # same directory as the BUILD.gn file that called the target.
1005     output = "//$target_out_dir/foo.zip"  # Where the foo.zip will end up
1006   }
1007
1008This will result in a ``.zip`` file called ``foo.zip`` stored in
1009``//$target_out_dir`` with the following structure:
1010
1011.. code-block::
1012
1013   foo.zip
1014   ├── bar/
1015   │   ├── file3.txt
1016   │   └── some_dir/
1017   │       ├── file4.txt
1018   │       └── some_other_dir/
1019   │           └── file5.txt
1020   ├── file1.txt
1021   └── renamed.txt
1022
1023.. _module-pw_build-relative-source-file-names:
1024
1025pw_relative_source_file_names
1026-----------------------------
1027This template recursively walks the listed dependencies and collects the names
1028of all the headers and source files required by the targets, and then transforms
1029them such that they reflect the ``__FILE__`` when pw_build's ``relative_paths``
1030config is applied. This is primarily intended for side-band generation of
1031pw_tokenizer tokens so file name tokens can be utilized in places where
1032pw_tokenizer is unable to embed token information as part of C/C++ compilation.
1033
1034This template produces a JSON file containing an array of strings (file paths
1035with ``-ffile-prefix-map``-like transformations applied) that can be used to
1036:ref:`generate a token database <module-pw_tokenizer-database-creation>`.
1037
1038Arguments
1039^^^^^^^^^
1040* ``deps``: A required list of targets to recursively extract file names from.
1041* ``outputs``: A required array with a single element: the path to write the
1042  final JSON file to.
1043
1044Example
1045^^^^^^^
1046Let's say we have the following project structure:
1047
1048.. code-block::
1049
1050   project root
1051   ├── foo/
1052   │   ├── foo.h
1053   │   └── foo.cc
1054   ├── bar/
1055   │   ├── bar.h
1056   │   └── bar.cc
1057   ├── unused/
1058   │   ├── unused.h
1059   │   └── unused.cc
1060   └── main.cc
1061
1062And a BUILD.gn at the root:
1063
1064.. code-block::
1065
1066   pw_source_set("bar") {
1067     public_configs = [ ":bar_headers" ]
1068     public = [ "bar/bar.h" ]
1069     sources = [ "bar/bar.cc" ]
1070   }
1071
1072   pw_source_set("foo") {
1073     public_configs = [ ":foo_headers" ]
1074     public = [ "foo/foo.h" ]
1075     sources = [ "foo/foo.cc" ]
1076     deps = [ ":bar" ]
1077   }
1078
1079
1080   pw_source_set("unused") {
1081     public_configs = [ ":unused_headers" ]
1082     public = [ "unused/unused.h" ]
1083     sources = [ "unused/unused.cc" ]
1084     deps = [ ":bar" ]
1085   }
1086
1087   pw_executable("main") {
1088     sources = [ "main.cc" ]
1089     deps = [ ":foo" ]
1090   }
1091
1092   pw_relative_source_file_names("main_source_files") {
1093     deps = [ ":main" ]
1094     outputs = [ "$target_gen_dir/main_source_files.json" ]
1095   }
1096
1097The json file written to `out/gen/main_source_files.json` will contain:
1098
1099.. code-block::
1100
1101   [
1102     "bar/bar.cc",
1103     "bar/bar.h",
1104     "foo/foo.cc",
1105     "foo/foo.h",
1106     "main.cc"
1107   ]
1108
1109Since ``unused`` isn't a transitive dependency of ``main``, its source files
1110are not included. Similarly, even though ``bar`` is not a direct dependency of
1111``main``, its source files *are* included because ``foo`` brings in ``bar`` as
1112a transitive dependency.
1113
1114Note how the file paths in this example are relative to the project root rather
1115than being absolute paths (e.g. ``/home/user/ralph/coding/my_proj/main.cc``).
1116This is a result of transformations applied to strip absolute pathing prefixes,
1117matching the behavior of pw_build's ``$dir_pw_build:relative_paths`` config.
1118
1119Build time errors: pw_error and pw_build_assert
1120-----------------------------------------------
1121In Pigweed's complex, multi-toolchain GN build it is not possible to build every
1122target in every configuration. GN's ``assert`` statement is not ideal for
1123enforcing the correct configuration because it may prevent the GN build files or
1124targets from being referred to at all, even if they aren't used.
1125
1126The ``pw_error`` GN template results in an error if it is executed during the
1127build. These error targets can exist in the build graph, but cannot be depended
1128on without an error.
1129
1130``pw_build_assert`` evaluates to a ``pw_error`` if a condition fails or nothing
1131(an empty group) if the condition passes. Targets can add a dependency on a
1132``pw_build_assert`` to enforce a condition at build time.
1133
1134The templates for build time errors are defined in ``pw_build/error.gni``.
1135
1136.. _module-pw_build-gn-pw_coverage_report:
1137
1138Generate code coverage reports: ``pw_coverage_report``
1139------------------------------------------------------
1140Pigweed supports generating coverage reports, in a variety of formats, for C/C++
1141code using the ``pw_coverage_report`` GN template.
1142
1143Coverage Caveats
1144^^^^^^^^^^^^^^^^
1145There are currently two code coverage caveats when enabled:
1146
1147#. Coverage reports are only populated based on host tests that use a ``clang``
1148   toolchain.
1149
1150#. Coverage reports will only show coverage information for headers included in
1151   a test binary.
1152
1153These two caveats mean that all device-specific code that cannot be compiled for
1154and run on the host will not be able to have reports generated for them, and
1155that the existence of these files will not appear in any coverage report.
1156
1157Try to ensure that your code can be written in a way that it can be compiled
1158into a host test for the purpose of coverage reporting, although this is
1159sometimes impossible due to requiring hardware-specific APIs to be available.
1160
1161Coverage Instrumentation
1162^^^^^^^^^^^^^^^^^^^^^^^^
1163For the ``pw_coverage_report`` to generate meaningful output, you must ensure
1164that it is invoked by a toolchain that instruments tests for code coverage
1165collection and output.
1166
1167Instrumentation is controlled by two GN build arguments:
1168
1169- ``pw_toolchain_COVERAGE_ENABLED`` being set to ``true``.
1170- ``pw_toolchain_PROFILE_SOURCE_FILES`` is an optional argument that provides a
1171  list of source files to selectively collect coverage.
1172
1173.. note::
1174
1175  It is possible to also instrument binaries for UBSAN, ASAN, or TSAN at the
1176  same time as coverage. However, TSAN will find issues in the coverage
1177  instrumentation code and fail to properly build.
1178
1179This can most easily be done by using the ``host_clang_coverage`` toolchain
1180provided in :ref:`module-pw_toolchain`, but you can also create custom
1181toolchains that manually set these GN build arguments as well.
1182
1183``pw_coverage_report``
1184^^^^^^^^^^^^^^^^^^^^^^
1185``pw_coverage_report`` is basically a GN frontend to the ``llvm-cov``
1186`tool <https://llvm.org/docs/CommandGuide/llvm-cov.html>`_ that can be
1187integrated into the normal build.
1188
1189It can be found at ``pw_build/coverage_report.gni`` and is available through
1190``import("$dir_pw_build/coverage_report.gni")``.
1191
1192The supported report formats are:
1193
1194- ``text``: A text representation of the code coverage report. This
1195  format is not suitable for further machine manipulation and is instead only
1196  useful for cases where a human needs to interpret the report. The text format
1197  provides a nice summary, but if you desire to drill down into the coverage
1198  details more, please consider using ``html`` instead.
1199
1200  - This is equivalent to ``llvm-cov show --format text`` and similar to
1201    ``llvm-cov report``.
1202
1203- ``html``: A static HTML site that provides an overall coverage summary and
1204  per-file information. This format is not suitable for further machine
1205  manipulation and is instead only useful for cases where a human needs to
1206  interpret the report.
1207
1208  - This is equivalent to ``llvm-cov show --format html``.
1209
1210- ``lcov``: A machine-friendly coverage report format. This format is not human-
1211  friendly. If that is necessary, use ``text`` or ``html`` instead.
1212
1213  - This is equivalent to ``llvm-cov export --format lcov``.
1214
1215- ``json``: A machine-friendly coverage report format. This format is not human-
1216  friendly. If that is necessary, use ``text`` or ``html`` instead.
1217
1218  - This is equivalent to ``llvm-cov export --format json``.
1219
1220Arguments
1221"""""""""
1222There are three classes of ``template`` arguments: build, coverage, and test.
1223
1224**Build Arguments:**
1225
1226- ``enable_if`` (optional): Conditionally activates coverage report generation when set to
1227  a boolean expression that evaluates to ``true``. This can be used to allow
1228  project builds to conditionally enable or disable coverage reports to minimize
1229  work needed for certain build configurations.
1230
1231- ``failure_mode`` (optional/unstable): Specify the failure mode for
1232  ``llvm-profdata`` (used to merge inidividual profraw files from ``pw_test``
1233  runs). Available options are ``"any"`` (default) or ``"all"``.
1234
1235  - This should be considered an unstable/deprecated argument that should only
1236    be used as a last resort to get a build working again. Using
1237    ``failure_mode = "all"`` usually indicates that there are underlying
1238    problems in the build or test infrastructure that should be independently
1239    resolved. Please reach out to the Pigweed team for assistance.
1240
1241**Coverage Arguments:**
1242
1243- ``filter_paths`` (optional): List of file paths to include when generating the
1244  coverage report. These cannot be regular expressions, but can be concrete file
1245  or folder paths. Folder paths will allow all files in that directory or any
1246  recursive child directory.
1247
1248  - These are passed to ``llvm-cov`` by the optional trailing positional
1249    ``[SOURCES]`` arguments.
1250
1251- ``ignore_filename_patterns`` (optional): List of file path regular expressions
1252  to ignore when generating the coverage report.
1253
1254  - These are passed to ``llvm-cov`` via ``--ignore-filename-regex`` named
1255    parameters.
1256
1257**Test Arguments (one of these is required to be provided):**
1258
1259- ``tests``: A list of ``pw_test`` :ref:`targets<module-pw_unit_test-pw_test>`.
1260
1261- ``group_deps``: A list of ``pw_test_group``
1262  :ref:`targets<module-pw_unit_test-pw_test_group>`.
1263
1264.. note::
1265
1266  ``tests`` and ``group_deps`` are treated exactly the same by
1267  ``pw_coverage_report``, so it is not that important to ensure they are used
1268  properly.
1269
1270Target Expansion
1271""""""""""""""""
1272``pw_coverage_report(<target_name>)`` expands to one concrete target for each
1273report format.
1274
1275- ``<target_name>.text``: Generates the ``text`` coverage report.
1276
1277- ``<target_name>.html``: Generates the ``html`` coverage report.
1278
1279- ``<target_name>.lcov``: Generates the ``lcov`` coverage report.
1280
1281- ``<target_name>.json``: Generates the ``json`` coverage report.
1282
1283To use any of these targets, you need only to add a dependency on the desired
1284target somewhere in your build.
1285
1286There is also a ``<target_name>`` target generated that is a ``group`` that adds
1287a dependency on all of the format-specific targets listed above.
1288
1289.. note::
1290  These targets are always available, even when the toolchain executing the
1291  target does not support coverage or coverage is not enabled. In these cases,
1292  the targets are set to empty groups.
1293
1294Coverage Output
1295^^^^^^^^^^^^^^^
1296Coverage reports are currently generated and placed into the build output
1297directory associated with the path to the GN file where the
1298``pw_coverage_report`` is used in a subfolder named
1299``<target_name>.<report_type>``.
1300
1301.. note::
1302
1303  Due to limitations with telling GN the entire output of coverage reports
1304  (stemming from per-source-file generation for HTML and text representations),
1305  it is not as simple as using GN's built-in ``copy`` to be able to move these
1306  coverage reports to another output location. However, it seems possible to add
1307  a target that can use Python to copy the entire output directory.
1308
1309Improved Ninja interface
1310------------------------
1311Ninja includes a basic progress display, showing in a single line the number of
1312targets finished, the total number of targets, and the name of the most recent
1313target it has either started or finished.
1314
1315For additional insight into the status of the build, Pigweed includes a Ninja
1316wrapper, ``pw-wrap-ninja``, that displays additional real-time information about
1317the progress of the build. The wrapper is invoked the same way you'd normally
1318invoke Ninja:
1319
1320.. code-block:: sh
1321
1322   pw-wrap-ninja -C out
1323
1324The script lists the progress of the build, as well as the list of targets that
1325Ninja is currently building, along with a timer that measures how long each
1326target has been building for:
1327
1328.. code-block::
1329
1330   [51.3s] Building [8924/10690] ...
1331     [10.4s] c++ pw_strict_host_clang_debug/obj/pw_string/string_test.lib.string_test.cc.o
1332     [ 9.5s] ACTION //pw_console/py:py.lint.mypy(//pw_build/python_toolchain:python)
1333     [ 9.4s] ACTION //pw_console/py:py.lint.pylint(//pw_build/python_toolchain:python)
1334     [ 6.1s] clang-tidy ../pw_log_rpc/log_service.cc
1335     [ 6.1s] clang-tidy ../pw_log_rpc/log_service_test.cc
1336     [ 6.1s] clang-tidy ../pw_log_rpc/rpc_log_drain.cc
1337     [ 6.1s] clang-tidy ../pw_log_rpc/rpc_log_drain_test.cc
1338     [ 5.4s] c++ pw_strict_host_clang_debug/obj/BUILD_DIR/pw_strict_host_clang_debug/gen/pw...
1339     ... and 109 more
1340
1341This allows you to, at a glance, know what Ninja's currently building, which
1342targets are bottlenecking the rest of the build, and which targets are taking
1343an unusually long time to complete.
1344
1345``pw-wrap-ninja`` includes other useful functionality as well. The
1346``--write-trace`` option writes a build trace to the specified path, which can
1347be viewed in the `Perfetto UI <https://ui.perfetto.dev/>`_, or via Chrome's
1348built-in ``chrome://tracing`` tool.
1349
1350.. _module-pw_build-gn-pw_linker_script:
1351
1352pw_linker_script
1353----------------
1354Preprocess a linker script and turn it into a target.
1355
1356In lieu of direct GN support for linker scripts, this template makes it
1357possible to run the C Preprocessor on a linker script file so defines can
1358be properly evaluated before the linker script is passed to linker.
1359
1360Arguments
1361^^^^^^^^^
1362- ``linker_script``: The linker script to send through the C preprocessor.
1363
1364- ``defines``: Preprocessor defines to apply when running the C preprocessor.
1365
1366- ``cflags``: Flags to pass to the C compiler.
1367
1368- ``includes``: Include these files when running the C preprocessor.
1369
1370- ``inputs``: Files that, when changed, should trigger a re-build of the linker
1371  script. linker_script and includes are implicitly added to this by the
1372  template.
1373
1374Example
1375^^^^^^^
1376.. code-block::
1377
1378   pw_linker_script("generic_linker_script") {
1379     defines = [
1380       "PW_HEAP_SIZE=1K",
1381       "PW_NOINIT_SIZE=512"
1382     ]
1383     linker_script = "basic_script.ld"
1384   }
1385