6 Pigweed's modules aim to be easily integratable into both new and existing
7 embedded projects. To that goal, the ``pw_build`` module provides support for
8 multiple build systems. Our personal favorite is `GN`_/`Ninja`_, which is used
9 by upstream developers for its speed and flexibility. `CMake`_ and `Bazel`_
10 build files are also provided by all modules, allowing Pigweed to be added to a
11 project with minimal effort.
13 .. _GN: https://gn.googlesource.com/gn/
14 .. _Ninja: https://ninja-build.org/
15 .. _CMake: https://cmake.org/
16 .. _Bazel: https://bazel.build/
18 Beyond just compiling code, Pigweed’s GN build system can also:
20 * Generate HTML documentation, via our Sphinx integration (with ``pw_docgen``)
21 * Display memory usage report cards (with ``pw_bloat``)
22 * Incrementally run unit tests after code changes (with ``pw_target_runner``)
25 These are only supported in the GN build, so we recommend using it if possible.
29 The GN / Ninja build system is the primary build system used for upstream
30 Pigweed development, and is the most tested and feature-rich build system
33 This module's ``build.gn`` file contains a number of C/C++ ``config``
34 declarations that are used by upstream Pigweed to set some architecture-agnostic
35 compiler defaults. (See Pigweed's ``//BUILDCONFIG.gn``)
37 ``pw_build`` also provides several useful GN templates that are used throughout
47 import("$dir_pw_build/target_types.gni")
49 pw_source_set("my_library") {
50 sources = [ "lib.cc" ]
53 Pigweed defines wrappers around the four basic GN binary types ``source_set``,
54 ``executable``, ``static_library``, and ``shared_library``. These wrappers apply
55 default arguments to each target as specified in the ``default_configs`` and
56 ``default_public_deps`` build args. Additionally, they allow defaults to be
57 removed on a per-target basis using ``remove_configs`` and
58 ``remove_public_deps`` variables, respectively.
60 The ``pw_executable`` template provides additional functionality around building
61 complete binaries. As Pigweed is a collection of libraries, it does not know how
62 its final targets are built. ``pw_executable`` solves this by letting each user
63 of Pigweed specify a global executable template for their target, and have
64 Pigweed build against it. This is controlled by the build variable
65 ``pw_executable_config.target_type``, specifying the name of the executable
66 template for a project.
70 Prefer to use ``pw_executable`` over plain ``executable`` targets to allow
71 cleanly building the same code for multiple target configs.
75 All of the ``pw_*`` target type overrides accept any arguments, as they simply
76 forward them through to the underlying target.
78 .. _module-pw_build-facade:
82 In their simplest form, a :ref:`facade<docs-module-structure-facades>` is a GN
83 build arg used to change a dependency at compile time. Pigweed targets configure
84 these facades as needed.
86 The ``pw_facade`` template bundles a ``pw_source_set`` with a facade build arg.
87 This allows the facade to provide header files, compilation options or anything
88 else a GN ``source_set`` provides.
90 The ``pw_facade`` template declares two targets:
92 * ``$target_name``: the public-facing ``pw_source_set``, with a ``public_dep``
94 * ``$target_name.facade``: target used by the backend to avoid circular
99 # Declares ":foo" and ":foo.facade" GN targets
101 backend = pw_log_BACKEND
102 public_configs = [ ":public_include_path" ]
103 public = [ "public/pw_foo/foo.h" ]
106 .. _module-pw_build-python-action:
110 The ``pw_python_action`` template is a convenience wrapper around ``action`` for
111 running Python scripts. The main benefit it provides is resolution of GN target
112 labels to compiled binary files. This allows Python scripts to be written
113 independently of GN, taking only filesystem paths as arguments.
115 Another convenience provided by the template is to allow running scripts without
116 any outputs. Sometimes scripts run in a build do not directly produce output
117 files, but GN requires that all actions have an output. ``pw_python_action``
118 solves this by accepting a boolean ``stamp`` argument which tells it to create a
119 dummy output file for the action.
123 ``pw_python_action`` accepts all of the arguments of a regular ``action``
124 target. Additionally, it has some of its own arguments:
126 * ``module``: Run the specified Python module instead of a script. Either
127 ``script`` or ``module`` must be specified, but not both.
128 * ``capture_output``: Optional boolean. If true, script output is hidden unless
129 the script fails with an error. Defaults to true.
130 * ``stamp``: Optional variable indicating whether to automatically create a
131 dummy output file for the script. This allows running scripts without
132 specifying ``outputs``. If ``stamp`` is true, a generic output file is
133 used. If ``stamp`` is a file path, that file is used as a stamp file. Like any
134 output file, ``stamp`` must be in the build directory. Defaults to false.
135 * ``directory``: Optional path. Change to this directory before executing the
136 command. Paths in arguments may need to be adjusted.
137 * ``environment``: Optional list of strings. Environment variables to set,
138 passed as NAME=VALUE strings.
142 ``pw_python_action`` evaluates expressions in ``args``, the arguments passed to
143 the script. These expressions function similarly to generator expressions in
144 CMake. Expressions may be passed as a standalone argument or as part of another
145 argument. A single argument may contain multiple expressions.
147 Generally, these expressions are used within templates rather than directly in
148 BUILD.gn files. This allows build code to use GN labels without having to worry
149 about converting them to files.
151 The following expressions are supported:
153 .. describe:: <TARGET_FILE(gn_target)>
155 Evaluates to the output file of the provided GN target. For example, the
160 "<TARGET_FILE(//foo/bar:static_lib)>"
166 "/home/User/project_root/out/obj/foo/bar/static_lib.a"
168 ``TARGET_FILE`` parses the ``.ninja`` file for the GN target, so it should
169 always find the correct output file, regardless of the toolchain's or target's
170 configuration. Some targets, such as ``source_set`` and ``group`` targets, do
171 not have an output file, and attempting to use ``TARGET_FILE`` with them
174 ``TARGET_FILE`` only resolves GN target labels to their outputs. To resolve
175 paths generally, use the standard GN approach of applying the
176 ``rebase_path(path)`` function. With default arguments, ``rebase_path``
177 converts the provided GN path or list of paths to be relative to the build
178 directory, from which all build commands and scripts are executed.
180 .. describe:: <TARGET_FILE_IF_EXISTS(gn_target)>
182 ``TARGET_FILE_IF_EXISTS`` evaluates to the output file of the provided GN
183 target, if the output file exists. If the output file does not exist, the
184 entire argument that includes this expression is omitted, even if there is
185 other text or another expression.
187 For example, consider this expression:
191 "--database=<TARGET_FILE_IF_EXISTS(//alpha/bravo)>"
193 If the ``//alpha/bravo`` target file exists, this might expand to the
198 "--database=/home/User/project/out/obj/alpha/bravo/bravo.elf"
200 If the ``//alpha/bravo`` target file does not exist, the entire
201 ``--database=`` argument is omitted from the script arguments.
203 .. describe:: <TARGET_OBJECTS(gn_target)>
205 Evaluates to the object files of the provided GN target. Expands to a separate
206 argument for each object file. If the target has no object files, the argument
207 is omitted entirely. Because it does not expand to a single expression, the
208 ``<TARGET_OBJECTS(...)>`` expression may not have leading or trailing text.
210 For example, the expression
214 "<TARGET_OBJECTS(//foo/bar:a_source_set)>"
216 might expand to multiple separate arguments:
220 "/home/User/project_root/out/obj/foo/bar/a_source_set.file_a.cc.o"
221 "/home/User/project_root/out/obj/foo/bar/a_source_set.file_b.cc.o"
222 "/home/User/project_root/out/obj/foo/bar/a_source_set.file_c.cc.o"
228 import("$dir_pw_build/python_action.gni")
230 pw_python_action("postprocess_main_image") {
231 script = "py/postprocess_binary.py"
234 rebase_path("my/database.csv"),
235 "--binary=<TARGET_FILE(//firmware/images:main)>",
242 ``pw_input_group`` defines a group of input files which are not directly
243 processed by the build but are still important dependencies of later build
244 steps. This is commonly used alongside metadata to propagate file dependencies
245 through the build graph and force rebuilds on file modifications.
247 For example ``pw_docgen`` defines a ``pw_doc_group`` template which outputs
248 metadata from a list of input files. The metadata file is not actually part of
249 the build, and so changes to any of the input files do not trigger a rebuild.
250 This is problematic, as targets that depend on the metadata should rebuild when
251 the inputs are modified but GN cannot express this dependency.
253 ``pw_input_group`` solves this problem by allowing a list of files to be listed
254 in a target that does not output any build artifacts, causing all dependent
255 targets to correctly rebuild.
259 ``pw_input_group`` accepts all arguments that can be passed to a ``group``
260 target, as well as requiring one extra:
262 * ``inputs``: List of input files.
268 import("$dir_pw_build/input_group.gni")
270 pw_input_group("foo_metadata") {
278 inputs = metadata.files
281 Targets depending on ``foo_metadata`` will rebuild when any of the ``.foo``
286 ``pw_zip`` is a target that allows users to zip up a set of input files and
287 directories into a single output ``.zip`` file—a simple automation of a
288 potentially repetitive task.
292 * ``inputs``: List of source files as well as the desired relative zip
293 destination. See below for the input syntax.
294 * ``dirs``: List of entire directories to be zipped as well as the desired
295 relative zip destination. See below for the input syntax.
296 * ``output``: Filename of output ``.zip`` file.
297 * ``deps``: List of dependencies for the target.
301 Inputs all need to follow the correct syntax:
303 #. Path to source file or directory. Directories must end with a ``/``.
304 #. The delimiter (defaults to ``>``).
305 #. The desired destination of the contents within the ``.zip``. Must start
306 with ``/`` to indicate the zip root. Any number of subdirectories are
307 allowed. If the source is a file it can be put into any subdirectory of the
308 root. If the source is a file, the zip copy can also be renamed by ending
309 the zip destination with a filename (no trailing ``/``).
311 Thus, it should look like the following: ``"[source file or dir] > /"``.
315 Let's say we have the following structure for a ``//source/`` directory:
328 And we create the following build target:
332 import("$dir_pw_build/zip.gni")
334 pw_zip("target_name") {
336 "//source/file1.txt > /", # Copied to the zip root dir.
337 "//source/file2.txt > /renamed.txt", # File renamed.
338 "//source/file3.txt > /bar/", # File moved to the /bar/ dir.
342 "//source/some_dir/ > /bar/some_dir/", # All /some_dir/ contents copied
346 # Note on output: if the specific output directory isn't defined
347 # (such as output = "zoo.zip") then the .zip will output to the
348 # same directory as the BUILD.gn file that called the target.
349 output = "//$target_out_dir/foo.zip" # Where the foo.zip will end up
352 This will result in a ``.zip`` file called ``foo.zip`` stored in
353 ``//$target_out_dir`` with the following structure:
362 │ └── some_other_dir/
369 Pigweed's `CMake`_ support is provided primarily for projects that have an
370 existing CMake build and wish to integrate Pigweed without switching to a new
373 The following command generates Ninja build files for a host build in the
374 ``out/cmake_host`` directory:
378 cmake -B out/cmake_host -S "$PW_ROOT" -G Ninja -DCMAKE_TOOLCHAIN_FILE=$PW_ROOT/pw_toolchain/host_clang/toolchain.cmake
380 The ``PW_ROOT`` environment variable must point to the root of the Pigweed
381 directory. This variable is set by Pigweed's environment setup.
383 Tests can be executed with the ``pw_run_tests.GROUP`` targets. To run Pigweed
384 module tests, execute ``pw_run_tests.modules``:
388 ninja -C out/cmake_host pw_run_tests.modules
390 :ref:`module-pw_watch` supports CMake, so you can also run
394 pw watch -C out/cmake_host pw_run_tests.modules
398 CMake convenience functions are defined in ``pw_build/pigweed.cmake``.
400 * ``pw_auto_add_simple_module`` -- For modules with only one library,
401 automatically declare the library and its tests.
402 * ``pw_auto_add_module_tests`` -- Create test targets for all tests in a module.
403 * ``pw_add_facade`` -- Declare a module facade.
404 * ``pw_set_backend`` -- Set the backend library to use for a facade.
405 * ``pw_add_module_library`` -- Add a library that is part of a module.
406 * ``pw_add_test`` -- Declare a test target.
408 See ``pw_build/pigweed.cmake`` for the complete documentation of these
411 Special libraries that do not fit well with these functions are created with the
412 standard CMake functions, such as ``add_library`` and ``target_link_libraries``.
416 The CMake build uses CMake cache variables for configuring
417 :ref:`facades<docs-module-structure-facades>` and backends. Cache variables are
418 similar to GN's build args set with ``gn args``. Unlike GN, CMake does not
419 support multi-toolchain builds, so these variables have a single global value
422 The ``pw_add_facade`` function declares a cache variable named
423 ``<module_name>_BACKEND`` for each facade. Cache variables can be awkward to
424 work with, since their values only change when they're assigned, but then
425 persist accross CMake invocations. These variables should be set in one of the
428 * Call ``pw_set_backend`` to set backends appropriate for the target in the
429 target's toolchain file. The toolchain file is provided to ``cmake`` with
430 ``-DCMAKE_TOOLCHAIN_FILE=<toolchain file>``.
431 * Call ``pw_set_backend`` in the top-level ``CMakeLists.txt`` before other
433 * Set the backend variable at the command line with the ``-D`` option.
437 cmake -B out/cmake_host -S "$PW_ROOT" -G Ninja \
438 -DCMAKE_TOOLCHAIN_FILE=$PW_ROOT/pw_toolchain/host_clang/toolchain.cmake \
439 -Dpw_log_BACKEND=pw_log_basic
441 * Temporarily override a backend by setting it interactively with ``ccmake`` or
446 In CMake, the toolchain is configured by setting CMake variables, as described
447 in the `CMake documentation <https://cmake.org/cmake/help/latest/manual/cmake-toolchains.7.html>`_.
448 These variables are typically set in a toolchain CMake file passed to ``cmake``
449 with the ``-D`` option (``-DCMAKE_TOOLCHAIN_FILE=path/to/file.cmake``).
450 For Pigweed embedded builds, set ``CMAKE_SYSTEM_NAME`` to the empty string
453 Third party libraries
454 ---------------------
455 The CMake build includes third-party libraries similarly to the GN build. A
456 ``dir_pw_third_party_<library>`` cache variable is defined for each third-party
457 dependency. This variable can have one of three values:
459 * ``""`` (empty) -- the dependency is not available
460 * ``PRESENT`` -- the dependency is available and is already included in the
462 * ``</path/to/the/dependency>`` -- the dependency is available and will be
463 automatically imported from this path using ``add_subdirectory``.
465 If the variable is empty (``if("${dir_pw_third_party_<library>}" STREQUAL
466 "")``), the dependency is not available. Otherwise, it is available and
467 libraries declared by it can be referenced.
469 Third party variables are set like any other cache global variable in CMake. It
470 is recommended to set these in one of the following ways:
472 * Set with the CMake ``set`` function in the toolchain file or a
473 ``CMakeLists.txt`` before other CMake code executes.
475 .. code-block:: cmake
477 set(dir_pw_third_party_nanopb PRESENT CACHE STRING "" FORCE)
479 * Set the variable at the command line with the ``-D`` option.
483 cmake -B out/cmake_host -S "$PW_ROOT" -G Ninja \
484 -DCMAKE_TOOLCHAIN_FILE=$PW_ROOT/pw_toolchain/host_clang/toolchain.cmake \
485 -Ddir_pw_third_party_nanopb=/path/to/nanopb
487 * Set the variable interactively with ``ccmake`` or ``cmake-gui``.
489 Use Pigweed from an existing CMake project
490 ------------------------------------------
491 To use Pigweed libraries form a CMake-based project, simply include the Pigweed
492 repository from a ``CMakeLists.txt``.
494 .. code-block:: cmake
496 add_subdirectory(path/to/pigweed pigweed)
498 All module libraries will be available as ``module_name`` or
499 ``module_name.sublibrary``.
501 If desired, modules can be included individually.
503 .. code-block:: cmake
505 add_subdirectory(path/to/pigweed/pw_some_module pw_some_module)
506 add_subdirectory(path/to/pigweed/pw_another_module pw_another_module)
510 Bazel is currently very experimental, and only builds for host.
512 The common configuration for Bazel for all modules is in the ``pigweed.bzl``
513 file. The built-in Bazel rules ``cc_binary``, ``cc_library``, and ``cc_test``
514 are wrapped with ``pw_cc_binary``, ``pw_cc_library``, and ``pw_cc_test``.
515 These wrappers add parameters to calls to the compiler and linker.
517 The ``BUILD`` file is merely a placeholder and currently does nothing.