blob: d1504b4cacfecdf46f8cb00ff16e16d7f83ef3f1 [file] [log] [blame]
Wyatt Heplerf9fb90f2020-09-30 18:59:33 -07001.. _module-pw_build:
Alexei Frolov9d169d52020-03-03 17:20:06 -08002
Rob Mohr84f234e2019-12-06 09:16:50 -08003--------
4pw_build
5--------
Alexei Frolov9d169d52020-03-03 17:20:06 -08006Pigweed's modules aim to be easily integratable into both new and existing
7embedded projects. To that goal, the ``pw_build`` module provides support for
8multiple build systems. Our personal favorite is `GN`_/`Ninja`_, which is used
9by upstream developers for its speed and flexibility. `CMake`_ and `Bazel`_
10build files are also provided by all modules, allowing Pigweed to be added to a
11project with minimal effort.
Rob Mohr84f234e2019-12-06 09:16:50 -080012
13.. _GN: https://gn.googlesource.com/gn/
14.. _Ninja: https://ninja-build.org/
Alexei Frolov9d169d52020-03-03 17:20:06 -080015.. _CMake: https://cmake.org/
Rob Mohr84f234e2019-12-06 09:16:50 -080016.. _Bazel: https://bazel.build/
17
Alexei Frolov9d169d52020-03-03 17:20:06 -080018Beyond just compiling code, Pigweed’s GN build system can also:
19
20* Generate HTML documentation, via our Sphinx integration (with ``pw_docgen``)
Armando Montanez0054a9b2020-03-13 13:06:24 -070021* Display memory usage report cards (with ``pw_bloat``)
Alexei Frolov9d169d52020-03-03 17:20:06 -080022* Incrementally run unit tests after code changes (with ``pw_target_runner``)
23* And more!
24
25These are only supported in the GN build, so we recommend using it if possible.
26
Rob Mohr84f234e2019-12-06 09:16:50 -080027GN / Ninja
28==========
Armando Montanezbcc194b2020-03-10 10:23:18 -070029The GN / Ninja build system is the primary build system used for upstream
30Pigweed development, and is the most tested and feature-rich build system
31Pigweed offers.
Rob Mohr84f234e2019-12-06 09:16:50 -080032
Armando Montanezbcc194b2020-03-10 10:23:18 -070033This module's ``build.gn`` file contains a number of C/C++ ``config``
34declarations that are used by upstream Pigweed to set some architecture-agnostic
35compiler defaults. (See Pigweed's ``//BUILDCONFIG.gn``)
36
Armando Montanez0054a9b2020-03-13 13:06:24 -070037``pw_build`` also provides several useful GN templates that are used throughout
Armando Montanezbcc194b2020-03-10 10:23:18 -070038Pigweed.
Alexei Frolov69ad1922019-12-13 13:11:32 -080039
40Templates
41---------
42
Alexei Frolovedd2f142020-06-09 19:11:27 -070043Target types
44^^^^^^^^^^^^
Wyatt Heplere0575f72020-10-16 10:47:03 -070045.. code-block::
Alexei Frolov69ad1922019-12-13 13:11:32 -080046
Alexei Frolovedd2f142020-06-09 19:11:27 -070047 import("$dir_pw_build/target_types.gni")
Alexei Frolov69ad1922019-12-13 13:11:32 -080048
Alexei Frolovedd2f142020-06-09 19:11:27 -070049 pw_source_set("my_library") {
50 sources = [ "lib.cc" ]
51 }
52
53Pigweed defines wrappers around the four basic GN binary types ``source_set``,
54``executable``, ``static_library``, and ``shared_library``. These wrappers apply
55default arguments to each target as specified in the ``default_configs`` and
56``default_public_deps`` build args. Additionally, they allow defaults to be
57removed on a per-target basis using ``remove_configs`` and
58``remove_public_deps`` variables, respectively.
59
60The ``pw_executable`` template provides additional functionality around building
61complete binaries. As Pigweed is a collection of libraries, it does not know how
62its final targets are built. ``pw_executable`` solves this by letting each user
63of Pigweed specify a global executable template for their target, and have
64Pigweed build against it. This is controlled by the build variable
65``pw_executable_config.target_type``, specifying the name of the executable
66template for a project.
Alexei Frolov69ad1922019-12-13 13:11:32 -080067
68.. tip::
69
70 Prefer to use ``pw_executable`` over plain ``executable`` targets to allow
71 cleanly building the same code for multiple target configs.
72
73**Arguments**
74
Alexei Frolovedd2f142020-06-09 19:11:27 -070075All of the ``pw_*`` target type overrides accept any arguments, as they simply
76forward them through to the underlying target.
Alexei Frolov69ad1922019-12-13 13:11:32 -080077
Wyatt Heplere0575f72020-10-16 10:47:03 -070078.. _module-pw_build-facade:
79
80pw_facade
81^^^^^^^^^
82In their simplest form, a :ref:`facade<docs-module-structure-facades>` is a GN
83build arg used to change a dependency at compile time. Pigweed targets configure
84these facades as needed.
85
86The ``pw_facade`` template bundles a ``pw_source_set`` with a facade build arg.
87This allows the facade to provide header files, compilation options or anything
88else a GN ``source_set`` provides.
89
90The ``pw_facade`` template declares two targets:
91
92* ``$target_name``: the public-facing ``pw_source_set``, with a ``public_dep``
93 on the backend
94* ``$target_name.facade``: target used by the backend to avoid circular
95 dependencies
96
97.. code-block::
98
99 # Declares ":foo" and ":foo.facade" GN targets
100 pw_facade("foo") {
101 backend = pw_log_BACKEND
102 public_configs = [ ":public_include_path" ]
103 public = [ "public/pw_foo/foo.h" ]
104 }
105
Wyatt Hepler0d32d1d2020-10-23 08:05:23 -0700106.. _module-pw_build-python-action:
Alexei Frolov199045a2020-08-28 13:02:30 -0700107
Wyatt Heplerc8e05a42020-10-19 14:49:39 -0700108pw_python_action
Alexei Frolov69ad1922019-12-13 13:11:32 -0800109^^^^^^^^^^^^^^^^
Wyatt Heplerc8e05a42020-10-19 14:49:39 -0700110The ``pw_python_action`` template is a convenience wrapper around ``action`` for
Wyatt Hepler8224a642020-07-29 08:55:56 -0700111running Python scripts. The main benefit it provides is resolution of GN target
112labels to compiled binary files. This allows Python scripts to be written
113independently of GN, taking only filesystem paths as arguments.
Alexei Frolov69ad1922019-12-13 13:11:32 -0800114
115Another convenience provided by the template is to allow running scripts without
116any outputs. Sometimes scripts run in a build do not directly produce output
Wyatt Heplerc8e05a42020-10-19 14:49:39 -0700117files, but GN requires that all actions have an output. ``pw_python_action``
Alexei Frolov69ad1922019-12-13 13:11:32 -0800118solves this by accepting a boolean ``stamp`` argument which tells it to create a
119dummy output file for the action.
120
121**Arguments**
122
Wyatt Heplerc8e05a42020-10-19 14:49:39 -0700123``pw_python_action`` accepts all of the arguments of a regular ``action``
Alexei Frolov69ad1922019-12-13 13:11:32 -0800124target. Additionally, it has some of its own arguments:
125
Wyatt Hepler79d983f2020-10-12 08:46:34 -0700126* ``module``: Run the specified Python module instead of a script. Either
127 ``script`` or ``module`` must be specified, but not both.
Wyatt Heplera74f7b02020-07-23 14:10:56 -0700128* ``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.
Wyatt Hepler79d983f2020-10-12 08:46:34 -0700135* ``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.
Alexei Frolov69ad1922019-12-13 13:11:32 -0800139
Wyatt Hepler8224a642020-07-29 08:55:56 -0700140**Expressions**
141
Wyatt Heplerc8e05a42020-10-19 14:49:39 -0700142``pw_python_action`` evaluates expressions in ``args``, the arguments passed to
Wyatt Hepler8224a642020-07-29 08:55:56 -0700143the script. These expressions function similarly to generator expressions in
144CMake. Expressions may be passed as a standalone argument or as part of another
145argument. A single argument may contain multiple expressions.
146
147Generally, these expressions are used within templates rather than directly in
148BUILD.gn files. This allows build code to use GN labels without having to worry
149about converting them to files.
150
Wyatt Hepler53a06fb2020-07-31 13:04:56 -0700151The following expressions are supported:
Wyatt Hepler8224a642020-07-29 08:55:56 -0700152
153.. describe:: <TARGET_FILE(gn_target)>
154
155 Evaluates to the output file of the provided GN target. For example, the
156 expression
157
Wyatt Heplere0575f72020-10-16 10:47:03 -0700158 .. code-block::
Wyatt Hepler8224a642020-07-29 08:55:56 -0700159
160 "<TARGET_FILE(//foo/bar:static_lib)>"
161
162 might expand to
163
Wyatt Heplere0575f72020-10-16 10:47:03 -0700164 .. code-block::
Wyatt Hepler8224a642020-07-29 08:55:56 -0700165
166 "/home/User/project_root/out/obj/foo/bar/static_lib.a"
167
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
172 results in an error.
173
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.
179
Wyatt Hepler53a06fb2020-07-31 13:04:56 -0700180.. describe:: <TARGET_FILE_IF_EXISTS(gn_target)>
181
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.
186
187 For example, consider this expression:
188
Wyatt Heplere0575f72020-10-16 10:47:03 -0700189 .. code-block::
Wyatt Hepler53a06fb2020-07-31 13:04:56 -0700190
191 "--database=<TARGET_FILE_IF_EXISTS(//alpha/bravo)>"
192
193 If the ``//alpha/bravo`` target file exists, this might expand to the
194 following:
195
Wyatt Heplere0575f72020-10-16 10:47:03 -0700196 .. code-block::
Wyatt Hepler53a06fb2020-07-31 13:04:56 -0700197
198 "--database=/home/User/project/out/obj/alpha/bravo/bravo.elf"
199
200 If the ``//alpha/bravo`` target file does not exist, the entire
201 ``--database=`` argument is omitted from the script arguments.
202
203.. describe:: <TARGET_OBJECTS(gn_target)>
204
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.
209
210 For example, the expression
211
Wyatt Heplere0575f72020-10-16 10:47:03 -0700212 .. code-block::
Wyatt Hepler53a06fb2020-07-31 13:04:56 -0700213
214 "<TARGET_OBJECTS(//foo/bar:a_source_set)>"
215
216 might expand to multiple separate arguments:
217
Wyatt Heplere0575f72020-10-16 10:47:03 -0700218 .. code-block::
Wyatt Hepler53a06fb2020-07-31 13:04:56 -0700219
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"
223
Alexei Frolov69ad1922019-12-13 13:11:32 -0800224**Example**
225
Wyatt Heplere0575f72020-10-16 10:47:03 -0700226.. code-block::
Alexei Frolov69ad1922019-12-13 13:11:32 -0800227
Wyatt Hepler51ded742020-10-19 14:45:27 -0700228 import("$dir_pw_build/python_action.gni")
Alexei Frolov69ad1922019-12-13 13:11:32 -0800229
Wyatt Heplerc8e05a42020-10-19 14:49:39 -0700230 pw_python_action("postprocess_main_image") {
Wyatt Hepler8224a642020-07-29 08:55:56 -0700231 script = "py/postprocess_binary.py"
232 args = [
233 "--database",
234 rebase_path("my/database.csv"),
235 "--binary=<TARGET_FILE(//firmware/images:main)>",
236 ]
Alexei Frolov69ad1922019-12-13 13:11:32 -0800237 stamp = true
238 }
239
240pw_input_group
241^^^^^^^^^^^^^^
242``pw_input_group`` defines a group of input files which are not directly
243processed by the build but are still important dependencies of later build
244steps. This is commonly used alongside metadata to propagate file dependencies
245through the build graph and force rebuilds on file modifications.
246
247For example ``pw_docgen`` defines a ``pw_doc_group`` template which outputs
248metadata from a list of input files. The metadata file is not actually part of
249the build, and so changes to any of the input files do not trigger a rebuild.
250This is problematic, as targets that depend on the metadata should rebuild when
251the inputs are modified but GN cannot express this dependency.
252
253``pw_input_group`` solves this problem by allowing a list of files to be listed
254in a target that does not output any build artifacts, causing all dependent
255targets to correctly rebuild.
256
257**Arguments**
258
259``pw_input_group`` accepts all arguments that can be passed to a ``group``
260target, as well as requiring one extra:
261
262* ``inputs``: List of input files.
263
264**Example**
265
Wyatt Heplere0575f72020-10-16 10:47:03 -0700266.. code-block::
Alexei Frolov69ad1922019-12-13 13:11:32 -0800267
268 import("$dir_pw_build/input_group.gni")
269
270 pw_input_group("foo_metadata") {
271 metadata = {
272 files = [
273 "x.foo",
274 "y.foo",
275 "z.foo",
276 ]
277 }
278 inputs = metadata.files
279 }
280
281Targets depending on ``foo_metadata`` will rebuild when any of the ``.foo``
282files are modified.
Rob Mohr84f234e2019-12-06 09:16:50 -0800283
Sam McCauley0da412c2020-10-02 10:34:56 -0700284pw_zip
Wyatt Heplere0575f72020-10-16 10:47:03 -0700285^^^^^^
Sam McCauley0da412c2020-10-02 10:34:56 -0700286``pw_zip`` is a target that allows users to zip up a set of input files and
287directories into a single output ``.zip`` file—a simple automation of a
288potentially repetitive task.
289
290**Arguments**
291
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.
298
299**Input Syntax**
300
301Inputs all need to follow the correct syntax:
302
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 ``/``).
310
311Thus, it should look like the following: ``"[source file or dir] > /"``.
312
313**Example**
314
315Let's say we have the following structure for a ``//source/`` directory:
316
Wyatt Heplere0575f72020-10-16 10:47:03 -0700317.. code-block::
Sam McCauley0da412c2020-10-02 10:34:56 -0700318
319 source/
320 ├── file1.txt
321 ├── file2.txt
322 ├── file3.txt
323 └── some_dir/
324 ├── file4.txt
325 └── some_other_dir/
326 └── file5.txt
327
328And we create the following build target:
329
Wyatt Heplere0575f72020-10-16 10:47:03 -0700330.. code-block::
Sam McCauley0da412c2020-10-02 10:34:56 -0700331
332 import("$dir_pw_build/zip.gni")
333
334 pw_zip("target_name") {
335 inputs = [
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.
339 ]
340
341 dirs = [
342 "//source/some_dir/ > /bar/some_dir/", # All /some_dir/ contents copied
343 # as /bar/some_dir/.
344 ]
345
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
350 }
351
352This will result in a ``.zip`` file called ``foo.zip`` stored in
353``//$target_out_dir`` with the following structure:
354
Wyatt Heplere0575f72020-10-16 10:47:03 -0700355.. code-block::
Sam McCauley0da412c2020-10-02 10:34:56 -0700356
357 foo.zip
358 ├── bar/
359 │   ├── file3.txt
360 │   └── some_dir/
361 │   ├── file4.txt
362 │   └── some_other_dir/
363 │   └── file5.txt
364 ├── file1.txt
365 └── renamed.txt
366
Wyatt Hepler0fbcdfc2020-01-02 07:53:39 -0800367CMake / Ninja
368=============
Armando Montanezbcc194b2020-03-10 10:23:18 -0700369
370Pigweed's CMake support is provided primarily for projects that have an existing
371CMake build and wish to integrate Pigweed without switching to a new build
372system.
373
Wyatt Hepler0fbcdfc2020-01-02 07:53:39 -0800374The following command generates Ninja build files in the out/cmake directory.
375
Wyatt Heplere0575f72020-10-16 10:47:03 -0700376.. code-block:: sh
Wyatt Hepler0fbcdfc2020-01-02 07:53:39 -0800377
378 cmake -B out/cmake -S /path/to/pigweed -G Ninja
379
380Tests can be executed with the ``pw_run_tests_GROUP`` targets. To run the basic
381Pigweed tests, run ``ninja -C out/cmake pw_run_tests_modules``.
382
383CMake functions
384---------------
385CMake convenience functions are defined in ``pw_build/pigweed.cmake``.
386
387* ``pw_auto_add_simple_module`` -- For modules with only one library,
388 automatically declare the library and its tests.
389* ``pw_add_facade`` -- Declare a module facade.
390* ``pw_add_module_library`` -- Add a library that is part of a module.
391* ``pw_add_test`` -- Declare a test target.
392
393See ``pw_build/pigweed.cmake`` for the complete documentation of these
394functions.
395
396Special libraries that do not fit well with these functions are created with the
397standard CMake functions, such as ``add_library`` and ``target_link_libraries``.
398
399Use Pigweed from an existing CMake project
400------------------------------------------
401To use Pigweed libraries form a CMake-based project, simply include the Pigweed
402repository from a ``CMakeLists.txt``.
403
Wyatt Heplere0575f72020-10-16 10:47:03 -0700404.. code-block:: cmake
Wyatt Hepler0fbcdfc2020-01-02 07:53:39 -0800405
406 add_subdirectory(path/to/pigweed pigweed)
407
408All module libraries will be available as ``module_name`` or
409``module_name.sublibrary``.
410
411If desired, modules can be included individually.
412
Wyatt Heplere0575f72020-10-16 10:47:03 -0700413.. code-block:: cmake
Wyatt Hepler0fbcdfc2020-01-02 07:53:39 -0800414
415 include(path/to/pigweed/pw_build/pigweed.cmake)
416
417 add_subdirectory(path/to/pigweed/pw_some_module pw_some_module)
418 add_subdirectory(path/to/pigweed/pw_another_module pw_another_module)
419
Rob Mohr84f234e2019-12-06 09:16:50 -0800420Bazel
421=====
Armando Montanezbcc194b2020-03-10 10:23:18 -0700422
423Bazel is currently very experimental, and only builds for host.
424
Rob Mohr84f234e2019-12-06 09:16:50 -0800425The common configuration for Bazel for all modules is in the ``pigweed.bzl``
426file. The built-in Bazel rules ``cc_binary``, ``cc_library``, and ``cc_test``
427are wrapped with ``pw_cc_binary``, ``pw_cc_library``, and ``pw_cc_test``.
428These wrappers add parameters to calls to the compiler and linker.
429
430The ``BUILD`` file is merely a placeholder and currently does nothing.