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 40Target types 41------------ 42.. code-block:: 43 44 import("$dir_pw_build/target_types.gni") 45 46 pw_source_set("my_library") { 47 sources = [ "lib.cc" ] 48 } 49 50Pigweed defines wrappers around the four basic GN binary types ``source_set``, 51``executable``, ``static_library``, and ``shared_library``. These wrappers apply 52default arguments to each target, as defined in ``pw_build/default.gni``. 53Arguments may be added or removed globally using the ``default_configs``, 54``default_public_deps``, and ``remove_default_configs`` build args. 55Additionally, arguments may be removed on a per-target basis with the 56``remove_configs`` and ``remove_public_deps`` variables. 57 58The ``pw_executable`` template provides additional functionality around building 59complete binaries. As Pigweed is a collection of libraries, it does not know how 60its final targets are built. ``pw_executable`` solves this by letting each user 61of Pigweed specify a global executable template for their target, and have 62Pigweed build against it. This is controlled by the build variable 63``pw_executable_config.target_type``, specifying the name of the executable 64template for a project. 65 66In some uncommon cases, a project's ``pw_executable`` template definition may 67need to stamp out some ``pw_source_set``s. Since a pw_executable template can't 68import ``$dir_pw_build/target_types.gni`` due to circular imports, it should 69import ``$dir_pw_build/cc_library.gni`` instead. 70 71Additionally ``pw_executable``, ``pw_source_set``, ``pw_static_library``, and 72``pw_shared_library`` track source files via the ``pw_source_files`` field the 73target's 74`GN metadata <https://gn.googlesource.com/gn/+/main/docs/reference.md#metadata_collection>`_. 75This list can be writen to a file at build time using ``generated_file``. The 76primary use case for this is to generate a token database containing all the 77source files. This allows PW_ASSERT to emit filename tokens even though it 78can't add them to the elf file because of the resons described at 79:ref:`module-pw_assert-assert-api`. 80 81.. note:: 82 ``pw_source_files``, if not rebased will default to outputing module relative 83 paths from a ``generated_file`` target. This is likely not useful. Adding 84 a ``rebase`` argument to ``generated_file`` such as 85 ``rebase = root_build_dir`` will result in usable paths. For an example, 86 see `//pw_tokenizer/database.gni`'s `pw_tokenizer_filename_database` template. 87 88.. tip:: 89 90 Prefer to use ``pw_executable`` over plain ``executable`` targets to allow 91 cleanly building the same code for multiple target configs. 92 93**Arguments** 94 95All of the ``pw_*`` target type overrides accept any arguments, as they simply 96forward them through to the underlying target. 97 98.. _module-pw_build-link-deps: 99 100Link-only deps 101-------------- 102It may be necessary to specify additional link-time dependencies that may not be 103explicitly depended on elsewhere in the build. One example of this is a 104``pw_assert`` backend, which may need to leave out dependencies to avoid 105circular dependencies. Its dependencies need to be linked for executables and 106libraries, even if they aren't pulled in elsewhere. 107 108The ``pw_build_LINK_DEPS`` build arg is a list of dependencies to add to all 109``pw_executable``, ``pw_static_library``, and ``pw_shared_library`` targets. 110This should only be used as a last resort when dependencies cannot be properly 111expressed in the build. 112 113Python packages 114--------------- 115GN templates for :ref:`Python build automation <docs-python-build>` are 116described in :ref:`module-pw_build-python`. 117 118.. toctree:: 119 :hidden: 120 121 python 122 123 124.. _module-pw_build-cc_blob_library: 125 126pw_cc_blob_library 127------------------ 128The ``pw_cc_blob_library`` template is useful for embedding binary data into a 129program. The template takes in a mapping of symbol names to file paths, and 130generates a set of C++ source and header files that embed the contents of the 131passed-in files as arrays. 132 133**Arguments** 134 135* ``blobs``: A list of GN scopes, where each scope corresponds to a binary blob 136 to be transformed from file to byte array. This is a required field. Blob 137 fields include: 138 139 * ``symbol_name``: The C++ symbol for the byte array. 140 * ``file_path``: The file path for the binary blob. 141 * ``linker_section``: If present, places the byte array in the specified 142 linker section. 143 144* ``out_header``: The header file to generate. Users will include this file 145 exactly as it is written here to reference the byte arrays. 146* ``namespace``: An optional (but highly recommended!) C++ namespace to place 147 the generated blobs within. 148 149Example 150^^^^^^^ 151 152**BUILD.gn** 153 154.. code-block:: 155 156 pw_cc_blob_library("foo_bar_blobs") { 157 blobs: [ 158 { 159 symbol_name: "kFooBlob" 160 file_path: "${target_out_dir}/stuff/bin/foo.bin" 161 }, 162 { 163 symbol_name: "kBarBlob" 164 file_path: "//stuff/bin/bar.bin" 165 linker_section: ".bar_section" 166 }, 167 ] 168 out_header: "my/stuff/foo_bar_blobs.h" 169 namespace: "my::stuff" 170 deps = [ ":generate_foo_bin" ] 171 } 172 173.. note:: If the binary blobs are generated as part of the build, be sure to 174 list them as deps to the pw_cc_blob_library target. 175 176**Generated Header** 177 178.. code-block:: 179 180 #pragma once 181 182 #include <array> 183 #include <cstddef> 184 185 namespace my::stuff { 186 187 extern const std::array<std::byte, 100> kFooBlob; 188 189 extern const std::array<std::byte, 50> kBarBlob; 190 191 } // namespace my::stuff 192 193**Generated Source** 194 195.. code-block:: 196 197 #include "my/stuff/foo_bar_blobs.h" 198 199 #include <array> 200 #include <cstddef> 201 202 #include "pw_preprocessor/compiler.h" 203 204 namespace my::stuff { 205 206 const std::array<std::byte, 100> kFooBlob = { ... }; 207 208 PW_PLACE_IN_SECTION(".bar_section") 209 const std::array<std::byte, 50> kBarBlob = { ... }; 210 211 } // namespace my::stuff 212 213.. _module-pw_build-facade: 214 215pw_facade 216--------- 217In their simplest form, a :ref:`facade<docs-module-structure-facades>` is a GN 218build arg used to change a dependency at compile time. Pigweed targets configure 219these facades as needed. 220 221The ``pw_facade`` template bundles a ``pw_source_set`` with a facade build arg. 222This allows the facade to provide header files, compilation options or anything 223else a GN ``source_set`` provides. 224 225The ``pw_facade`` template declares two targets: 226 227* ``$target_name``: the public-facing ``pw_source_set``, with a ``public_dep`` 228 on the backend 229* ``$target_name.facade``: target used by the backend to avoid circular 230 dependencies 231 232.. code-block:: 233 234 # Declares ":foo" and ":foo.facade" GN targets 235 pw_facade("foo") { 236 backend = pw_log_BACKEND 237 public_configs = [ ":public_include_path" ] 238 public = [ "public/pw_foo/foo.h" ] 239 } 240 241Low-level facades like ``pw_assert`` cannot express all of their dependencies 242due to the potential for dependency cycles. Facades with this issue may require 243backends to place their implementations in a separate build target to be listed 244in ``pw_build_LINK_DEPS`` (see :ref:`module-pw_build-link-deps`). The 245``require_link_deps`` variable in ``pw_facade`` asserts that all specified build 246targets are present in ``pw_build_LINK_DEPS`` if the facade's backend variable 247is set. 248 249.. _module-pw_build-python-action: 250 251pw_python_action 252---------------- 253The ``pw_python_action`` template is a convenience wrapper around ``action`` for 254running Python scripts. The main benefit it provides is resolution of GN target 255labels to compiled binary files. This allows Python scripts to be written 256independently of GN, taking only filesystem paths as arguments. 257 258Another convenience provided by the template is to allow running scripts without 259any outputs. Sometimes scripts run in a build do not directly produce output 260files, but GN requires that all actions have an output. ``pw_python_action`` 261solves this by accepting a boolean ``stamp`` argument which tells it to create a 262placeholder output file for the action. 263 264**Arguments** 265 266``pw_python_action`` accepts all of the arguments of a regular ``action`` 267target. Additionally, it has some of its own arguments: 268 269* ``module``: Run the specified Python module instead of a script. Either 270 ``script`` or ``module`` must be specified, but not both. 271* ``capture_output``: Optional boolean. If true, script output is hidden unless 272 the script fails with an error. Defaults to true. 273* ``stamp``: Optional variable indicating whether to automatically create a 274 placeholder output file for the script. This allows running scripts without 275 specifying ``outputs``. If ``stamp`` is true, a generic output file is 276 used. If ``stamp`` is a file path, that file is used as a stamp file. Like any 277 output file, ``stamp`` must be in the build directory. Defaults to false. 278* ``environment``: Optional list of strings. Environment variables to set, 279 passed as NAME=VALUE strings. 280* ``working_directory``: Optional file path. When provided the current working 281 directory will be set to this location before the Python module or script is 282 run. 283 284**Expressions** 285 286``pw_python_action`` evaluates expressions in ``args``, the arguments passed to 287the script. These expressions function similarly to generator expressions in 288CMake. Expressions may be passed as a standalone argument or as part of another 289argument. A single argument may contain multiple expressions. 290 291Generally, these expressions are used within templates rather than directly in 292BUILD.gn files. This allows build code to use GN labels without having to worry 293about converting them to files. 294 295.. note:: 296 297 We intend to replace these expressions with native GN features when possible. 298 See `pwbug/347 <http://bugs.pigweed.dev/347>`_. 299 300The following expressions are supported: 301 302.. describe:: <TARGET_FILE(gn_target)> 303 304 Evaluates to the output file of the provided GN target. For example, the 305 expression 306 307 .. code-block:: 308 309 "<TARGET_FILE(//foo/bar:static_lib)>" 310 311 might expand to 312 313 .. code-block:: 314 315 "/home/User/project_root/out/obj/foo/bar/static_lib.a" 316 317 ``TARGET_FILE`` parses the ``.ninja`` file for the GN target, so it should 318 always find the correct output file, regardless of the toolchain's or target's 319 configuration. Some targets, such as ``source_set`` and ``group`` targets, do 320 not have an output file, and attempting to use ``TARGET_FILE`` with them 321 results in an error. 322 323 ``TARGET_FILE`` only resolves GN target labels to their outputs. To resolve 324 paths generally, use the standard GN approach of applying the 325 ``rebase_path(path, root_build_dir)`` function. This function 326 converts the provided GN path or list of paths to be relative to the build 327 directory, from which all build commands and scripts are executed. 328 329.. describe:: <TARGET_FILE_IF_EXISTS(gn_target)> 330 331 ``TARGET_FILE_IF_EXISTS`` evaluates to the output file of the provided GN 332 target, if the output file exists. If the output file does not exist, the 333 entire argument that includes this expression is omitted, even if there is 334 other text or another expression. 335 336 For example, consider this expression: 337 338 .. code-block:: 339 340 "--database=<TARGET_FILE_IF_EXISTS(//alpha/bravo)>" 341 342 If the ``//alpha/bravo`` target file exists, this might expand to the 343 following: 344 345 .. code-block:: 346 347 "--database=/home/User/project/out/obj/alpha/bravo/bravo.elf" 348 349 If the ``//alpha/bravo`` target file does not exist, the entire 350 ``--database=`` argument is omitted from the script arguments. 351 352.. describe:: <TARGET_OBJECTS(gn_target)> 353 354 Evaluates to the object files of the provided GN target. Expands to a separate 355 argument for each object file. If the target has no object files, the argument 356 is omitted entirely. Because it does not expand to a single expression, the 357 ``<TARGET_OBJECTS(...)>`` expression may not have leading or trailing text. 358 359 For example, the expression 360 361 .. code-block:: 362 363 "<TARGET_OBJECTS(//foo/bar:a_source_set)>" 364 365 might expand to multiple separate arguments: 366 367 .. code-block:: 368 369 "/home/User/project_root/out/obj/foo/bar/a_source_set.file_a.cc.o" 370 "/home/User/project_root/out/obj/foo/bar/a_source_set.file_b.cc.o" 371 "/home/User/project_root/out/obj/foo/bar/a_source_set.file_c.cc.o" 372 373**Example** 374 375.. code-block:: 376 377 import("$dir_pw_build/python_action.gni") 378 379 pw_python_action("postprocess_main_image") { 380 script = "py/postprocess_binary.py" 381 args = [ 382 "--database", 383 rebase_path("my/database.csv", root_build_dir), 384 "--binary=<TARGET_FILE(//firmware/images:main)>", 385 ] 386 stamp = true 387 } 388 389.. _module-pw_build-pw_exec: 390 391pw_exec 392------- 393``pw_exec`` allows for execution of arbitrary programs. It is a wrapper around 394``pw_python_action`` but allows for specifying the program to execute. 395 396.. note:: Prefer to use ``pw_python_action`` instead of calling out to shell 397 scripts, as the python will be more portable. ``pw_exec`` should generally 398 only be used for interacting with legacy/existing scripts. 399 400**Arguments** 401 402* ``program``: The program to run. Can be a full path or just a name (in which 403 case $PATH is searched). 404* ``args``: Optional list of arguments to the program. 405* ``deps``: Dependencies for this target. 406* ``public_deps``: Public dependencies for this target. In addition to outputs 407 from this target, outputs generated by public dependencies can be used as 408 inputs from targets that depend on this one. This is not the case for private 409 deps. 410* ``inputs``: Optional list of build inputs to the program. 411* ``outputs``: Optional list of artifacts produced by the program's execution. 412* ``env``: Optional list of key-value pairs defining environment variables for 413 the program. 414* ``env_file``: Optional path to a file containing a list of newline-separated 415 key-value pairs defining environment variables for the program. 416* ``args_file``: Optional path to a file containing additional positional 417 arguments to the program. Each line of the file is appended to the 418 invocation. Useful for specifying arguments from GN metadata. 419* ``skip_empty_args``: If args_file is provided, boolean indicating whether to 420 skip running the program if the file is empty. Used to avoid running 421 commands which error when called without arguments. 422* ``capture_output``: If true, output from the program is hidden unless the 423 program exits with an error. Defaults to true. 424* ``working_directory``: The working directory to execute the subprocess with. 425 If not specified it will not be set and the subprocess will have whatever 426 the parent current working directory is. 427 428**Example** 429 430.. code-block:: 431 432 import("$dir_pw_build/exec.gni") 433 434 pw_exec("hello_world") { 435 program = "/bin/sh" 436 args = [ 437 "-c", 438 "echo hello \$WORLD", 439 ] 440 env = [ 441 "WORLD=world", 442 ] 443 } 444 445pw_input_group 446-------------- 447``pw_input_group`` defines a group of input files which are not directly 448processed by the build but are still important dependencies of later build 449steps. This is commonly used alongside metadata to propagate file dependencies 450through the build graph and force rebuilds on file modifications. 451 452For example ``pw_docgen`` defines a ``pw_doc_group`` template which outputs 453metadata from a list of input files. The metadata file is not actually part of 454the build, and so changes to any of the input files do not trigger a rebuild. 455This is problematic, as targets that depend on the metadata should rebuild when 456the inputs are modified but GN cannot express this dependency. 457 458``pw_input_group`` solves this problem by allowing a list of files to be listed 459in a target that does not output any build artifacts, causing all dependent 460targets to correctly rebuild. 461 462**Arguments** 463 464``pw_input_group`` accepts all arguments that can be passed to a ``group`` 465target, as well as requiring one extra: 466 467* ``inputs``: List of input files. 468 469**Example** 470 471.. code-block:: 472 473 import("$dir_pw_build/input_group.gni") 474 475 pw_input_group("foo_metadata") { 476 metadata = { 477 files = [ 478 "x.foo", 479 "y.foo", 480 "z.foo", 481 ] 482 } 483 inputs = metadata.files 484 } 485 486Targets depending on ``foo_metadata`` will rebuild when any of the ``.foo`` 487files are modified. 488 489pw_zip 490------ 491``pw_zip`` is a target that allows users to zip up a set of input files and 492directories into a single output ``.zip`` file—a simple automation of a 493potentially repetitive task. 494 495**Arguments** 496 497* ``inputs``: List of source files as well as the desired relative zip 498 destination. See below for the input syntax. 499* ``dirs``: List of entire directories to be zipped as well as the desired 500 relative zip destination. See below for the input syntax. 501* ``output``: Filename of output ``.zip`` file. 502* ``deps``: List of dependencies for the target. 503 504**Input Syntax** 505 506Inputs all need to follow the correct syntax: 507 508#. Path to source file or directory. Directories must end with a ``/``. 509#. The delimiter (defaults to ``>``). 510#. The desired destination of the contents within the ``.zip``. Must start 511 with ``/`` to indicate the zip root. Any number of subdirectories are 512 allowed. If the source is a file it can be put into any subdirectory of the 513 root. If the source is a file, the zip copy can also be renamed by ending 514 the zip destination with a filename (no trailing ``/``). 515 516Thus, it should look like the following: ``"[source file or dir] > /"``. 517 518**Example** 519 520Let's say we have the following structure for a ``//source/`` directory: 521 522.. code-block:: 523 524 source/ 525 ├── file1.txt 526 ├── file2.txt 527 ├── file3.txt 528 └── some_dir/ 529 ├── file4.txt 530 └── some_other_dir/ 531 └── file5.txt 532 533And we create the following build target: 534 535.. code-block:: 536 537 import("$dir_pw_build/zip.gni") 538 539 pw_zip("target_name") { 540 inputs = [ 541 "//source/file1.txt > /", # Copied to the zip root dir. 542 "//source/file2.txt > /renamed.txt", # File renamed. 543 "//source/file3.txt > /bar/", # File moved to the /bar/ dir. 544 ] 545 546 dirs = [ 547 "//source/some_dir/ > /bar/some_dir/", # All /some_dir/ contents copied 548 # as /bar/some_dir/. 549 ] 550 551 # Note on output: if the specific output directory isn't defined 552 # (such as output = "zoo.zip") then the .zip will output to the 553 # same directory as the BUILD.gn file that called the target. 554 output = "//$target_out_dir/foo.zip" # Where the foo.zip will end up 555 } 556 557This will result in a ``.zip`` file called ``foo.zip`` stored in 558``//$target_out_dir`` with the following structure: 559 560.. code-block:: 561 562 foo.zip 563 ├── bar/ 564 │ ├── file3.txt 565 │ └── some_dir/ 566 │ ├── file4.txt 567 │ └── some_other_dir/ 568 │ └── file5.txt 569 ├── file1.txt 570 └── renamed.txt 571 572.. _module-pw_build-relative-source-file-names: 573 574pw_relative_source_file_names 575----------------------------- 576This template recursively walks the listed dependencies and collects the names 577of all the headers and source files required by the targets, and then transforms 578them such that they reflect the ``__FILE__`` when pw_build's ``relative_paths`` 579config is applied. This is primarily intended for side-band generation of 580pw_tokenizer tokens so file name tokens can be utilized in places where 581pw_tokenizer is unable to embed token information as part of C/C++ compilation. 582 583This template produces a JSON file containing an array of strings (file paths 584with ``-ffile-prefix-map``-like transformations applied) that can be used to 585:ref:`generate a token database <module-pw_tokenizer-database-creation>`. 586 587**Arguments** 588 589* ``deps``: A required list of targets to recursively extract file names from. 590* ``outputs``: A required array with a single element: the path to write the 591 final JSON file to. 592 593**Example** 594 595Let's say we have the following project structure: 596 597.. code-block:: 598 599 project root 600 ├── foo/ 601 │ ├── foo.h 602 │ └── foo.cc 603 ├── bar/ 604 │ ├── bar.h 605 │ └── bar.cc 606 ├── unused/ 607 │ ├── unused.h 608 │ └── unused.cc 609 └── main.cc 610 611And a BUILD.gn at the root: 612 613.. code-block:: 614 615 pw_source_set("bar") { 616 public_configs = [ ":bar_headers" ] 617 public = [ "bar/bar.h" ] 618 sources = [ "bar/bar.cc" ] 619 } 620 621 pw_source_set("foo") { 622 public_configs = [ ":foo_headers" ] 623 public = [ "foo/foo.h" ] 624 sources = [ "foo/foo.cc" ] 625 deps = [ ":bar" ] 626 } 627 628 629 pw_source_set("unused") { 630 public_configs = [ ":unused_headers" ] 631 public = [ "unused/unused.h" ] 632 sources = [ "unused/unused.cc" ] 633 deps = [ ":bar" ] 634 } 635 636 pw_executable("main") { 637 sources = [ "main.cc" ] 638 deps = [ ":foo" ] 639 } 640 641 pw_relative_source_file_names("main_source_files") { 642 deps = [ ":main" ] 643 outputs = [ "$target_gen_dir/main_source_files.json" ] 644 } 645 646The json file written to `out/gen/main_source_files.json` will contain: 647 648.. code-block:: 649 650 [ 651 "bar/bar.cc", 652 "bar/bar.h", 653 "foo/foo.cc", 654 "foo/foo.h", 655 "main.cc" 656 ] 657 658Since ``unused`` isn't a transitive dependency of ``main``, its source files 659are not included. Similarly, even though ``bar`` is not a direct dependency of 660``main``, its source files *are* included because ``foo`` brings in ``bar`` as 661a transitive dependency. 662 663Note how the file paths in this example are relative to the project root rather 664than being absolute paths (e.g. ``/home/user/ralph/coding/my_proj/main.cc``). 665This is a result of transformations applied to strip absolute pathing prefixes, 666matching the behavior of pw_build's ``$dir_pw_build:relative_paths`` config. 667 668Build time errors: pw_error and pw_build_assert 669----------------------------------------------- 670In Pigweed's complex, multi-toolchain GN build it is not possible to build every 671target in every configuration. GN's ``assert`` statement is not ideal for 672enforcing the correct configuration because it may prevent the GN build files or 673targets from being referred to at all, even if they aren't used. 674 675The ``pw_error`` GN template results in an error if it is executed during the 676build. These error targets can exist in the build graph, but cannot be depended 677on without an error. 678 679``pw_build_assert`` evaluates to a ``pw_error`` if a condition fails or nothing 680(an empty group) if the condition passes. Targets can add a dependency on a 681``pw_build_assert`` to enforce a condition at build time. 682 683The templates for build time errors are defined in ``pw_build/error.gni``. 684 685CMake 686===== 687Pigweed's `CMake`_ support is provided primarily for projects that have an 688existing CMake build and wish to integrate Pigweed without switching to a new 689build system. 690 691The following command generates Ninja build files for a host build in the 692``out/cmake_host`` directory: 693 694.. code-block:: sh 695 696 cmake -B out/cmake_host -S "$PW_ROOT" -G Ninja -DCMAKE_TOOLCHAIN_FILE=$PW_ROOT/pw_toolchain/host_clang/toolchain.cmake 697 698The ``PW_ROOT`` environment variable must point to the root of the Pigweed 699directory. This variable is set by Pigweed's environment setup. 700 701Tests can be executed with the ``pw_run_tests.GROUP`` targets. To run Pigweed 702module tests, execute ``pw_run_tests.modules``: 703 704.. code-block:: sh 705 706 ninja -C out/cmake_host pw_run_tests.modules 707 708:ref:`module-pw_watch` supports CMake, so you can also run 709 710.. code-block:: sh 711 712 pw watch -C out/cmake_host pw_run_tests.modules 713 714CMake functions 715--------------- 716CMake convenience functions are defined in ``pw_build/pigweed.cmake``. 717 718* ``pw_auto_add_simple_module`` -- For modules with only one library, 719 automatically declare the library and its tests. 720* ``pw_auto_add_module_tests`` -- Create test targets for all tests in a module. 721* ``pw_add_facade`` -- Declare a module facade. 722* ``pw_set_backend`` -- Set the backend library to use for a facade. 723* ``pw_add_module_library`` -- Add a library that is part of a module. 724* ``pw_add_test`` -- Declare a test target. 725 726See ``pw_build/pigweed.cmake`` for the complete documentation of these 727functions. 728 729Special libraries that do not fit well with these functions are created with the 730standard CMake functions, such as ``add_library`` and ``target_link_libraries``. 731 732Facades and backends 733-------------------- 734The CMake build uses CMake cache variables for configuring 735:ref:`facades<docs-module-structure-facades>` and backends. Cache variables are 736similar to GN's build args set with ``gn args``. Unlike GN, CMake does not 737support multi-toolchain builds, so these variables have a single global value 738per build directory. 739 740The ``pw_add_facade`` function declares a cache variable named 741``<module_name>_BACKEND`` for each facade. Cache variables can be awkward to 742work with, since their values only change when they're assigned, but then 743persist accross CMake invocations. These variables should be set in one of the 744following ways: 745 746* Call ``pw_set_backend`` to set backends appropriate for the target in the 747 target's toolchain file. The toolchain file is provided to ``cmake`` with 748 ``-DCMAKE_TOOLCHAIN_FILE=<toolchain file>``. 749* Call ``pw_set_backend`` in the top-level ``CMakeLists.txt`` before other 750 CMake code executes. 751* Set the backend variable at the command line with the ``-D`` option. 752 753 .. code-block:: sh 754 755 cmake -B out/cmake_host -S "$PW_ROOT" -G Ninja \ 756 -DCMAKE_TOOLCHAIN_FILE=$PW_ROOT/pw_toolchain/host_clang/toolchain.cmake \ 757 -Dpw_log_BACKEND=pw_log_basic 758 759* Temporarily override a backend by setting it interactively with ``ccmake`` or 760 ``cmake-gui``. 761 762If the backend is set to a build target that does not exist, there will be an 763error message like the following: 764 765.. code-block:: 766 767 CMake Error at pw_build/pigweed.cmake:244 (add_custom_target): 768 Error evaluating generator expression: 769 770 $<TARGET_PROPERTY:my_backend_that_does_not_exist,TYPE> 771 772 Target "my_backend_that_does_not_exist" not found. 773 774Toolchain setup 775--------------- 776In CMake, the toolchain is configured by setting CMake variables, as described 777in the `CMake documentation <https://cmake.org/cmake/help/latest/manual/cmake-toolchains.7.html>`_. 778These variables are typically set in a toolchain CMake file passed to ``cmake`` 779with the ``-D`` option (``-DCMAKE_TOOLCHAIN_FILE=path/to/file.cmake``). 780For Pigweed embedded builds, set ``CMAKE_SYSTEM_NAME`` to the empty string 781(``""``). 782 783Toolchains may set the ``pw_build_WARNINGS`` variable to a list of ``INTERFACE`` 784libraries with compilation options for Pigweed's upstream libraries. This 785defaults to a strict set of warnings. Projects may need to use less strict 786compilation warnings to compile backends exposed to Pigweed code (such as 787``pw_log``) that cannot compile with Pigweed's flags. If desired, Projects can 788access these warnings by depending on ``pw_build.warnings``. 789 790Third party libraries 791--------------------- 792The CMake build includes third-party libraries similarly to the GN build. A 793``dir_pw_third_party_<library>`` cache variable is defined for each third-party 794dependency. The variable must be set to the absolute path of the library in 795order to use it. If the variable is empty 796(``if("${dir_pw_third_party_<library>}" STREQUAL "")``), the dependency is not 797available. 798 799Third-party dependencies are not automatically added to the build. They can be 800manually added with ``add_subdirectory`` or by setting the 801``pw_third_party_<library>_ADD_SUBDIRECTORY`` option to ``ON``. 802 803Third party variables are set like any other cache global variable in CMake. It 804is recommended to set these in one of the following ways: 805 806* Set with the CMake ``set`` function in the toolchain file or a 807 ``CMakeLists.txt`` before other CMake code executes. 808 809 .. code-block:: cmake 810 811 set(dir_pw_third_party_nanopb ${CMAKE_CURRENT_SOURCE_DIR}/external/nanopb CACHE PATH "" FORCE) 812 813* Set the variable at the command line with the ``-D`` option. 814 815 .. code-block:: sh 816 817 cmake -B out/cmake_host -S "$PW_ROOT" -G Ninja \ 818 -DCMAKE_TOOLCHAIN_FILE=$PW_ROOT/pw_toolchain/host_clang/toolchain.cmake \ 819 -Ddir_pw_third_party_nanopb=/path/to/nanopb 820 821* Set the variable interactively with ``ccmake`` or ``cmake-gui``. 822 823Use Pigweed from an existing CMake project 824------------------------------------------ 825To use Pigweed libraries form a CMake-based project, simply include the Pigweed 826repository from a ``CMakeLists.txt``. 827 828.. code-block:: cmake 829 830 add_subdirectory(path/to/pigweed pigweed) 831 832All module libraries will be available as ``module_name`` or 833``module_name.sublibrary``. 834 835If desired, modules can be included individually. 836 837.. code-block:: cmake 838 839 add_subdirectory(path/to/pigweed/pw_some_module pw_some_module) 840 add_subdirectory(path/to/pigweed/pw_another_module pw_another_module) 841 842Bazel 843===== 844Bazel is currently very experimental, and only builds for host and ARM Cortex-M 845microcontrollers. 846 847The common configuration for Bazel for all modules is in the ``pigweed.bzl`` 848file. The built-in Bazel rules ``cc_binary``, ``cc_library``, and ``cc_test`` 849are wrapped with ``pw_cc_binary``, ``pw_cc_library``, and ``pw_cc_test``. 850These wrappers add parameters to calls to the compiler and linker. 851 852In addition to wrapping the built-in rules, Pigweed also provides a custom 853rule for handling linker scripts with Bazel. e.g. 854 855.. code-block:: python 856 857 pw_linker_script( 858 name = "some_linker_script", 859 linker_script = ":some_configurable_linker_script.ld", 860 defines = [ 861 "PW_BOOT_FLASH_BEGIN=0x08000200", 862 "PW_BOOT_FLASH_SIZE=1024K", 863 "PW_BOOT_HEAP_SIZE=112K", 864 "PW_BOOT_MIN_STACK_SIZE=1K", 865 "PW_BOOT_RAM_BEGIN=0x20000000", 866 "PW_BOOT_RAM_SIZE=192K", 867 "PW_BOOT_VECTOR_TABLE_BEGIN=0x08000000", 868 "PW_BOOT_VECTOR_TABLE_SIZE=512", 869 ], 870 ) 871 872 pw_cc_binary( 873 name = "some_binary", 874 srcs = ["some_source.c"], 875 additional_linker_inputs = [":some_linker_script"], 876 linkopts = ["-T $(location :some_linker_script)"], 877 ) 878 879Currently Pigweed is making use of a set of 880`open source <https://github.com/silvergasp/bazel-embedded>`_ toolchains. The 881host builds are only supported on Linux/Mac based systems. Additionally the 882host builds are not entirely hermetic, and will make use of system 883libraries and headers. This is close to the default configuration for Bazel, 884though slightly more hermetic. The host toolchain is based around clang-11 which 885has a system dependency on 'libtinfo.so.5' which is often included as part of 886the libncurses packages. On Debian based systems this can be installed using the 887command below: 888 889.. code-block:: sh 890 891 sudo apt install libncurses5 892 893The host toolchain does not currently support native Windows, though using WSL 894is a viable alternative. 895 896The ARM Cortex-M Bazel toolchains are based around gcc-arm-non-eabi and are 897entirely hermetic. You can target Cortex-M, by using the platforms command line 898option. This set of toolchains is supported from hosts; Windows, Mac and Linux. 899The platforms that are currently supported are listed below: 900 901.. code-block:: sh 902 903 bazel build //:your_target --platforms=@pigweed//pw_build/platforms:cortex_m0 904 bazel build //:your_target --platforms=@pigweed//pw_build/platforms:cortex_m1 905 bazel build //:your_target --platforms=@pigweed//pw_build/platforms:cortex_m3 906 bazel build //:your_target --platforms=@pigweed//pw_build/platforms:cortex_m4 907 bazel build //:your_target --platforms=@pigweed//pw_build/platforms:cortex_m7 908 bazel build //:your_target \ 909 --platforms=@pigweed//pw_build/platforms:cortex_m4_fpu 910 bazel build //:your_target \ 911 --platforms=@pigweed//pw_build/platforms:cortex_m7_fpu 912 913 914The above examples are cpu/fpu oriented platforms and can be used where 915applicable for your application. There some more specific platforms for the 916types of boards that are included as examples in Pigweed. It is strongly 917encouraged that you create your own set of platforms specific for your project, 918that implement the constraint_settings in this repository. e.g. 919 920New board constraint_value: 921 922.. code-block:: python 923 924 #your_repo/build_settings/constraints/board/BUILD 925 constraint_value( 926 name = "nucleo_l432kc", 927 constraint_setting = "@pigweed//pw_build/constraints/board", 928 ) 929 930New chipset constraint_value: 931 932.. code-block:: python 933 934 # your_repo/build_settings/constraints/chipset/BUILD 935 constraint_value( 936 name = "stm32l432kc", 937 constraint_setting = "@pigweed//pw_build/constraints/chipset", 938 ) 939 940New platforms for chipset and board: 941 942.. code-block:: python 943 944 #your_repo/build_settings/platforms/BUILD 945 # Works with all stm32l432kc 946 platforms( 947 name = "stm32l432kc", 948 parents = ["@pigweed//pw_build/platforms:cortex_m4"], 949 constraint_values = 950 ["@your_repo//build_settings/constraints/chipset:stm32l432kc"], 951 ) 952 953 # Works with only the nucleo_l432kc 954 platforms( 955 name = "nucleo_l432kc", 956 parents = [":stm32l432kc"], 957 constraint_values = 958 ["@your_repo//build_settings/constraints/board:nucleo_l432kc"], 959 ) 960 961In the above example you can build your code with the command line: 962 963.. code-block:: python 964 965 bazel build //:your_target_for_nucleo_l432kc \ 966 --platforms=@your_repo//build_settings:nucleo_l432kc 967 968 969You can also specify that a specific target is only compatible with one 970platform: 971 972.. code-block:: python 973 974 cc_library( 975 name = "compatible_with_all_stm32l432kc", 976 srcs = ["tomato_src.c"], 977 target_compatible_with = 978 ["@your_repo//build_settings/constraints/chipset:stm32l432kc"], 979 ) 980 981 cc_library( 982 name = "compatible_with_only_nucleo_l432kc", 983 srcs = ["bbq_src.c"], 984 target_compatible_with = 985 ["@your_repo//build_settings/constraints/board:nucleo_l432kc"], 986 ) 987 988