1.. _module-pw_build-bazel: 2 3Bazel 4===== 5.. pigweed-module-subpage:: 6 :name: pw_build 7 8Bazel is currently very experimental, and only builds for host and ARM Cortex-M 9microcontrollers. 10 11.. _module-pw_build-bazel-wrapper-rules: 12 13Wrapper rules 14------------- 15The common configuration for Bazel for all modules is in the ``pigweed.bzl`` 16file. The built-in Bazel rules ``cc_binary``, ``cc_test`` are wrapped with 17``pw_cc_binary`` and ``pw_cc_test``. 18 19.. _module-pw_build-bazel-pw_linker_script: 20 21pw_linker_script 22---------------- 23In addition to wrapping the built-in rules, Pigweed also provides a custom 24rule for handling linker scripts with Bazel. e.g. 25 26.. code-block:: python 27 28 pw_linker_script( 29 name = "some_linker_script", 30 linker_script = ":some_configurable_linker_script.ld", 31 defines = [ 32 "PW_BOOT_FLASH_BEGIN=0x08000200", 33 "PW_BOOT_FLASH_SIZE=1024K", 34 "PW_BOOT_HEAP_SIZE=112K", 35 "PW_BOOT_MIN_STACK_SIZE=1K", 36 "PW_BOOT_RAM_BEGIN=0x20000000", 37 "PW_BOOT_RAM_SIZE=192K", 38 "PW_BOOT_VECTOR_TABLE_BEGIN=0x08000000", 39 "PW_BOOT_VECTOR_TABLE_SIZE=512", 40 ], 41 deps = [":some_header_library"], 42 ) 43 44 # You can include headers provided by targets specified in deps. 45 cc_library( 46 name = "some_header_library", 47 hdrs = ["test_header.h"], 48 includes = ["."], 49 ) 50 51 # You can include the linker script in the deps. 52 cc_binary( 53 name = "some_binary", 54 srcs = ["some_source.cc"], 55 deps = [":some_linker_script"], 56 ) 57 58 # Alternatively, you can use additional_linker_inputs and linkopts. This 59 # allows you to explicitly specify the command line order of linker scripts, 60 # and may be useful if your project defines more than one. 61 cc_binary( 62 name = "some_binary", 63 srcs = ["some_source.cc"], 64 additional_linker_inputs = [":some_linker_script"], 65 linkopts = ["-T $(location :some_linker_script)"], 66 ) 67 68.. _module-pw_build-bazel-pw_facade: 69 70pw_facade 71--------- 72In Bazel, a :ref:`facade <docs-module-structure-facades>` module has a few 73components: 74 75#. The **facade target**, i.e. the interface to the module. This is what 76 *backend implementations* depend on to know what interface they're supposed 77 to implement. 78 79#. The **library target**, i.e. both the facade (interface) and backend 80 (implementation). This is what *users of the module* depend on. It's a 81 regular ``cc_library`` that exposes the same headers as the facade, but 82 has a dependency on the "backend label flag" (discussed next). It may also 83 include some source files (if these are backend-independent). 84 85 Both the facade and library targets are created using the 86 ``pw_facade`` macro. For example, consider the following 87 macro invocation: 88 89 .. code-block:: python 90 91 pw_facade( 92 name = "binary_semaphore", 93 # A backend-independent source file. 94 srcs = [ 95 "binary_semaphore.cc", 96 ], 97 # The facade header. 98 hdrs = [ 99 "public/pw_sync/binary_semaphore.h", 100 ], 101 # Dependencies of this header. 102 deps = [ 103 "//pw_chrono:system_clock", 104 "//pw_preprocessor", 105 ], 106 # The backend, hidden behind a label_flag; see below. 107 backend = [ 108 ":binary_semaphore_backend", 109 ], 110 ) 111 112 This macro expands to both the library target, named ``binary_semaphore``, 113 and the facade target, named ``binary_semaphore.facade``. 114 115#. The **backend label flag**. This is a `label_flag 116 <https://bazel.build/extending/config#label-typed-build-settings>`_: a 117 dependency edge in the build graph that can be overridden by downstream projects. 118 119#. The **backend target** implements a particular backend for a facade. It's 120 just a plain ``cc_library``, with a dependency on the facade target. For example, 121 122 .. code-block:: python 123 124 cc_library( 125 name = "binary_semaphore", 126 srcs = [ 127 "binary_semaphore.cc", 128 ], 129 hdrs = [ 130 "public/pw_sync_stl/binary_semaphore_inline.h", 131 "public/pw_sync_stl/binary_semaphore_native.h", 132 "public_overrides/pw_sync_backend/binary_semaphore_inline.h", 133 "public_overrides/pw_sync_backend/binary_semaphore_native.h", 134 ], 135 includes = [ 136 "public", 137 "public_overrides", 138 ], 139 deps = [ 140 # Dependencies of the backend's headers and sources. 141 "//pw_assert", 142 "//pw_chrono:system_clock", 143 # A dependency on the facade target, which defines the interface 144 # this backend target implements. 145 "//pw_sync:binary_semaphore.facade", 146 ], 147 ) 148 149 If a project uses only one backend for a given facade, the backend label 150 flag should point at that backend target. 151 152#. The **facade constraint setting** and **backend constraint values**. Every 153 facade has an associated `constraint setting 154 <https://bazel.build/concepts/platforms#api-review>`_ (enum used in platform 155 definition), and each backend for this facade has an associated 156 ``constraint_value`` (enum value). Example: 157 158 .. code-block:: python 159 160 # //pw_sync/BUILD.bazel 161 constraint_setting( 162 name = "binary_semaphore_backend_constraint_setting", 163 ) 164 165 # //pw_sync_stl/BUILD.bazel 166 constraint_value( 167 name = "binary_semaphore_backend", 168 constraint_setting = "//pw_sync:binary_semaphore_backend_constraint_setting", 169 ) 170 171 # //pw_sync_freertos/BUILD.bazel 172 constraint_value( 173 name = "binary_semaphore_backend", 174 constraint_setting = "//pw_sync:binary_semaphore_backend_constraint_setting", 175 ) 176 177 `Target platforms <https://bazel.build/extending/platforms>`_ for Pigweed 178 projects should indicate which backend they select for each facade by 179 listing the corresponding ``constraint_value`` in their definition. This can 180 be used in a couple of ways: 181 182 #. It allows projects to switch between multiple backends based only on the 183 `target platform <https://bazel.build/extending/platforms>`_ using a 184 *backend multiplexer* (see below) instead of setting label flags in 185 their ``.bazelrc``. 186 187 #. It allows tests or libraries that only support a particular backend to 188 express this through the `target_compatible_with 189 <https://bazel.build/reference/be/common-definitions#common.target_compatible_with>`_ 190 attribute. Bazel will use this to `automatically skip incompatible 191 targets in wildcard builds 192 <https://bazel.build/extending/platforms#skipping-incompatible-targets>`_. 193 194#. The **backend multiplexer**. If a project uses more than one backend for a 195 given facade (e.g., it uses different backends for host and embedded target 196 builds), the backend label flag will point to a target that resolves to the 197 correct backend based on the target platform. This will typically be an 198 `alias <https://bazel.build/reference/be/general#alias>`_ with a ``select`` 199 statement mapping constraint values to the appropriate backend targets. For 200 example, 201 202 .. code-block:: python 203 204 alias( 205 name = "pw_sync_binary_semaphore_backend_multiplexer", 206 actual = select({ 207 "//pw_sync_stl:binary_semaphore_backend": "@pigweed//pw_sync_stl:binary_semaphore", 208 "//pw_sync_freertos:binary_semaphore_backend": "@pigweed//pw_sync_freertos:binary_semaphore_backend", 209 # If we're building for a host OS, use the STL backend. 210 "@platforms//os:macos": "@pigweed//pw_sync_stl:binary_semaphore", 211 "@platforms//os:linux": "@pigweed//pw_sync_stl:binary_semaphore", 212 "@platforms//os:windows": "@pigweed//pw_sync_stl:binary_semaphore", 213 # Unless the target platform is the host platform, it must 214 # explicitly specify which backend to use. The unspecified_backend 215 # is not compatible with any platform; taking this branch will produce 216 # an informative error. 217 "//conditions:default": "@pigweed//pw_build:unspecified_backend", 218 }), 219 ) 220 221pw_cc_blob_library 222------------------ 223The ``pw_cc_blob_library`` rule is useful for embedding binary data into a 224program. The rule takes in a mapping of symbol names to file paths, and 225generates a set of C++ source and header files that embed the contents of the 226passed-in files as arrays of ``std::byte``. 227 228The blob byte arrays are constant initialized and are safe to access at any 229time, including before ``main()``. 230 231``pw_cc_blob_library`` is also available in the :ref:`GN <module-pw_build-cc_blob_library>` 232and CMake builds. 233 234Arguments 235^^^^^^^^^ 236* ``blobs``: A list of ``pw_cc_blob_info`` targets, where each target 237 corresponds to a binary blob to be transformed from file to byte array. This 238 is a required field. ``pw_cc_blob_info`` attributes include: 239 240 * ``symbol_name``: The C++ symbol for the byte array. 241 * ``file_path``: The file path for the binary blob. 242 * ``linker_section``: If present, places the byte array in the specified 243 linker section. 244 * ``alignas``: If present, uses the specified string verbatim in 245 the ``alignas()`` specifier for the byte array. 246 247* ``out_header``: The header file to generate. Users will include this file 248 exactly as it is written here to reference the byte arrays. 249* ``namespace``: C++ namespace to place the generated blobs within. 250* ``alwayslink``: Whether this library should always be linked. Defaults to false. 251 252Example 253^^^^^^^ 254**BUILD.bazel** 255 256.. code-block:: python 257 258 pw_cc_blob_info( 259 name = "foo_blob", 260 file_path = "foo.bin", 261 symbol_name = "kFooBlob", 262 ) 263 264 pw_cc_blob_info( 265 name = "bar_blob", 266 file_path = "bar.bin", 267 symbol_name = "kBarBlob", 268 linker_section = ".bar_section", 269 ) 270 271 pw_cc_blob_library( 272 name = "foo_bar_blobs", 273 blobs = [ 274 ":foo_blob", 275 ":bar_blob", 276 ], 277 out_header = "my/stuff/foo_bar_blobs.h", 278 namespace = "my::stuff", 279 ) 280 281.. note:: If the binary blobs are generated as part of the build, be sure to 282 list them as deps to the pw_cc_blob_library target. 283 284**Generated Header** 285 286.. code-block:: 287 288 #pragma once 289 290 #include <array> 291 #include <cstddef> 292 293 namespace my::stuff { 294 295 extern const std::array<std::byte, 100> kFooBlob; 296 297 extern const std::array<std::byte, 50> kBarBlob; 298 299 } // namespace my::stuff 300 301**Generated Source** 302 303.. code-block:: 304 305 #include "my/stuff/foo_bar_blobs.h" 306 307 #include <array> 308 #include <cstddef> 309 310 #include "pw_preprocessor/compiler.h" 311 312 namespace my::stuff { 313 314 const std::array<std::byte, 100> kFooBlob = { ... }; 315 316 PW_PLACE_IN_SECTION(".bar_section") 317 const std::array<std::byte, 50> kBarBlob = { ... }; 318 319 } // namespace my::stuff 320 321.. _module-pw_build-bazel-pw_cc_binary_with_map: 322 323pw_cc_binary_with_map 324--------------------- 325The ``pw_cc_binary_with_map`` rule can be used to build a binary like 326``cc_binary`` does but also generate a .map file from the linking step. 327 328.. code-block:: python 329 330 pw_cc_binary_with_map( 331 name = "test", 332 srcs = ["empty_main.cc"], 333 ) 334 335This should result in a ``test.map`` file generated next to the ``test`` binary. 336 337Note that it's only partially compatible with the ``cc_binary`` interface and 338certain things are not implemented like make variable substitution. 339 340pw_elf_to_bin 341------------- 342The ``pw_elf_to_bin`` rule takes in a binary executable target and produces a 343file using the ``-Obinary`` option to ``objcopy``. This is only suitable for use 344with binaries where all the segments are non-overlapping. A common use case for 345this type of file is booting directly on hardware with no bootloader. 346 347.. code-block:: python 348 349 load("@pigweed//pw_build:binary_tools.bzl", "pw_elf_to_bin") 350 351 pw_elf_to_bin( 352 name = "bin", 353 elf_input = ":main", 354 bin_out = "main.bin", 355 ) 356 357pw_elf_to_dump 358-------------- 359The ``pw_elf_to_dump`` rule takes in a binary executable target and produces a 360text file containing the output of the toolchain's ``objdump -xd`` command. This 361contains the full binary layout, symbol table and disassembly which is often 362useful when debugging embedded firmware. 363 364.. code-block:: python 365 366 load("@pigweed//pw_build:binary_tools.bzl", "pw_elf_to_dump") 367 368 pw_elf_to_dump( 369 name = "dump", 370 elf_input = ":main", 371 dump_out = "main.dump", 372 ) 373 374Miscellaneous utilities 375----------------------- 376 377.. _module-pw_build-bazel-empty_cc_library: 378 379empty_cc_library 380^^^^^^^^^^^^^^^^ 381This empty library is used as a placeholder for label flags that need to point 382to a library of some kind, but don't actually need the dependency to amount to 383anything. 384 385default_link_extra_lib 386^^^^^^^^^^^^^^^^^^^^^^ 387This library groups together all libraries commonly required at link time by 388Pigweed modules. See :ref:`docs-build_system-bazel_link-extra-lib` for more 389details. 390 391unspecified_backend 392^^^^^^^^^^^^^^^^^^^ 393A special target used instead of a cc_library as the default condition in 394backend multiplexer select statements to signal that a facade is in an 395unconfigured state. This produces better error messages than e.g. using an 396invalid label. 397 398Toolchains and platforms 399------------------------ 400Pigweed provides clang-based host toolchains for Linux and Mac Arm gcc 401toolchain. The clang-based Linux and Arm gcc toolchains are entirely hermetic. 402We don't currently provide a host toolchain for Windows. 403