blob: 64c67f99555c3a11bc5f3432b63f04819968a96f [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^^^^^^^^^^^^
Alexei Frolov69ad1922019-12-13 13:11:32 -080045.. code::
46
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 Heplerf9fb90f2020-09-30 18:59:33 -070078.. _module-pw_build-python-script:
Alexei Frolov199045a2020-08-28 13:02:30 -070079
Wyatt Heplerc8e05a42020-10-19 14:49:39 -070080pw_python_action
Alexei Frolov69ad1922019-12-13 13:11:32 -080081^^^^^^^^^^^^^^^^
Wyatt Heplerc8e05a42020-10-19 14:49:39 -070082The ``pw_python_action`` template is a convenience wrapper around ``action`` for
Wyatt Hepler8224a642020-07-29 08:55:56 -070083running Python scripts. The main benefit it provides is resolution of GN target
84labels to compiled binary files. This allows Python scripts to be written
85independently of GN, taking only filesystem paths as arguments.
Alexei Frolov69ad1922019-12-13 13:11:32 -080086
87Another convenience provided by the template is to allow running scripts without
88any outputs. Sometimes scripts run in a build do not directly produce output
Wyatt Heplerc8e05a42020-10-19 14:49:39 -070089files, but GN requires that all actions have an output. ``pw_python_action``
Alexei Frolov69ad1922019-12-13 13:11:32 -080090solves this by accepting a boolean ``stamp`` argument which tells it to create a
91dummy output file for the action.
92
93**Arguments**
94
Wyatt Heplerc8e05a42020-10-19 14:49:39 -070095``pw_python_action`` accepts all of the arguments of a regular ``action``
Alexei Frolov69ad1922019-12-13 13:11:32 -080096target. Additionally, it has some of its own arguments:
97
Wyatt Hepler79d983f2020-10-12 08:46:34 -070098* ``module``: Run the specified Python module instead of a script. Either
99 ``script`` or ``module`` must be specified, but not both.
Wyatt Heplera74f7b02020-07-23 14:10:56 -0700100* ``capture_output``: Optional boolean. If true, script output is hidden unless
101 the script fails with an error. Defaults to true.
102* ``stamp``: Optional variable indicating whether to automatically create a
103 dummy output file for the script. This allows running scripts without
104 specifying ``outputs``. If ``stamp`` is true, a generic output file is
105 used. If ``stamp`` is a file path, that file is used as a stamp file. Like any
106 output file, ``stamp`` must be in the build directory. Defaults to false.
Wyatt Hepler79d983f2020-10-12 08:46:34 -0700107* ``directory``: Optional path. Change to this directory before executing the
108 command. Paths in arguments may need to be adjusted.
109* ``environment``: Optional list of strings. Environment variables to set,
110 passed as NAME=VALUE strings.
Alexei Frolov69ad1922019-12-13 13:11:32 -0800111
Wyatt Hepler8224a642020-07-29 08:55:56 -0700112**Expressions**
113
Wyatt Heplerc8e05a42020-10-19 14:49:39 -0700114``pw_python_action`` evaluates expressions in ``args``, the arguments passed to
Wyatt Hepler8224a642020-07-29 08:55:56 -0700115the script. These expressions function similarly to generator expressions in
116CMake. Expressions may be passed as a standalone argument or as part of another
117argument. A single argument may contain multiple expressions.
118
119Generally, these expressions are used within templates rather than directly in
120BUILD.gn files. This allows build code to use GN labels without having to worry
121about converting them to files.
122
Wyatt Hepler53a06fb2020-07-31 13:04:56 -0700123The following expressions are supported:
Wyatt Hepler8224a642020-07-29 08:55:56 -0700124
125.. describe:: <TARGET_FILE(gn_target)>
126
127 Evaluates to the output file of the provided GN target. For example, the
128 expression
129
130 .. code::
131
132 "<TARGET_FILE(//foo/bar:static_lib)>"
133
134 might expand to
135
136 .. code::
137
138 "/home/User/project_root/out/obj/foo/bar/static_lib.a"
139
140 ``TARGET_FILE`` parses the ``.ninja`` file for the GN target, so it should
141 always find the correct output file, regardless of the toolchain's or target's
142 configuration. Some targets, such as ``source_set`` and ``group`` targets, do
143 not have an output file, and attempting to use ``TARGET_FILE`` with them
144 results in an error.
145
146 ``TARGET_FILE`` only resolves GN target labels to their outputs. To resolve
147 paths generally, use the standard GN approach of applying the
148 ``rebase_path(path)`` function. With default arguments, ``rebase_path``
149 converts the provided GN path or list of paths to be relative to the build
150 directory, from which all build commands and scripts are executed.
151
Wyatt Hepler53a06fb2020-07-31 13:04:56 -0700152.. describe:: <TARGET_FILE_IF_EXISTS(gn_target)>
153
154 ``TARGET_FILE_IF_EXISTS`` evaluates to the output file of the provided GN
155 target, if the output file exists. If the output file does not exist, the
156 entire argument that includes this expression is omitted, even if there is
157 other text or another expression.
158
159 For example, consider this expression:
160
161 .. code::
162
163 "--database=<TARGET_FILE_IF_EXISTS(//alpha/bravo)>"
164
165 If the ``//alpha/bravo`` target file exists, this might expand to the
166 following:
167
168 .. code::
169
170 "--database=/home/User/project/out/obj/alpha/bravo/bravo.elf"
171
172 If the ``//alpha/bravo`` target file does not exist, the entire
173 ``--database=`` argument is omitted from the script arguments.
174
175.. describe:: <TARGET_OBJECTS(gn_target)>
176
177 Evaluates to the object files of the provided GN target. Expands to a separate
178 argument for each object file. If the target has no object files, the argument
179 is omitted entirely. Because it does not expand to a single expression, the
180 ``<TARGET_OBJECTS(...)>`` expression may not have leading or trailing text.
181
182 For example, the expression
183
184 .. code::
185
186 "<TARGET_OBJECTS(//foo/bar:a_source_set)>"
187
188 might expand to multiple separate arguments:
189
190 .. code::
191
192 "/home/User/project_root/out/obj/foo/bar/a_source_set.file_a.cc.o"
193 "/home/User/project_root/out/obj/foo/bar/a_source_set.file_b.cc.o"
194 "/home/User/project_root/out/obj/foo/bar/a_source_set.file_c.cc.o"
195
Alexei Frolov69ad1922019-12-13 13:11:32 -0800196**Example**
197
198.. code::
199
Wyatt Hepler51ded742020-10-19 14:45:27 -0700200 import("$dir_pw_build/python_action.gni")
Alexei Frolov69ad1922019-12-13 13:11:32 -0800201
Wyatt Heplerc8e05a42020-10-19 14:49:39 -0700202 pw_python_action("postprocess_main_image") {
Wyatt Hepler8224a642020-07-29 08:55:56 -0700203 script = "py/postprocess_binary.py"
204 args = [
205 "--database",
206 rebase_path("my/database.csv"),
207 "--binary=<TARGET_FILE(//firmware/images:main)>",
208 ]
Alexei Frolov69ad1922019-12-13 13:11:32 -0800209 stamp = true
210 }
211
212pw_input_group
213^^^^^^^^^^^^^^
214``pw_input_group`` defines a group of input files which are not directly
215processed by the build but are still important dependencies of later build
216steps. This is commonly used alongside metadata to propagate file dependencies
217through the build graph and force rebuilds on file modifications.
218
219For example ``pw_docgen`` defines a ``pw_doc_group`` template which outputs
220metadata from a list of input files. The metadata file is not actually part of
221the build, and so changes to any of the input files do not trigger a rebuild.
222This is problematic, as targets that depend on the metadata should rebuild when
223the inputs are modified but GN cannot express this dependency.
224
225``pw_input_group`` solves this problem by allowing a list of files to be listed
226in a target that does not output any build artifacts, causing all dependent
227targets to correctly rebuild.
228
229**Arguments**
230
231``pw_input_group`` accepts all arguments that can be passed to a ``group``
232target, as well as requiring one extra:
233
234* ``inputs``: List of input files.
235
236**Example**
237
238.. code::
239
240 import("$dir_pw_build/input_group.gni")
241
242 pw_input_group("foo_metadata") {
243 metadata = {
244 files = [
245 "x.foo",
246 "y.foo",
247 "z.foo",
248 ]
249 }
250 inputs = metadata.files
251 }
252
253Targets depending on ``foo_metadata`` will rebuild when any of the ``.foo``
254files are modified.
Rob Mohr84f234e2019-12-06 09:16:50 -0800255
Sam McCauley0da412c2020-10-02 10:34:56 -0700256pw_zip
257^^^^^^^^^^^^^^
258``pw_zip`` is a target that allows users to zip up a set of input files and
259directories into a single output ``.zip`` file—a simple automation of a
260potentially repetitive task.
261
262**Arguments**
263
264* ``inputs``: List of source files as well as the desired relative zip
265 destination. See below for the input syntax.
266* ``dirs``: List of entire directories to be zipped as well as the desired
267 relative zip destination. See below for the input syntax.
268* ``output``: Filename of output ``.zip`` file.
269* ``deps``: List of dependencies for the target.
270
271**Input Syntax**
272
273Inputs all need to follow the correct syntax:
274
275#. Path to source file or directory. Directories must end with a ``/``.
276#. The delimiter (defaults to ``>``).
277#. The desired destination of the contents within the ``.zip``. Must start
278 with ``/`` to indicate the zip root. Any number of subdirectories are
279 allowed. If the source is a file it can be put into any subdirectory of the
280 root. If the source is a file, the zip copy can also be renamed by ending
281 the zip destination with a filename (no trailing ``/``).
282
283Thus, it should look like the following: ``"[source file or dir] > /"``.
284
285**Example**
286
287Let's say we have the following structure for a ``//source/`` directory:
288
289.. code::
290
291 source/
292 ├── file1.txt
293 ├── file2.txt
294 ├── file3.txt
295 └── some_dir/
296 ├── file4.txt
297 └── some_other_dir/
298 └── file5.txt
299
300And we create the following build target:
301
302.. code::
303
304 import("$dir_pw_build/zip.gni")
305
306 pw_zip("target_name") {
307 inputs = [
308 "//source/file1.txt > /", # Copied to the zip root dir.
309 "//source/file2.txt > /renamed.txt", # File renamed.
310 "//source/file3.txt > /bar/", # File moved to the /bar/ dir.
311 ]
312
313 dirs = [
314 "//source/some_dir/ > /bar/some_dir/", # All /some_dir/ contents copied
315 # as /bar/some_dir/.
316 ]
317
318 # Note on output: if the specific output directory isn't defined
319 # (such as output = "zoo.zip") then the .zip will output to the
320 # same directory as the BUILD.gn file that called the target.
321 output = "//$target_out_dir/foo.zip" # Where the foo.zip will end up
322 }
323
324This will result in a ``.zip`` file called ``foo.zip`` stored in
325``//$target_out_dir`` with the following structure:
326
327.. code::
328
329 foo.zip
330 ├── bar/
331 │   ├── file3.txt
332 │   └── some_dir/
333 │   ├── file4.txt
334 │   └── some_other_dir/
335 │   └── file5.txt
336 ├── file1.txt
337 └── renamed.txt
338
Wyatt Hepler0fbcdfc2020-01-02 07:53:39 -0800339CMake / Ninja
340=============
Armando Montanezbcc194b2020-03-10 10:23:18 -0700341
342Pigweed's CMake support is provided primarily for projects that have an existing
343CMake build and wish to integrate Pigweed without switching to a new build
344system.
345
Wyatt Hepler0fbcdfc2020-01-02 07:53:39 -0800346The following command generates Ninja build files in the out/cmake directory.
347
348.. code:: sh
349
350 cmake -B out/cmake -S /path/to/pigweed -G Ninja
351
352Tests can be executed with the ``pw_run_tests_GROUP`` targets. To run the basic
353Pigweed tests, run ``ninja -C out/cmake pw_run_tests_modules``.
354
355CMake functions
356---------------
357CMake convenience functions are defined in ``pw_build/pigweed.cmake``.
358
359* ``pw_auto_add_simple_module`` -- For modules with only one library,
360 automatically declare the library and its tests.
361* ``pw_add_facade`` -- Declare a module facade.
362* ``pw_add_module_library`` -- Add a library that is part of a module.
363* ``pw_add_test`` -- Declare a test target.
364
365See ``pw_build/pigweed.cmake`` for the complete documentation of these
366functions.
367
368Special libraries that do not fit well with these functions are created with the
369standard CMake functions, such as ``add_library`` and ``target_link_libraries``.
370
371Use Pigweed from an existing CMake project
372------------------------------------------
373To use Pigweed libraries form a CMake-based project, simply include the Pigweed
374repository from a ``CMakeLists.txt``.
375
376.. code:: cmake
377
378 add_subdirectory(path/to/pigweed pigweed)
379
380All module libraries will be available as ``module_name`` or
381``module_name.sublibrary``.
382
383If desired, modules can be included individually.
384
385.. code:: cmake
386
387 include(path/to/pigweed/pw_build/pigweed.cmake)
388
389 add_subdirectory(path/to/pigweed/pw_some_module pw_some_module)
390 add_subdirectory(path/to/pigweed/pw_another_module pw_another_module)
391
Rob Mohr84f234e2019-12-06 09:16:50 -0800392Bazel
393=====
Armando Montanezbcc194b2020-03-10 10:23:18 -0700394
395Bazel is currently very experimental, and only builds for host.
396
Rob Mohr84f234e2019-12-06 09:16:50 -0800397The common configuration for Bazel for all modules is in the ``pigweed.bzl``
398file. The built-in Bazel rules ``cc_binary``, ``cc_library``, and ``cc_test``
399are wrapped with ``pw_cc_binary``, ``pw_cc_library``, and ``pw_cc_test``.
400These wrappers add parameters to calls to the compiler and linker.
401
402The ``BUILD`` file is merely a placeholder and currently does nothing.