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