1.. _module-pw_toolchain_bazel-api: 2 3============= 4API reference 5============= 6.. pigweed-module-subpage:: 7 :name: pw_toolchain_bazel 8 9.. py:class:: pw_cc_toolchain 10 11 This rule is the core of a C/C++ toolchain definition. Critically, it is 12 intended to fully specify the following: 13 14 * Which tools to use for various compile/link actions. 15 * Which `well-known features <https://bazel.build/docs/cc-toolchain-config-reference#wellknown-features>`_ 16 are supported. 17 * Which flags to apply to various actions. 18 19 .. py:attribute:: action_configs 20 :type: List[label] 21 22 List of :py:class:`pw_cc_action_config` labels that bind tools to the 23 appropriate actions. This is how Bazel knows which binaries to use when 24 compiling, linking, or taking other actions like embedding data using 25 objcopy. 26 27 .. py:attribute:: flag_sets 28 :type: List[label] 29 30 List of flag sets to unconditionally apply to the respective 31 :py:class:`pw_cc_action_config`\s. The labels listed here will point to 32 :py:class:`pw_cc_flag_set` rules. 33 34 .. py:attribute:: extra_action_files 35 :type: List[label] 36 37 List of extra files to give to each different type of action. Replaces 38 all_files, ar_files, compiler_files, ... in the existing toolchain 39 definition. 40 41 .. py:attribute:: toolchain_identifier 42 :type: str 43 44 See `cc_common.create_cc_toolchain_config_info() <https://bazel.build/rules/lib/toplevel/cc_common#create_cc_toolchain_config_info>`_\. 45 46 .. py:attribute:: host_system_name 47 :type: str 48 49 See `cc_common.create_cc_toolchain_config_info() <https://bazel.build/rules/lib/toplevel/cc_common#create_cc_toolchain_config_info>`_\. 50 51 .. py:attribute:: target_system_name 52 :type: str 53 54 See `cc_common.create_cc_toolchain_config_info() <https://bazel.build/rules/lib/toplevel/cc_common#create_cc_toolchain_config_info>`_\. 55 56 .. py:attribute:: target_cpu 57 :type: str 58 59 See `cc_common.create_cc_toolchain_config_info() <https://bazel.build/rules/lib/toplevel/cc_common#create_cc_toolchain_config_info>`_\. 60 61 .. py:attribute:: target_libc 62 :type: str 63 64 See `cc_common.create_cc_toolchain_config_info() <https://bazel.build/rules/lib/toplevel/cc_common#create_cc_toolchain_config_info>`_\. 65 66 .. py:attribute:: compiler 67 :type: str 68 69 See `cc_common.create_cc_toolchain_config_info() <https://bazel.build/rules/lib/toplevel/cc_common#create_cc_toolchain_config_info>`_\. 70 71 .. py:attribute:: abi_version 72 :type: str 73 74 See `cc_common.create_cc_toolchain_config_info() <https://bazel.build/rules/lib/toplevel/cc_common#create_cc_toolchain_config_info>`_\. 75 76 .. py:attribute:: abi_libc_version 77 :type: str 78 79 See `cc_common.create_cc_toolchain_config_info() <https://bazel.build/rules/lib/toplevel/cc_common#create_cc_toolchain_config_info>`_\. 80 81 .. py:attribute:: cc_target_os 82 :type: str 83 84 See `cc_common.create_cc_toolchain_config_info() <https://bazel.build/rules/lib/toplevel/cc_common#create_cc_toolchain_config_info>`_\. 85 86 .. py:attribute:: builtin_sysroot 87 :type: str 88 89 See `cc_common.create_cc_toolchain_config_info() <https://bazel.build/rules/lib/toplevel/cc_common#create_cc_toolchain_config_info>`_\. 90 91 .. py:attribute:: cxx_builtin_include_directories 92 :type: List[str] 93 94 See `cc_common.create_cc_toolchain_config_info() <https://bazel.build/rules/lib/toplevel/cc_common#create_cc_toolchain_config_info>`_\. 95 96.. py:class:: pw_cc_flag_set 97 98 Declares an ordered set of flags bound to a set of actions. 99 100 Flag sets can be attached to a :py:class:`pw_cc_toolchain` via 101 :py:attr:`pw_cc_toolchain.flag_sets`\. 102 103 Examples: 104 105 .. code-block:: py 106 107 pw_cc_flag_set( 108 name = "warnings_as_errors", 109 flags = ["-Werror"], 110 ) 111 112 pw_cc_flag_set( 113 name = "layering_check", 114 flag_groups = [ 115 ":strict_module_headers", 116 ":dependent_module_map_files", 117 ], 118 ) 119 120 .. inclusive-language: disable 121 122 Note: In the vast majority of cases, alphabetical sorting is not desirable 123 for the :py:attr:`pw_cc_flag_set.flags` and 124 :py:attr:`pw_cc_flag_set.flag_groups` attributes. 125 `Buildifier <https://github.com/bazelbuild/buildtools/blob/master/buildifier/README.md>`_ 126 shouldn't ever try to sort these, but in the off chance it starts to these 127 members should be listed as exceptions in the ``SortableDenylist``. 128 129 .. inclusive-language: enable 130 131 .. py:attribute:: actions 132 :type: List[str] 133 134 A list of action names that this flag set applies to. 135 136 .. inclusive-language: disable 137 138 Valid choices are listed at 139 `@rules_cc//cc:action_names.bzl <https://github.com/bazelbuild/bazel/blob/master/tools/build_defs/cc/action_names.bzl>`_\. 140 141 .. inclusive-language: enable 142 143 It is possible for some needed action names to not be enumerated in this list, 144 so there is not rigid validation for these strings. Prefer using constants 145 rather than manually typing action names. 146 147 .. py:attribute:: flags 148 :type: List[str] 149 150 Flags that should be applied to the specified actions. 151 152 These are evaluated in order, with earlier flags appearing earlier in the 153 invocation of the underlying tool. If you need expansion logic, prefer 154 enumerating flags in a :py:class:`pw_cc_flag_group` or create a custom 155 rule that provides ``FlagGroupInfo``. 156 157 Note: :py:attr:`pw_cc_flag_set.flags` and 158 :py:attr:`pw_cc_flag_set.flag_groups` are mutually exclusive. 159 160 .. py:attribute:: flag_groups 161 :type: List[label] 162 163 Labels pointing to :py:class:`pw_cc_flag_group` rules. 164 165 This is intended to be compatible with any other rules that provide 166 ``FlagGroupInfo``. These are evaluated in order, with earlier flag groups 167 appearing earlier in the invocation of the underlying tool. 168 169 Note: :py:attr:`pw_cc_flag_set.flag_groups` and 170 :py:attr:`pw_cc_flag_set.flags` are mutually exclusive. 171 172.. py:class:: pw_cc_flag_group 173 174 Declares an (optionally parametric) ordered set of flags. 175 176 :py:class:`pw_cc_flag_group` rules are expected to be consumed exclusively by 177 :py:class:`pw_cc_flag_set` rules. Though simple lists of flags can be 178 expressed by populating ``flags`` on a :py:class:`pw_cc_flag_set`, 179 :py:class:`pw_cc_flag_group` provides additional power in the following two 180 ways: 181 182 1. Iteration and conditional expansion. Using 183 :py:attr:`pw_cc_flag_group.iterate_over`, 184 :py:attr:`pw_cc_flag_group.expand_if_available`\, and 185 :py:attr:`pw_cc_flag_group.expand_if_not_available`\, more complex 186 flag expressions can be made. This is critical for implementing things 187 like the ``libraries_to_link`` feature, where library names are 188 transformed into flags that end up in the final link invocation. 189 190 Note: ``expand_if_equal``, ``expand_if_true``, and ``expand_if_false`` 191 are not yet supported. 192 193 2. Flags are tool-independent. A :py:class:`pw_cc_flag_group` expresses 194 ordered flags that may be reused across various 195 :py:class:`pw_cc_flag_set` rules. This is useful for cases where multiple 196 :py:class:`pw_cc_flag_set` rules must be created to implement a feature 197 for which flags are slightly different depending on the action (e.g. 198 compile vs link). Common flags can be expressed in a shared 199 :py:class:`pw_cc_flag_group`, and the differences can be relegated to 200 separate :py:class:`pw_cc_flag_group` instances. 201 202 Examples: 203 204 .. code-block:: py 205 206 pw_cc_flag_group( 207 name = "user_compile_flag_expansion", 208 flags = ["%{user_compile_flags}"], 209 iterate_over = "user_compile_flags", 210 expand_if_available = "user_compile_flags", 211 ) 212 213 # This flag_group might be referenced from various FDO-related 214 # `pw_cc_flag_set` rules. More importantly, the flag sets pulling this in 215 # may apply to different sets of actions. 216 pw_cc_flag_group( 217 name = "fdo_profile_correction", 218 flags = ["-fprofile-correction"], 219 expand_if_available = "fdo_profile_path", 220 ) 221 222 .. py:attribute:: flags 223 :type: List[str] 224 225 List of flags provided by this rule. 226 227 For extremely complex expressions of flags that require nested flag groups 228 with multiple layers of expansion, prefer creating a custom rule in 229 `Starlark <https://bazel.build/rules/language>`_ that provides 230 ``FlagGroupInfo`` or ``FlagSetInfo``. 231 232 233 .. py:attribute:: iterate_over 234 :type: str 235 236 Expands :py:attr:`pw_cc_flag_group.flags` for items in the named list. 237 238 Toolchain actions have various variables accessible as names that can be 239 used to guide flag expansions. For variables that are lists, 240 :py:attr:`pw_cc_flag_group.iterate_over` must be used to expand the list into a series of flags. 241 242 Note that :py:attr:`pw_cc_flag_group.iterate_over` is the string name of a 243 build variable, and not an actual list. Valid options are listed in the 244 `C++ Toolchain Configuration <https://bazel.build/docs/cc-toolchain-config-reference#cctoolchainconfiginfo-build-variables>`_ 245 reference. 246 247 248 249 Note that the flag expansion stamps out the entire list of flags in 250 :py:attr:`pw_cc_flag_group.flags` once for each item in the list. 251 252 Example: 253 254 .. code-block:: py 255 256 # Expands each path in ``system_include_paths`` to a series of 257 # ``-isystem`` includes. 258 # 259 # Example input: 260 # system_include_paths = ["/usr/local/include", "/usr/include"] 261 # 262 # Expected result: 263 # "-isystem /usr/local/include -isystem /usr/include" 264 pw_cc_flag_group( 265 name = "system_include_paths", 266 flags = ["-isystem", "%{system_include_paths}"], 267 iterate_over = "system_include_paths", 268 ) 269 270 .. py:attribute:: expand_if_available 271 :type: str 272 273 Expands the expression in :py:attr:`pw_cc_flag_group.flags` if the 274 specified build variable is set. 275 276 .. py:attribute:: expand_if_not_available 277 :type: str 278 279 Expands the expression in :py:attr:`pw_cc_flag_group.flags` if the 280 specified build variable is **NOT** set. 281 282.. py:class:: pw_cc_tool 283 284 Declares a singular tool that can be bound to action configs. 285 286 :py:class:`pw_cc_tool` rules are intended to be consumed exclusively by 287 :py:class:`pw_cc_action_config` rules. These rules declare an underlying tool 288 that can be used to fulfill various actions. Many actions may reuse a shared 289 tool. 290 291 Examples: 292 293 .. code-block:: py 294 295 # A project-provided tool. 296 pw_cc_tool( 297 name = "clang_tool", 298 tool = "@llvm_toolchain//:bin/clang", 299 ) 300 301 # A tool expected to be preinstalled on a user's machine. 302 pw_cc_tool( 303 name = "clang_tool", 304 path = "/usr/bin/clang", 305 ) 306 307 .. py:attribute:: tool 308 :type: label 309 310 The underlying tool that this rule represents. 311 312 This attribute is a label rather than a simple file path. This means that 313 the file must be referenced relative to the BUILD file that exports it. 314 For example: 315 316 .. code-block:: none 317 318 @llvm_toolchain//:bin/clang 319 ^ ^ ^ 320 321 Where: 322 323 * ``@llvm_toolchain`` is the repository. 324 * ``//`` is the directory of the BUILD file that exports the file of 325 interest. 326 * ``bin/clang`` is the path of the actual binary relative to the BUILD 327 file of interest. 328 329 Note: :py:attr:`pw_cc_tool.tool` and :py:attr:`pw_cc_tool.path` are 330 mutually exclusive. 331 332 .. py:attribute:: path 333 :type: Path 334 335 An absolute path to a binary to use for this tool. 336 337 Relative paths are also supported, but they are relative to the 338 :py:class:`pw_cc_toolchain` that uses this tool rather than relative to 339 this :py:class:`pw_cc_tool` rule. 340 341 Note: :py:attr:`pw_cc_tool.path` and :py:attr:`pw_cc_tool.tool` are 342 mutually exclusive. 343 344 .. admonition:: Note 345 :class: warning 346 347 This method of listing a tool is NOT recommended, and is provided as an 348 escape hatch for edge cases. Prefer using :py:attr:`pw_cc_tool.tool` 349 whenever possible. 350 351 .. py:attribute:: execution_requirements 352 :type: List[str] 353 354 A list of strings that provide hints for execution environment 355 compatibility (e.g. ``requires-darwin``). 356 357 .. py:attribute:: requires_any_of 358 :type: List[label] 359 360 This tool may only be enabled when at least one of the constraints are 361 met. 362 363 If omitted, this tool will be enabled unconditionally. 364 365 .. py:attribute:: additional_files 366 :type: List[label] 367 368 Additional files that are required for this tool to correctly operate. 369 These files are propagated up to the :py:class:`pw_cc_toolchain` so you 370 typically won't need to explicitly specify the ``*_files`` attributes 371 on a :py:class:`pw_cc_toolchain`. 372 373 374.. py:class:: pw_cc_action_config 375 376 Declares the configuration and selection of `pw_cc_tool` rules. 377 378 Action configs are bound to a toolchain through `action_configs`, and are the 379 driving mechanism for controlling toolchain tool invocation/behavior. 380 381 Action configs define three key things: 382 383 * Which tools to invoke for a given type of action. 384 * Tool features and compatibility. 385 * :py:class:`pw_cc_flag_set`\s that are unconditionally bound to a tool 386 invocation. 387 388 Examples: 389 390 .. code-block:: py 391 392 pw_cc_action_config( 393 name = "ar", 394 action_names = ["@pw_toolchain//actions:all_ar_actions"], 395 implies = [ 396 "@pw_toolchain//features/legacy:archiver_flags", 397 "@pw_toolchain//features/legacy:linker_param_file", 398 ], 399 tools = [":ar_tool"], 400 ) 401 402 pw_cc_action_config( 403 name = "clang", 404 action_names = [ 405 "@pw_toolchain//actions:all_asm_actions", 406 "@pw_toolchain//actions:all_c_compiler_actions", 407 ] 408 tools = [":clang_tool"], 409 ) 410 411 .. py:attribute:: action_names 412 :type: List[str] 413 414 A list of action names to apply this action to. 415 416 .. inclusive-language: disable 417 418 Valid choices are listed at 419 `@rules_cc//cc:action_names.bzl <https://github.com/bazelbuild/bazel/blob/master/tools/build_defs/cc/action_names.bzl>`_\. 420 421 .. inclusive-language: enable 422 423 It is possible for some needed action names to not be enumerated in this list, 424 so there is not rigid validation for these strings. Prefer using constants 425 rather than manually typing action names. 426 427 .. py:attribute:: enabled 428 :type: bool 429 430 Whether or not this action config is enabled by default. 431 432 .. admonition:: Note 433 434 This defaults to ``True`` since it's assumed that most listed action 435 configs will be enabled and used by default. This is the opposite of 436 Bazel's native default. 437 438 .. py:attribute:: tools 439 :type: List[label] 440 441 The tool to use for the specified actions. 442 443 A tool can be a :py:class:`pw_cc_tool`, or a binary. 444 445 If multiple tools are specified, the first tool that has ``with_features`` 446 that satisfy the currently enabled feature set is used. 447 448 .. py:attribute:: flag_sets 449 :type: List[label] 450 451 Labels that point to :py:class:`pw_cc_flag_set`\s that are unconditionally 452 bound to the specified actions. 453 454 .. admonition:: Note 455 456 The flags in the :py:class:`pw_cc_flag_set` are only bound to matching 457 action names. If an action is listed in this rule's 458 :py:attr:`pw_cc_action_config.action_names`, 459 but is NOT listed in the :py:class:`pw_cc_flag_set`\'s 460 :py:attr:`pw_cc_flag_set.actions`, the flag will not be applied to that 461 action. 462 463 .. py:attribute:: implies 464 :type: List[str] 465 466 Names of features that should be automatically enabled when this tool is 467 used. 468 469 .. admonition:: Note 470 :class: warning 471 472 If this action config implies an unknown feature, this action config 473 will silently be disabled. This behavior is native to Bazel itself, and 474 there's no way to detect this and emit an error instead. For this 475 reason, be very cautious when listing implied features! 476 477.. py:class:: pw_cc_feature 478 479 Defines the implemented behavior of a C/C++ toolchain feature. 480 481 482 This rule is effectively a wrapper for the ``feature`` constructor in 483 `@rules_cc//cc:cc_toolchain_config_lib.bzl <https://github.com/bazelbuild/rules_cc/blob/main/cc/cc_toolchain_config_lib.bzl>`_. 484 485 A feature is basically a dynamic flag set. There are a variety of 486 dependencies and compatibility requirements that must be satisfied for the 487 listed flag sets to be applied. 488 489 A feature may be enabled or disabled through the following mechanisms:\ 490 491 * Via command-line flags, or a 492 `.bazelrc file <https://bazel.build/run/bazelrc>`_\. 493 * Through inter-feature relationships (enabling one feature may implicitly 494 enable another). 495 * Individual rules may elect to manually enable or disable features through 496 the 497 `builtin features attribute <https://bazel.build/reference/be/common-definitions#common.features>`_\. 498 499 Because of the dynamic nature of toolchain features, it's generally best to 500 avoid enumerating features as part of your toolchain with the following 501 exceptions: 502 503 * You want the flags to be controllable via Bazel's CLI. For example, adding 504 ``-v`` to a compiler invocation is often too verbose to be useful for most 505 workflows, but can be instrumental when debugging obscure errors. By 506 expressing compiler verbosity as a feature, users may opt-in when 507 necessary. 508 * You need to carry forward Starlark toolchain behaviors. If you're migrating 509 a complex Starlark-based toolchain definition to these rules, many of the 510 workflows and flags were likely based on features. This rule exists to 511 support those existing structures. 512 513 For more details about how Bazel handles features, see the official Bazel 514 documentation at 515 https://bazel.build/docs/cc-toolchain-config-reference#features. 516 517 Note: ``env_sets`` are not yet supported. 518 519 Examples: 520 521 .. code-block:: py 522 523 # A feature that can be easily toggled to include extra compiler output to 524 # help debug things like include search path ordering and showing all the 525 # flags passed to the compiler. 526 # 527 # Add `--features=verbose_compiler_output` to your Bazel invocation to 528 # enable. 529 pw_cc_feature( 530 name = "verbose_compiler_output", 531 enabled = False, 532 feature_name = "verbose_compiler_output", 533 flag_sets = [":verbose_compiler_flags"], 534 ) 535 536 # This feature signals a capability, and doesn't have associated flags. 537 # 538 # For a list of well-known features, see: 539 # https://bazel.build/docs/cc-toolchain-config-reference#wellknown-features 540 pw_cc_feature( 541 name = "link_object_files", 542 enabled = True, 543 feature_name = "supports_start_end_lib", 544 ) 545 546 .. py:attribute:: feature_name 547 :type: str 548 549 The name of the feature that this rule implements. 550 551 Feature names are used to express feature dependencies and compatibility. 552 Because features are tracked by string names rather than labels, there's 553 great flexibility in swapping out feature implementations or overriding 554 the built-in legacy features that Bazel silently binds to every 555 toolchain. 556 557 :py:attr:`pw_cc_feature.feature_name` is used rather than ``name`` to 558 distinguish between the rule name, and the intended final feature name. 559 This allows similar rules to exist in the same package, even if slight 560 differences are required. 561 562 Example: 563 564 .. code-block:: py 565 566 pw_cc_feature( 567 name = "sysroot_macos", 568 feature_name = "sysroot", 569 ... 570 ) 571 572 pw_cc_feature( 573 name = "sysroot_linux", 574 feature_name = "sysroot", 575 ... 576 ) 577 578 While two features with the same :py:attr:`pw_cc_feature.feature_name` may 579 not be bound to the same toolchain, they can happily live alongside each 580 other in the same BUILD file. 581 582 .. py:attribute:: enabled 583 :type: bool 584 585 Whether or not this feature is enabled by default. 586 587 .. py:attribute:: flag_sets 588 :type: List[label] 589 590 Flag sets that, when expanded, implement this feature. 591 592 .. py:attribute:: requires_any_of 593 :type: List[label] 594 595 A list of feature sets that define toolchain compatibility. 596 597 If **at least one** of the listed :py:class:`pw_cc_feature`\s or 598 :py:class:`pw_cc_feature_set`\s are satisfied (all features exist in the 599 toolchain AND are currently enabled), this feature is deemed compatible 600 and may be enabled. 601 602 If this feature **cannot** be enabled (such as if, in the first example 603 below, thin_lto didn't exist in the toolchain), it will throw an error. 604 605 .. code-block:: py 606 607 pw_cc_feature( 608 name = "requires_thin_lto_and_opt", 609 feature_name = "requires_thin_lto_and_opt", 610 requires_any_of = [":thin_lto_requirements"] 611 ) 612 613 pw_cc_feature( 614 name = "requires_thin_lto_or_opt", 615 feature_name = "requires_thin_lto_or_opt", 616 requires_any_of = [":thin_lto", ":opt"] 617 ) 618 619 .. admonition:: Note 620 621 Even if :py:attr:`pw_cc_feature.requires_any_of` is satisfied, a 622 feature is not enabled unless another mechanism (e.g. command-line 623 flags, :py:attr:`pw_cc_feature.implies`, or 624 :py:attr:`pw_cc_feature.enabled`\) signals that the feature should 625 actually be enabled. 626 627 .. py:attribute:: implies 628 :type: List[label] 629 630 List of features or action configs enabled along with this feature. 631 632 .. admonition:: Note 633 :class: warning 634 635 If any of the named features cannot be enabled, this feature is 636 silently disabled. 637 638 .. py:attribute:: mutually_exclusive 639 :type: List[Label] 640 641 A list of feature or mutually exclusive categories that this feature is 642 mutually exclusive with. 643 644 .. admonition:: Note 645 646 This feature cannot be enabled if another feature also provides the 647 listed feature. 648 649 650.. py:class:: pw_cc_feature_set 651 652 Defines a group of features. 653 654 Semantically equivalent to "all of the specified features", and may be used 655 wherever you can provide multiple features. 656 657 Example: 658 659 .. code-block:: py 660 661 pw_cc_feature_set( 662 name = "thin_lto_requirements", 663 all_of = [ 664 ":thin_lto", 665 ":opt", 666 ], 667 ) 668 669 .. py:attribute:: features 670 :type: List[label] 671 672 Features that must be enabled for this feature set to be deemed compatible 673 with the current toolchain configuration. 674