1.. _module-pw_build: 2 3-------- 4pw_build 5-------- 6Pigweed'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. 12 13.. _GN: https://gn.googlesource.com/gn/ 14.. _Ninja: https://ninja-build.org/ 15.. _CMake: https://cmake.org/ 16.. _Bazel: https://bazel.build/ 17 18Beyond just compiling code, Pigweed’s GN build system can also: 19 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``) 23* And more! 24 25These are only supported in the GN build, so we recommend using it if possible. 26 27GN / Ninja 28========== 29The 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. 32 33This 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 37``pw_build`` also provides several useful GN templates that are used throughout 38Pigweed. 39 40Build system philosophies 41------------------------- 42While Pigweed's GN build is not hermetic, it strives to adhere to principles of 43`hermeticity <https://bazel.build/concepts/hermeticity>`_. Some guidelines to 44move towards the ideal of hermeticity include: 45 46* Only rely on pre-compiled tools provided by CIPD (or some other versioned, 47 pre-compiled binary distribution mechanism). This eliminates build artifact 48 differences caused by different tool versions or variations (e.g. same tool 49 version built with slightly different compilation flags). 50* Do not use absolute paths in Ninja commands. Typically, these appear when 51 using ``rebase_path("//path/to/my_script.py")``. Most of the time, Ninja 52 steps should be passed paths rebased relative to the build directory (i.e. 53 ``rebase_path("//path/to/my_script.py", root_build_dir)``). This ensures build 54 commands are the same across different machines. 55* Prevent produced artifacts from relying on or referencing system state. This 56 includes time stamps, writing absolute paths to generated artifacts, or 57 producing artifacts that reference system state in a way that prevents them 58 from working the same way on a different machine. 59* Isolate build actions to the build directory. In general, the build system 60 should not add or modify files outside of the build directory. This can cause 61 confusion to users, and makes the concept of a clean build more ambiguous. 62 63Target types 64------------ 65.. code-block:: 66 67 import("$dir_pw_build/target_types.gni") 68 69 pw_source_set("my_library") { 70 sources = [ "lib.cc" ] 71 } 72 73Pigweed defines wrappers around the four basic GN binary types ``source_set``, 74``executable``, ``static_library``, and ``shared_library``. These templates 75do several things: 76 77#. **Add default configs/deps** 78 79 Rather than binding the majority of compiler flags related to C++ standard, 80 cross-compilation, warning/error policy, etc. directly to toolchain 81 invocations, these flags are applied as configs to all ``pw_*`` C/C++ target 82 types. The primary motivations for this are to allow some targets to modify 83 the default set of flags when needed by specifying ``remove_configs``, and to 84 reduce the complexity of building novel toolchains. 85 86 Pigweed's global default configs are set in ``pw_build/default.gni``, and 87 individual platform-specific toolchains extend the list by appending to the 88 ``default_configs`` build argument. 89 90 Default deps were added to support polyfill, which has since been 91 deprecated. Default dependency functionality continues to exist for 92 backwards compatibility. 93 94#. **Optionally add link-time binding** 95 96 Some libraries like pw_assert and pw_log are borderline impossible to 97 implement well without introducing circular dependencies. One solution for 98 addressing this is to break apart the libraries into an interface with 99 minimal dependencies, and an implementation with the bulk of the 100 dependencies that would typically create dependency cycles. In order for the 101 implementation to be linked in, it must be added to the dependency tree of 102 linked artifacts (e.g. ``pw_executable``, ``pw_static_library``). Since 103 there's no way for the libraries themselves to just happily pull in the 104 implementation if someone depends on the interface, the implementation is 105 instead late-bound by adding it as a direct dependency of the final linked 106 artifact. This is all managed through ``pw_build_LINK_DEPS``, which is global 107 for each toolchain and applied to every ``pw_executable``, 108 ``pw_static_library``, and ``pw_shared_library``. 109 110#. **Apply a default visibility policy** 111 112 Projects can globally control the default visibility of pw_* target types by 113 specifying ``pw_build_DEFAULT_VISIBILITY``. This template applies that as the 114 default visibility for any pw_* targets that do not explicitly specify 115 a visibility. 116 117#. **Add source file names as metadata** 118 119 All source file names are collected as 120 `GN metadata <https://gn.googlesource.com/gn/+/main/docs/reference.md#metadata_collection>`_. 121 This list can be writen to a file at build time using ``generated_file``. The 122 primary use case for this is to generate a token database containing all the 123 source files. This allows PW_ASSERT to emit filename tokens even though it 124 can't add them to the elf file because of the reasons described at 125 :ref:`module-pw_assert-assert-api`. 126 127 .. note:: 128 ``pw_source_files``, if not rebased will default to outputing module 129 relative paths from a ``generated_file`` target. This is likely not 130 useful. Adding a ``rebase`` argument to ``generated_file`` such as 131 ``rebase = root_build_dir`` will result in usable paths. For an example, 132 see ``//pw_tokenizer/database.gni``'s ``pw_tokenizer_filename_database`` 133 template. 134 135The ``pw_executable`` template provides additional functionality around building 136complete binaries. As Pigweed is a collection of libraries, it does not know how 137its final targets are built. ``pw_executable`` solves this by letting each user 138of Pigweed specify a global executable template for their target, and have 139Pigweed build against it. This is controlled by the build variable 140``pw_executable_config.target_type``, specifying the name of the executable 141template for a project. 142 143In some uncommon cases, a project's ``pw_executable`` template definition may 144need to stamp out some ``pw_source_set``\s. Since a pw_executable template can't 145import ``$dir_pw_build/target_types.gni`` due to circular imports, it should 146import ``$dir_pw_build/cc_library.gni`` instead. 147 148.. tip:: 149 150 Prefer to use ``pw_executable`` over plain ``executable`` targets to allow 151 cleanly building the same code for multiple target configs. 152 153**Arguments** 154 155All of the ``pw_*`` target type overrides accept any arguments supported by 156the underlying native types, as they simply forward them through to the 157underlying target. 158 159Additionally, the following arguments are also supported: 160 161* **remove_configs**: (optional) A list of configs / config patterns to remove 162 from the set of default configs specified by the current toolchain 163 configuration. 164* **remove_public_deps**: (optional) A list of targets to remove from the set of 165 default public_deps specified by the current toolchain configuration. 166 167.. _module-pw_build-link-deps: 168 169Link-only deps 170-------------- 171It may be necessary to specify additional link-time dependencies that may not be 172explicitly depended on elsewhere in the build. One example of this is a 173``pw_assert`` backend, which may need to leave out dependencies to avoid 174circular dependencies. Its dependencies need to be linked for executables and 175libraries, even if they aren't pulled in elsewhere. 176 177The ``pw_build_LINK_DEPS`` build arg is a list of dependencies to add to all 178``pw_executable``, ``pw_static_library``, and ``pw_shared_library`` targets. 179This should only be used as a last resort when dependencies cannot be properly 180expressed in the build. 181 182Python packages 183--------------- 184GN templates for :ref:`Python build automation <docs-python-build>` are 185described in :ref:`module-pw_build-python`. 186 187.. toctree:: 188 :hidden: 189 190 python 191 192 193.. _module-pw_build-cc_blob_library: 194 195pw_cc_blob_library 196------------------ 197The ``pw_cc_blob_library`` template is useful for embedding binary data into a 198program. The template takes in a mapping of symbol names to file paths, and 199generates a set of C++ source and header files that embed the contents of the 200passed-in files as arrays of ``std::byte``. 201 202The blob byte arrays are constant initialized and are safe to access at any 203time, including before ``main()``. 204 205``pw_cc_blob_library`` is also available in the CMake build. It is provided by 206``pw_build/cc_blob_library.cmake``. 207 208**Arguments** 209 210* ``blobs``: A list of GN scopes, where each scope corresponds to a binary blob 211 to be transformed from file to byte array. This is a required field. Blob 212 fields include: 213 214 * ``symbol_name``: The C++ symbol for the byte array. 215 * ``file_path``: The file path for the binary blob. 216 * ``linker_section``: If present, places the byte array in the specified 217 linker section. 218 * ``alignas``: If present, uses the specified string or integer verbatim in 219 the ``alignas()`` specifier for the byte array. 220 221* ``out_header``: The header file to generate. Users will include this file 222 exactly as it is written here to reference the byte arrays. 223* ``namespace``: An optional (but highly recommended!) C++ namespace to place 224 the generated blobs within. 225 226Example 227^^^^^^^ 228 229**BUILD.gn** 230 231.. code-block:: 232 233 pw_cc_blob_library("foo_bar_blobs") { 234 blobs: [ 235 { 236 symbol_name: "kFooBlob" 237 file_path: "${target_out_dir}/stuff/bin/foo.bin" 238 }, 239 { 240 symbol_name: "kBarBlob" 241 file_path: "//stuff/bin/bar.bin" 242 linker_section: ".bar_section" 243 }, 244 ] 245 out_header: "my/stuff/foo_bar_blobs.h" 246 namespace: "my::stuff" 247 deps = [ ":generate_foo_bin" ] 248 } 249 250.. note:: If the binary blobs are generated as part of the build, be sure to 251 list them as deps to the pw_cc_blob_library target. 252 253**Generated Header** 254 255.. code-block:: 256 257 #pragma once 258 259 #include <array> 260 #include <cstddef> 261 262 namespace my::stuff { 263 264 extern const std::array<std::byte, 100> kFooBlob; 265 266 extern const std::array<std::byte, 50> kBarBlob; 267 268 } // namespace my::stuff 269 270**Generated Source** 271 272.. code-block:: 273 274 #include "my/stuff/foo_bar_blobs.h" 275 276 #include <array> 277 #include <cstddef> 278 279 #include "pw_preprocessor/compiler.h" 280 281 namespace my::stuff { 282 283 const std::array<std::byte, 100> kFooBlob = { ... }; 284 285 PW_PLACE_IN_SECTION(".bar_section") 286 const std::array<std::byte, 50> kBarBlob = { ... }; 287 288 } // namespace my::stuff 289 290.. _module-pw_build-facade: 291 292pw_facade 293--------- 294In their simplest form, a :ref:`facade<docs-module-structure-facades>` is a GN 295build arg used to change a dependency at compile time. Pigweed targets configure 296these facades as needed. 297 298The ``pw_facade`` template bundles a ``pw_source_set`` with a facade build arg. 299This allows the facade to provide header files, compilation options or anything 300else a GN ``source_set`` provides. 301 302The ``pw_facade`` template declares two targets: 303 304* ``$target_name``: the public-facing ``pw_source_set``, with a ``public_dep`` 305 on the backend 306* ``$target_name.facade``: target used by the backend to avoid circular 307 dependencies 308 309.. code-block:: 310 311 # Declares ":foo" and ":foo.facade" GN targets 312 pw_facade("foo") { 313 backend = pw_log_BACKEND 314 public_configs = [ ":public_include_path" ] 315 public = [ "public/pw_foo/foo.h" ] 316 } 317 318Low-level facades like ``pw_assert`` cannot express all of their dependencies 319due to the potential for dependency cycles. Facades with this issue may require 320backends to place their implementations in a separate build target to be listed 321in ``pw_build_LINK_DEPS`` (see :ref:`module-pw_build-link-deps`). The 322``require_link_deps`` variable in ``pw_facade`` asserts that all specified build 323targets are present in ``pw_build_LINK_DEPS`` if the facade's backend variable 324is set. 325 326.. _module-pw_build-python-action: 327 328pw_python_action 329---------------- 330The ``pw_python_action`` template is a convenience wrapper around GN's `action 331function <https://gn.googlesource.com/gn/+/main/docs/reference.md#func_action>`_ 332for running Python scripts. The main benefit it provides is resolution of GN 333target labels to compiled binary files. This allows Python scripts to be written 334independently of GN, taking only filesystem paths as arguments. 335 336Another convenience provided by the template is to allow running scripts without 337any outputs. Sometimes scripts run in a build do not directly produce output 338files, but GN requires that all actions have an output. ``pw_python_action`` 339solves this by accepting a boolean ``stamp`` argument which tells it to create a 340placeholder output file for the action. 341 342**Arguments** 343 344``pw_python_action`` accepts all of the arguments of a regular ``action`` 345target. Additionally, it has some of its own arguments: 346 347* ``module``: Run the specified Python module instead of a script. Either 348 ``script`` or ``module`` must be specified, but not both. 349* ``capture_output``: Optional boolean. If true, script output is hidden unless 350 the script fails with an error. Defaults to true. 351* ``stamp``: Optional variable indicating whether to automatically create a 352 placeholder output file for the script. This allows running scripts without 353 specifying ``outputs``. If ``stamp`` is true, a generic output file is 354 used. If ``stamp`` is a file path, that file is used as a stamp file. Like any 355 output file, ``stamp`` must be in the build directory. Defaults to false. 356* ``environment``: Optional list of strings. Environment variables to set, 357 passed as NAME=VALUE strings. 358* ``working_directory``: Optional file path. When provided the current working 359 directory will be set to this location before the Python module or script is 360 run. 361* ``command_launcher``: Optional string. Arguments to prepend to the Python 362 command, e.g. ``'/usr/bin/fakeroot --'`` will run the Python script within a 363 fakeroot environment. 364* ``venv``: Optional gn target of the pw_python_venv that should be used to run 365 this action. 366 367.. _module-pw_build-python-action-expressions: 368 369Expressions 370^^^^^^^^^^^ 371 372``pw_python_action`` evaluates expressions in ``args``, the arguments passed to 373the script. These expressions function similarly to generator expressions in 374CMake. Expressions may be passed as a standalone argument or as part of another 375argument. A single argument may contain multiple expressions. 376 377Generally, these expressions are used within templates rather than directly in 378BUILD.gn files. This allows build code to use GN labels without having to worry 379about converting them to files. 380 381.. note:: 382 383 We intend to replace these expressions with native GN features when possible. 384 See `b/234886742 <http://issuetracker.google.com/234886742>`_. 385 386The following expressions are supported: 387 388.. describe:: <TARGET_FILE(gn_target)> 389 390 Evaluates to the output file of the provided GN target. For example, the 391 expression 392 393 .. code-block:: 394 395 "<TARGET_FILE(//foo/bar:static_lib)>" 396 397 might expand to 398 399 .. code-block:: 400 401 "/home/User/project_root/out/obj/foo/bar/static_lib.a" 402 403 ``TARGET_FILE`` parses the ``.ninja`` file for the GN target, so it should 404 always find the correct output file, regardless of the toolchain's or target's 405 configuration. Some targets, such as ``source_set`` and ``group`` targets, do 406 not have an output file, and attempting to use ``TARGET_FILE`` with them 407 results in an error. 408 409 ``TARGET_FILE`` only resolves GN target labels to their outputs. To resolve 410 paths generally, use the standard GN approach of applying the 411 ``rebase_path(path, root_build_dir)`` function. This function 412 converts the provided GN path or list of paths to be relative to the build 413 directory, from which all build commands and scripts are executed. 414 415.. describe:: <TARGET_FILE_IF_EXISTS(gn_target)> 416 417 ``TARGET_FILE_IF_EXISTS`` evaluates to the output file of the provided GN 418 target, if the output file exists. If the output file does not exist, the 419 entire argument that includes this expression is omitted, even if there is 420 other text or another expression. 421 422 For example, consider this expression: 423 424 .. code-block:: 425 426 "--database=<TARGET_FILE_IF_EXISTS(//alpha/bravo)>" 427 428 If the ``//alpha/bravo`` target file exists, this might expand to the 429 following: 430 431 .. code-block:: 432 433 "--database=/home/User/project/out/obj/alpha/bravo/bravo.elf" 434 435 If the ``//alpha/bravo`` target file does not exist, the entire 436 ``--database=`` argument is omitted from the script arguments. 437 438.. describe:: <TARGET_OBJECTS(gn_target)> 439 440 Evaluates to the object files of the provided GN target. Expands to a separate 441 argument for each object file. If the target has no object files, the argument 442 is omitted entirely. Because it does not expand to a single expression, the 443 ``<TARGET_OBJECTS(...)>`` expression may not have leading or trailing text. 444 445 For example, the expression 446 447 .. code-block:: 448 449 "<TARGET_OBJECTS(//foo/bar:a_source_set)>" 450 451 might expand to multiple separate arguments: 452 453 .. code-block:: 454 455 "/home/User/project_root/out/obj/foo/bar/a_source_set.file_a.cc.o" 456 "/home/User/project_root/out/obj/foo/bar/a_source_set.file_b.cc.o" 457 "/home/User/project_root/out/obj/foo/bar/a_source_set.file_c.cc.o" 458 459**Example** 460 461.. code-block:: 462 463 import("$dir_pw_build/python_action.gni") 464 465 pw_python_action("postprocess_main_image") { 466 script = "py/postprocess_binary.py" 467 args = [ 468 "--database", 469 rebase_path("my/database.csv", root_build_dir), 470 "--binary=<TARGET_FILE(//firmware/images:main)>", 471 ] 472 stamp = true 473 } 474 475.. _module-pw_build-evaluate-path-expressions: 476 477pw_evaluate_path_expressions 478---------------------------- 479It is not always feasible to pass information to a script through command line 480arguments. If a script requires a large amount of input data, writing to a file 481is often more convenient. However, doing so bypasses ``pw_python_action``'s GN 482target label resolution, preventing such scripts from working with build 483artifacts in a build system-agnostic manner. 484 485``pw_evaluate_path_expressions`` is designed to address this use case. It takes 486a list of input files and resolves target expressions within them, modifying the 487files in-place. 488 489Refer to ``pw_python_action``'s :ref:`module-pw_build-python-action-expressions` 490section for the list of supported expressions. 491 492.. note:: 493 494 ``pw_evaluate_path_expressions`` is typically used as an intermediate 495 sub-target of a larger template, rather than a standalone build target. 496 497**Arguments** 498 499* ``files``: A list of scopes, each containing a ``source`` file to process and 500 a ``dest`` file to which to write the result. 501 502**Example** 503 504The following template defines an executable target which additionally outputs 505the list of object files from which it was compiled, making use of 506``pw_evaluate_path_expressions`` to resolve their paths. 507 508.. code-block:: 509 510 import("$dir_pw_build/evaluate_path_expressions.gni") 511 512 template("executable_with_artifacts") { 513 executable("${target_name}.exe") { 514 sources = invoker.sources 515 if defined(invoker.deps) { 516 deps = invoker.deps 517 } 518 } 519 520 _artifacts_input = "$target_gen_dir/${target_name}_artifacts.json.in" 521 _artifacts_output = "$target_gen_dir/${target_name}_artifacts.json" 522 _artifacts = { 523 binary = "<TARGET_FILE(:${target_name}.exe)>" 524 objects = "<TARGET_OBJECTS(:${target_name}.exe)>" 525 } 526 write_file(_artifacts_input, _artifacts, "json") 527 528 pw_evaluate_path_expressions("${target_name}.evaluate") { 529 files = [ 530 { 531 source = _artifacts_input 532 dest = _artifacts_output 533 }, 534 ] 535 } 536 537 group(target_name) { 538 deps = [ 539 ":${target_name}.exe", 540 ":${target_name}.evaluate", 541 ] 542 } 543 } 544 545.. _module-pw_build-pw_exec: 546 547pw_exec 548------- 549``pw_exec`` allows for execution of arbitrary programs. It is a wrapper around 550``pw_python_action`` but allows for specifying the program to execute. 551 552.. note:: Prefer to use ``pw_python_action`` instead of calling out to shell 553 scripts, as the python will be more portable. ``pw_exec`` should generally 554 only be used for interacting with legacy/existing scripts. 555 556**Arguments** 557 558* ``program``: The program to run. Can be a full path or just a name (in which 559 case $PATH is searched). 560* ``args``: Optional list of arguments to the program. 561* ``deps``: Dependencies for this target. 562* ``public_deps``: Public dependencies for this target. In addition to outputs 563 from this target, outputs generated by public dependencies can be used as 564 inputs from targets that depend on this one. This is not the case for private 565 deps. 566* ``inputs``: Optional list of build inputs to the program. 567* ``outputs``: Optional list of artifacts produced by the program's execution. 568* ``env``: Optional list of key-value pairs defining environment variables for 569 the program. 570* ``env_file``: Optional path to a file containing a list of newline-separated 571 key-value pairs defining environment variables for the program. 572* ``args_file``: Optional path to a file containing additional positional 573 arguments to the program. Each line of the file is appended to the 574 invocation. Useful for specifying arguments from GN metadata. 575* ``skip_empty_args``: If args_file is provided, boolean indicating whether to 576 skip running the program if the file is empty. Used to avoid running 577 commands which error when called without arguments. 578* ``capture_output``: If true, output from the program is hidden unless the 579 program exits with an error. Defaults to true. 580* ``working_directory``: The working directory to execute the subprocess with. 581 If not specified it will not be set and the subprocess will have whatever 582 the parent current working directory is. 583* ``visibility``: GN visibility to apply to the underlying target. 584 585**Example** 586 587.. code-block:: 588 589 import("$dir_pw_build/exec.gni") 590 591 pw_exec("hello_world") { 592 program = "/bin/sh" 593 args = [ 594 "-c", 595 "echo hello \$WORLD", 596 ] 597 env = [ 598 "WORLD=world", 599 ] 600 } 601 602pw_input_group 603-------------- 604``pw_input_group`` defines a group of input files which are not directly 605processed by the build but are still important dependencies of later build 606steps. This is commonly used alongside metadata to propagate file dependencies 607through the build graph and force rebuilds on file modifications. 608 609For example ``pw_docgen`` defines a ``pw_doc_group`` template which outputs 610metadata from a list of input files. The metadata file is not actually part of 611the build, and so changes to any of the input files do not trigger a rebuild. 612This is problematic, as targets that depend on the metadata should rebuild when 613the inputs are modified but GN cannot express this dependency. 614 615``pw_input_group`` solves this problem by allowing a list of files to be listed 616in a target that does not output any build artifacts, causing all dependent 617targets to correctly rebuild. 618 619**Arguments** 620 621``pw_input_group`` accepts all arguments that can be passed to a ``group`` 622target, as well as requiring one extra: 623 624* ``inputs``: List of input files. 625 626**Example** 627 628.. code-block:: 629 630 import("$dir_pw_build/input_group.gni") 631 632 pw_input_group("foo_metadata") { 633 metadata = { 634 files = [ 635 "x.foo", 636 "y.foo", 637 "z.foo", 638 ] 639 } 640 inputs = metadata.files 641 } 642 643Targets depending on ``foo_metadata`` will rebuild when any of the ``.foo`` 644files are modified. 645 646pw_zip 647------ 648``pw_zip`` is a target that allows users to zip up a set of input files and 649directories into a single output ``.zip`` file—a simple automation of a 650potentially repetitive task. 651 652**Arguments** 653 654* ``inputs``: List of source files as well as the desired relative zip 655 destination. See below for the input syntax. 656* ``dirs``: List of entire directories to be zipped as well as the desired 657 relative zip destination. See below for the input syntax. 658* ``output``: Filename of output ``.zip`` file. 659* ``deps``: List of dependencies for the target. 660 661**Input Syntax** 662 663Inputs all need to follow the correct syntax: 664 665#. Path to source file or directory. Directories must end with a ``/``. 666#. The delimiter (defaults to ``>``). 667#. The desired destination of the contents within the ``.zip``. Must start 668 with ``/`` to indicate the zip root. Any number of subdirectories are 669 allowed. If the source is a file it can be put into any subdirectory of the 670 root. If the source is a file, the zip copy can also be renamed by ending 671 the zip destination with a filename (no trailing ``/``). 672 673Thus, it should look like the following: ``"[source file or dir] > /"``. 674 675**Example** 676 677Let's say we have the following structure for a ``//source/`` directory: 678 679.. code-block:: 680 681 source/ 682 ├── file1.txt 683 ├── file2.txt 684 ├── file3.txt 685 └── some_dir/ 686 ├── file4.txt 687 └── some_other_dir/ 688 └── file5.txt 689 690And we create the following build target: 691 692.. code-block:: 693 694 import("$dir_pw_build/zip.gni") 695 696 pw_zip("target_name") { 697 inputs = [ 698 "//source/file1.txt > /", # Copied to the zip root dir. 699 "//source/file2.txt > /renamed.txt", # File renamed. 700 "//source/file3.txt > /bar/", # File moved to the /bar/ dir. 701 ] 702 703 dirs = [ 704 "//source/some_dir/ > /bar/some_dir/", # All /some_dir/ contents copied 705 # as /bar/some_dir/. 706 ] 707 708 # Note on output: if the specific output directory isn't defined 709 # (such as output = "zoo.zip") then the .zip will output to the 710 # same directory as the BUILD.gn file that called the target. 711 output = "//$target_out_dir/foo.zip" # Where the foo.zip will end up 712 } 713 714This will result in a ``.zip`` file called ``foo.zip`` stored in 715``//$target_out_dir`` with the following structure: 716 717.. code-block:: 718 719 foo.zip 720 ├── bar/ 721 │ ├── file3.txt 722 │ └── some_dir/ 723 │ ├── file4.txt 724 │ └── some_other_dir/ 725 │ └── file5.txt 726 ├── file1.txt 727 └── renamed.txt 728 729.. _module-pw_build-relative-source-file-names: 730 731pw_relative_source_file_names 732----------------------------- 733This template recursively walks the listed dependencies and collects the names 734of all the headers and source files required by the targets, and then transforms 735them such that they reflect the ``__FILE__`` when pw_build's ``relative_paths`` 736config is applied. This is primarily intended for side-band generation of 737pw_tokenizer tokens so file name tokens can be utilized in places where 738pw_tokenizer is unable to embed token information as part of C/C++ compilation. 739 740This template produces a JSON file containing an array of strings (file paths 741with ``-ffile-prefix-map``-like transformations applied) that can be used to 742:ref:`generate a token database <module-pw_tokenizer-database-creation>`. 743 744**Arguments** 745 746* ``deps``: A required list of targets to recursively extract file names from. 747* ``outputs``: A required array with a single element: the path to write the 748 final JSON file to. 749 750**Example** 751 752Let's say we have the following project structure: 753 754.. code-block:: 755 756 project root 757 ├── foo/ 758 │ ├── foo.h 759 │ └── foo.cc 760 ├── bar/ 761 │ ├── bar.h 762 │ └── bar.cc 763 ├── unused/ 764 │ ├── unused.h 765 │ └── unused.cc 766 └── main.cc 767 768And a BUILD.gn at the root: 769 770.. code-block:: 771 772 pw_source_set("bar") { 773 public_configs = [ ":bar_headers" ] 774 public = [ "bar/bar.h" ] 775 sources = [ "bar/bar.cc" ] 776 } 777 778 pw_source_set("foo") { 779 public_configs = [ ":foo_headers" ] 780 public = [ "foo/foo.h" ] 781 sources = [ "foo/foo.cc" ] 782 deps = [ ":bar" ] 783 } 784 785 786 pw_source_set("unused") { 787 public_configs = [ ":unused_headers" ] 788 public = [ "unused/unused.h" ] 789 sources = [ "unused/unused.cc" ] 790 deps = [ ":bar" ] 791 } 792 793 pw_executable("main") { 794 sources = [ "main.cc" ] 795 deps = [ ":foo" ] 796 } 797 798 pw_relative_source_file_names("main_source_files") { 799 deps = [ ":main" ] 800 outputs = [ "$target_gen_dir/main_source_files.json" ] 801 } 802 803The json file written to `out/gen/main_source_files.json` will contain: 804 805.. code-block:: 806 807 [ 808 "bar/bar.cc", 809 "bar/bar.h", 810 "foo/foo.cc", 811 "foo/foo.h", 812 "main.cc" 813 ] 814 815Since ``unused`` isn't a transitive dependency of ``main``, its source files 816are not included. Similarly, even though ``bar`` is not a direct dependency of 817``main``, its source files *are* included because ``foo`` brings in ``bar`` as 818a transitive dependency. 819 820Note how the file paths in this example are relative to the project root rather 821than being absolute paths (e.g. ``/home/user/ralph/coding/my_proj/main.cc``). 822This is a result of transformations applied to strip absolute pathing prefixes, 823matching the behavior of pw_build's ``$dir_pw_build:relative_paths`` config. 824 825Build time errors: pw_error and pw_build_assert 826----------------------------------------------- 827In Pigweed's complex, multi-toolchain GN build it is not possible to build every 828target in every configuration. GN's ``assert`` statement is not ideal for 829enforcing the correct configuration because it may prevent the GN build files or 830targets from being referred to at all, even if they aren't used. 831 832The ``pw_error`` GN template results in an error if it is executed during the 833build. These error targets can exist in the build graph, but cannot be depended 834on without an error. 835 836``pw_build_assert`` evaluates to a ``pw_error`` if a condition fails or nothing 837(an empty group) if the condition passes. Targets can add a dependency on a 838``pw_build_assert`` to enforce a condition at build time. 839 840The templates for build time errors are defined in ``pw_build/error.gni``. 841 842Improved Ninja interface 843------------------------ 844Ninja includes a basic progress display, showing in a single line the number of 845targets finished, the total number of targets, and the name of the most recent 846target it has either started or finished. 847 848For additional insight into the status of the build, Pigweed includes a Ninja 849wrapper, ``pw-wrap-ninja``, that displays additional real-time information about 850the progress of the build. The wrapper is invoked the same way you'd normally 851invoke Ninja: 852 853.. code-block:: sh 854 855 pw-wrap-ninja -C out 856 857The script lists the progress of the build, as well as the list of targets that 858Ninja is currently building, along with a timer that measures how long each 859target has been building for: 860 861.. code-block:: 862 863 [51.3s] Building [8924/10690] ... 864 [10.4s] c++ pw_strict_host_clang_debug/obj/pw_string/string_test.lib.string_test.cc.o 865 [ 9.5s] ACTION //pw_console/py:py.lint.mypy(//pw_build/python_toolchain:python) 866 [ 9.4s] ACTION //pw_console/py:py.lint.pylint(//pw_build/python_toolchain:python) 867 [ 6.1s] clang-tidy ../pw_log_rpc/log_service.cc 868 [ 6.1s] clang-tidy ../pw_log_rpc/log_service_test.cc 869 [ 6.1s] clang-tidy ../pw_log_rpc/rpc_log_drain.cc 870 [ 6.1s] clang-tidy ../pw_log_rpc/rpc_log_drain_test.cc 871 [ 5.4s] c++ pw_strict_host_clang_debug/obj/BUILD_DIR/pw_strict_host_clang_debug/gen/pw... 872 ... and 109 more 873 874This allows you to, at a glance, know what Ninja's currently building, which 875targets are bottlenecking the rest of the build, and which targets are taking 876an unusually long time to complete. 877 878``pw-wrap-ninja`` includes other useful functionality as well. The 879``--write-trace`` option writes a build trace to the specified path, which can 880be viewed in the `Perfetto UI <https://ui.perfetto.dev/>`_, or via Chrome's 881built-in ``chrome://tracing`` tool. 882 883CMake 884===== 885Pigweed's `CMake`_ support is provided primarily for projects that have an 886existing CMake build and wish to integrate Pigweed without switching to a new 887build system. 888 889The following command generates Ninja build files for a host build in the 890``out/cmake_host`` directory: 891 892.. code-block:: sh 893 894 cmake -B out/cmake_host -S "$PW_ROOT" -G Ninja -DCMAKE_TOOLCHAIN_FILE=$PW_ROOT/pw_toolchain/host_clang/toolchain.cmake 895 896The ``PW_ROOT`` environment variable must point to the root of the Pigweed 897directory. This variable is set by Pigweed's environment setup. 898 899Tests can be executed with the ``pw_run_tests.GROUP`` targets. To run Pigweed 900module tests, execute ``pw_run_tests.modules``: 901 902.. code-block:: sh 903 904 ninja -C out/cmake_host pw_run_tests.modules 905 906:ref:`module-pw_watch` supports CMake, so you can also run 907 908.. code-block:: sh 909 910 pw watch -C out/cmake_host pw_run_tests.modules 911 912CMake functions 913--------------- 914CMake convenience functions are defined in ``pw_build/pigweed.cmake``. 915 916* ``pw_add_library_generic`` -- The base helper used to instantiate CMake 917 libraries. This is meant for use in downstream projects as upstream Pigweed 918 modules are expected to use ``pw_add_library``. 919* ``pw_add_library`` -- Add an upstream Pigweed library. 920* ``pw_add_facade_generic`` -- The base helper used to instantiate facade 921 libraries. This is meant for use in downstream projects as upstream Pigweed 922 modules are expected to use ``pw_add_facade``. 923* ``pw_add_facade`` -- Declare an upstream Pigweed facade. 924* ``pw_set_backend`` -- Set the backend library to use for a facade. 925* ``pw_add_test_generic`` -- The base helper used to instantiate test targets. 926 This is meant for use in downstrema projects as upstream Pigweed modules are 927 expected to use ``pw_add_test``. 928* ``pw_add_test`` -- Declare an upstream Pigweed test target. 929* ``pw_add_test_group`` -- Declare a target to group and bundle test targets. 930* ``pw_target_link_targets`` -- Helper wrapper around ``target_link_libraries`` 931 which only supports CMake targets and detects when the target does not exist. 932 Note that generator expressions are not supported. 933* ``pw_add_global_compile_options`` -- Applies compilation options to all 934 targets in the build. This should only be used to add essential compilation 935 options, such as those that affect the ABI. Use ``pw_add_library`` or 936 ``target_compile_options`` to apply other compile options. 937* ``pw_add_error_target`` -- Declares target which reports a message and causes 938 a build failure only when compiled. This is useful when ``FATAL_ERROR`` 939 messages cannot be used to catch problems during the CMake configuration 940 phase. 941* ``pw_parse_arguments`` -- Helper to parse CMake function arguments. 942 943See ``pw_build/pigweed.cmake`` for the complete documentation of these 944functions. 945 946Special libraries that do not fit well with these functions are created with the 947standard CMake functions, such as ``add_library`` and ``target_link_libraries``. 948 949Facades and backends 950-------------------- 951The CMake build uses CMake cache variables for configuring 952:ref:`facades<docs-module-structure-facades>` and backends. Cache variables are 953similar to GN's build args set with ``gn args``. Unlike GN, CMake does not 954support multi-toolchain builds, so these variables have a single global value 955per build directory. 956 957The ``pw_add_module_facade`` function declares a cache variable named 958``<module_name>_BACKEND`` for each facade. Cache variables can be awkward to 959work with, since their values only change when they're assigned, but then 960persist accross CMake invocations. These variables should be set in one of the 961following ways: 962 963* Prior to setting a backend, your application should include 964 ``$ENV{PW_ROOT}/backends.cmake``. This file will setup all the backend targets 965 such that any misspelling of a facade or backend will yield a warning. 966 967 .. note:: 968 Zephyr developers do not need to do this, backends can be set automatically 969 by enabling the appropriate Kconfig options. 970 971* Call ``pw_set_backend`` to set backends appropriate for the target in the 972 target's toolchain file. The toolchain file is provided to ``cmake`` with 973 ``-DCMAKE_TOOLCHAIN_FILE=<toolchain file>``. 974* Call ``pw_set_backend`` in the top-level ``CMakeLists.txt`` before other 975 CMake code executes. 976* Set the backend variable at the command line with the ``-D`` option. 977 978 .. code-block:: sh 979 980 cmake -B out/cmake_host -S "$PW_ROOT" -G Ninja \ 981 -DCMAKE_TOOLCHAIN_FILE=$PW_ROOT/pw_toolchain/host_clang/toolchain.cmake \ 982 -Dpw_log_BACKEND=pw_log_basic 983 984* Temporarily override a backend by setting it interactively with ``ccmake`` or 985 ``cmake-gui``. 986 987If the backend is set to a build target that does not exist, there will be an 988error message like the following: 989 990.. code-block:: 991 992 CMake Error at pw_build/pigweed.cmake:257 (message): 993 my_module.my_facade's INTERFACE dep "my_nonexistent_backend" is not 994 a target. 995 Call Stack (most recent call first): 996 pw_build/pigweed.cmake:238:EVAL:1 (_pw_target_link_targets_deferred_check) 997 CMakeLists.txt:DEFERRED 998 999 1000Toolchain setup 1001--------------- 1002In CMake, the toolchain is configured by setting CMake variables, as described 1003in the `CMake documentation <https://cmake.org/cmake/help/latest/manual/cmake-toolchains.7.html>`_. 1004These variables are typically set in a toolchain CMake file passed to ``cmake`` 1005with the ``-D`` option (``-DCMAKE_TOOLCHAIN_FILE=path/to/file.cmake``). 1006For Pigweed embedded builds, set ``CMAKE_SYSTEM_NAME`` to the empty string 1007(``""``). 1008 1009Toolchains may set the ``pw_build_WARNINGS`` variable to a list of ``INTERFACE`` 1010libraries with compilation options for Pigweed's upstream libraries. This 1011defaults to a strict set of warnings. Projects may need to use less strict 1012compilation warnings to compile backends exposed to Pigweed code (such as 1013``pw_log``) that cannot compile with Pigweed's flags. If desired, Projects can 1014access these warnings by depending on ``pw_build.warnings``. 1015 1016Third party libraries 1017--------------------- 1018The CMake build includes third-party libraries similarly to the GN build. A 1019``dir_pw_third_party_<library>`` cache variable is defined for each third-party 1020dependency. The variable must be set to the absolute path of the library in 1021order to use it. If the variable is empty 1022(``if("${dir_pw_third_party_<library>}" STREQUAL "")``), the dependency is not 1023available. 1024 1025Third-party dependencies are not automatically added to the build. They can be 1026manually added with ``add_subdirectory`` or by setting the 1027``pw_third_party_<library>_ADD_SUBDIRECTORY`` option to ``ON``. 1028 1029Third party variables are set like any other cache global variable in CMake. It 1030is recommended to set these in one of the following ways: 1031 1032* Set with the CMake ``set`` function in the toolchain file or a 1033 ``CMakeLists.txt`` before other CMake code executes. 1034 1035 .. code-block:: cmake 1036 1037 set(dir_pw_third_party_nanopb ${CMAKE_CURRENT_SOURCE_DIR}/external/nanopb CACHE PATH "" FORCE) 1038 1039* Set the variable at the command line with the ``-D`` option. 1040 1041 .. code-block:: sh 1042 1043 cmake -B out/cmake_host -S "$PW_ROOT" -G Ninja \ 1044 -DCMAKE_TOOLCHAIN_FILE=$PW_ROOT/pw_toolchain/host_clang/toolchain.cmake \ 1045 -Ddir_pw_third_party_nanopb=/path/to/nanopb 1046 1047* Set the variable interactively with ``ccmake`` or ``cmake-gui``. 1048 1049Use Pigweed from an existing CMake project 1050------------------------------------------ 1051To use Pigweed libraries form a CMake-based project, simply include the Pigweed 1052repository from a ``CMakeLists.txt``. 1053 1054.. code-block:: cmake 1055 1056 add_subdirectory(path/to/pigweed pigweed) 1057 1058All module libraries will be available as ``module_name`` or 1059``module_name.sublibrary``. 1060 1061If desired, modules can be included individually. 1062 1063.. code-block:: cmake 1064 1065 add_subdirectory(path/to/pigweed/pw_some_module pw_some_module) 1066 add_subdirectory(path/to/pigweed/pw_another_module pw_another_module) 1067 1068Bazel 1069===== 1070Bazel is currently very experimental, and only builds for host and ARM Cortex-M 1071microcontrollers. 1072 1073The common configuration for Bazel for all modules is in the ``pigweed.bzl`` 1074file. The built-in Bazel rules ``cc_binary``, ``cc_library``, and ``cc_test`` 1075are wrapped with ``pw_cc_binary``, ``pw_cc_library``, and ``pw_cc_test``. 1076These wrappers add parameters to calls to the compiler and linker. 1077 1078In addition to wrapping the built-in rules, Pigweed also provides a custom 1079rule for handling linker scripts with Bazel. e.g. 1080 1081.. code-block:: python 1082 1083 pw_linker_script( 1084 name = "some_linker_script", 1085 linker_script = ":some_configurable_linker_script.ld", 1086 defines = [ 1087 "PW_BOOT_FLASH_BEGIN=0x08000200", 1088 "PW_BOOT_FLASH_SIZE=1024K", 1089 "PW_BOOT_HEAP_SIZE=112K", 1090 "PW_BOOT_MIN_STACK_SIZE=1K", 1091 "PW_BOOT_RAM_BEGIN=0x20000000", 1092 "PW_BOOT_RAM_SIZE=192K", 1093 "PW_BOOT_VECTOR_TABLE_BEGIN=0x08000000", 1094 "PW_BOOT_VECTOR_TABLE_SIZE=512", 1095 ], 1096 ) 1097 1098 pw_cc_binary( 1099 name = "some_binary", 1100 srcs = ["some_source.c"], 1101 additional_linker_inputs = [":some_linker_script"], 1102 linkopts = ["-T $(location :some_linker_script)"], 1103 ) 1104 1105Currently Pigweed is making use of a set of 1106`open source <https://github.com/silvergasp/bazel-embedded>`_ toolchains. The 1107host builds are only supported on Linux/Mac based systems. Additionally the 1108host builds are not entirely hermetic, and will make use of system 1109libraries and headers. This is close to the default configuration for Bazel, 1110though slightly more hermetic. The host toolchain is based around clang-11 which 1111has a system dependency on 'libtinfo.so.5' which is often included as part of 1112the libncurses packages. On Debian based systems this can be installed using the 1113command below: 1114 1115.. code-block:: sh 1116 1117 sudo apt install libncurses5 1118 1119The host toolchain does not currently support native Windows, though using WSL 1120is a viable alternative. 1121 1122The ARM Cortex-M Bazel toolchains are based around gcc-arm-non-eabi and are 1123entirely hermetic. You can target Cortex-M, by using the platforms command line 1124option. This set of toolchains is supported from hosts; Windows, Mac and Linux. 1125The platforms that are currently supported are listed below: 1126 1127.. code-block:: sh 1128 1129 bazel build //:your_target --platforms=@pigweed//pw_build/platforms:cortex_m0 1130 bazel build //:your_target --platforms=@pigweed//pw_build/platforms:cortex_m1 1131 bazel build //:your_target --platforms=@pigweed//pw_build/platforms:cortex_m3 1132 bazel build //:your_target --platforms=@pigweed//pw_build/platforms:cortex_m4 1133 bazel build //:your_target --platforms=@pigweed//pw_build/platforms:cortex_m7 1134 bazel build //:your_target \ 1135 --platforms=@pigweed//pw_build/platforms:cortex_m4_fpu 1136 bazel build //:your_target \ 1137 --platforms=@pigweed//pw_build/platforms:cortex_m7_fpu 1138 1139 1140The above examples are cpu/fpu oriented platforms and can be used where 1141applicable for your application. There some more specific platforms for the 1142types of boards that are included as examples in Pigweed. It is strongly 1143encouraged that you create your own set of platforms specific for your project, 1144that implement the constraint_settings in this repository. e.g. 1145 1146New board constraint_value: 1147 1148.. code-block:: python 1149 1150 #your_repo/build_settings/constraints/board/BUILD 1151 constraint_value( 1152 name = "nucleo_l432kc", 1153 constraint_setting = "@pigweed//pw_build/constraints/board", 1154 ) 1155 1156New chipset constraint_value: 1157 1158.. code-block:: python 1159 1160 # your_repo/build_settings/constraints/chipset/BUILD 1161 constraint_value( 1162 name = "stm32l432kc", 1163 constraint_setting = "@pigweed//pw_build/constraints/chipset", 1164 ) 1165 1166New platforms for chipset and board: 1167 1168.. code-block:: python 1169 1170 #your_repo/build_settings/platforms/BUILD 1171 # Works with all stm32l432kc 1172 platforms( 1173 name = "stm32l432kc", 1174 parents = ["@pigweed//pw_build/platforms:cortex_m4"], 1175 constraint_values = 1176 ["@your_repo//build_settings/constraints/chipset:stm32l432kc"], 1177 ) 1178 1179 # Works with only the nucleo_l432kc 1180 platforms( 1181 name = "nucleo_l432kc", 1182 parents = [":stm32l432kc"], 1183 constraint_values = 1184 ["@your_repo//build_settings/constraints/board:nucleo_l432kc"], 1185 ) 1186 1187In the above example you can build your code with the command line: 1188 1189.. code-block:: python 1190 1191 bazel build //:your_target_for_nucleo_l432kc \ 1192 --platforms=@your_repo//build_settings:nucleo_l432kc 1193 1194 1195You can also specify that a specific target is only compatible with one 1196platform: 1197 1198.. code-block:: python 1199 1200 cc_library( 1201 name = "compatible_with_all_stm32l432kc", 1202 srcs = ["tomato_src.c"], 1203 target_compatible_with = 1204 ["@your_repo//build_settings/constraints/chipset:stm32l432kc"], 1205 ) 1206 1207 cc_library( 1208 name = "compatible_with_only_nucleo_l432kc", 1209 srcs = ["bbq_src.c"], 1210 target_compatible_with = 1211 ["@your_repo//build_settings/constraints/board:nucleo_l432kc"], 1212 ) 1213 1214