1.. _seed-0113: 2 3=========================================== 40113: Add modular Bazel C/C++ toolchain API 5=========================================== 6.. seed:: 7 :number: 0113 8 :name: Add modular Bazel C/C++ toolchain API 9 :status: Accepted 10 :proposal_date: 2023-09-28 11 :cl: 173453 12 :authors: Armando Montanez 13 :facilitator: Ted Pudlik 14 15------- 16Summary 17------- 18This SEED proposes custom Starlark rules for declaring C/C++ toolchains in 19Bazel, and scalable patterns for sharing modular components of C/C++ toolchain 20definitions. 21 22---------- 23Motivation 24---------- 25There is a lot of boilerplate involved in standing up a Bazel C/C++ toolchain. 26While a good portion of the verbosity of specifying a new toolchain is 27important, necessary machinery, nearly as much suffers from one or more of the 28following problems: 29 30- **Underdocumented patterns**: The 31 `create_cc_toolchain_config_info() <https://bazel.build/rules/lib/toplevel/cc_common#create_cc_toolchain_config_info>`_ 32 method has an attribute called ``target_cpu`` that doesn't have an associated 33 list of expected values, which suggests the argument is for bookkeeping 34 purposes and doesn't affect Bazel behavior. The reality is this argument 35 *does* have expected values that change behavior, but these are undocumented 36 (see `this GitHub issue <https://github.com/bazelbuild/bazel/issues/19353>`_ 37 for more information). 38 39- **Not inherently modular**: Bazel expects the overwhelming majority of a 40 C/C++ toolchain to be specified as part of a call to 41 ``create_cc_toolchain_config_info()``. Because this is a Starlark method, 42 there's a lot of flexibility with how you construct a toolchain config, but 43 very little by way of existing patterns for creating something that is 44 testable, sharable, or in other ways modular. The existing 45 `tutorial for creating a C/C++ toolchain <https://bazel.build/tutorials/ccp-toolchain-config#configure-cc-toolchain>`_ 46 illustrates expanding out the toolchain definition as a no-argument Starlark 47 rule. 48 49As Pigweed fully embraces multi-platform builds, it is critical for both 50Pigweed and users of Pigweed that it is easy to stand up custom toolchain 51definitions that work for the relevant hardware project-specific code/libraries. 52 53This SEED seeks to address the shortcomings in Bazel C/C++ toolchain 54declaration by establishing patterns and providing custom build rules that 55are owned and maintained by Pigweed. 56 57-------- 58Proposal 59-------- 601. Introduce rules for defining C/C++ toolchains 61================================================ 62In an effort to improve the experience of defining a C/C++ toolchain, Pigweed 63will introduce new Bazel rules that allow toolchains to share common boilerplate 64without hindering power-user functionality. 65 66While this work centers around an improved experience for defining a toolchain 67via ``create_cc_toolchain_config_info()``, other build rules will be introduced 68for closely related aspects of the toolchain definition process. 69 70An example of what these rules would look like in practice is as follows: 71 72.. code-block:: 73 74 # A tool that can be used by various build actions. 75 pw_cc_tool( 76 name = "clang_tool", 77 path = "@cipd_llvm_toolchain//:bin/clang", 78 additional_files = [ 79 "@cipd_llvm_toolchain//:all", 80 ], 81 ) 82 83 # A mapping of a tool to actions, with flag sets that define behaviors. 84 pw_cc_action_config( 85 name = "clang", 86 actions = ALL_ASM_ACTIONS + ALL_C_COMPILER_ACTIONS, 87 tools = [ 88 ":clang_tool", 89 ], 90 flag_sets = [ 91 # Most flags should NOT end up here. Only unconditional flags that 92 # should ALWAYS be bound to this tool (e.g. static library 93 # workaround fix for macOS). 94 "@pw_toolchain//flag_sets:generate_depfile", 95 ], 96 ) 97 98 # A trivial flag to be consumed by a C/C++ toolchain. 99 pw_cc_flag_set( 100 name = "werror", 101 actions = ALL_COMPILE_ACTIONS, 102 flags = [ 103 "-Werror", 104 ], 105 ) 106 107 # A list of flags that can be added to a toolchain configuration. 108 pw_cc_flag_set( 109 name = "user_compile_options", 110 actions = ALL_COMPILE_ACTIONS, 111 flag_groups = [ 112 ":user_compile_options_flags", 113 ] 114 ) 115 116 # A more complex compiler flag that requires template expansion. 117 pw_cc_flag_group( 118 name = "user_compile_options_flags", 119 flags = ["%{user_compile_flags}"], 120 iterate_over = "user_compile_flags", 121 expand_if_available = "user_compile_flags", 122 ) 123 124 # The underlying definition of a complete C/C++ toolchain. 125 pw_cc_toolchain( 126 name = "host_toolchain_linux", 127 action_configs = [ 128 ":clang", 129 ":clang++", 130 # ... 131 ], 132 additional_files = ":linux_sysroot_files", 133 action_config_flag_sets = [ 134 "@pw_toolchain//flag_sets:no_canonical_prefixes", 135 ":user_compile_options", 136 ":werror", 137 ], 138 features = [ 139 "@pw_toolchain//features:c++17", 140 ], 141 target_cpu = "x86_64", 142 target_system_name = "x86_64-unknown-linux-gnu", 143 toolchain_identifier = "host-toolchain-linux", 144 ) 145 146 # Toolchain resolution parameters for the above C/C++ toolchain. 147 toolchain( 148 name = "host_cc_toolchain_linux", 149 exec_compatible_with = [ 150 "@platforms//os:linux", 151 ], 152 target_compatible_with = [ 153 "@platforms//os:linux", 154 ], 155 toolchain = ":host_toolchain_linux", 156 toolchain_type = "@bazel_tools//tools/cpp:toolchain_type", 157 ) 158 1592. Provide standard toolchain building-blocks 160============================================= 161Pigweed will build out a repository of sharable instantiations of the 162aforementioned custom rules to give projects the resources they need to quickly 163and easily assemble toolchains for desktop and embedded targets. This includes, 164but is not limited to: 165 166- Rules that define tool sets for common toolchains (LLVM/clang, GNU/gcc). 167- Fully specified, modular 168 `features <https://bazel.build/docs/cc-toolchain-config-reference#features>`_. 169- Common flag sets that users may want to apply directly to their toolchains. 170 (enabling/disabling warnings, C++ standard version, etc.) 171- Platform/architecture support rules, including host OS SDK integrations 172 (Xcode, Windows SDK) and architecture-specific flag sets. 173 174These components will help establish patterns that will make it significantly 175easier for Pigweed users (and Bazel users at large) to define their own 176toolchains. 177 178--------------------- 179Problem investigation 180--------------------- 181This section explores previous work, and details why existing solutions don't 182meet Pigweed's needs. 183 184bazelembedded/rules_cc_toolchain 185================================ 186The `rules_cc_toolchain <https://github.com/bazelembedded/rules_cc_toolchain>`_ 187as part of the larger bazelembedded suite was actually the initial foundation 188of Pigweed's Bazel build. While this served as a very good initial foundation, 189it didn't provide the flexibility needed to easily stand up additional 190toolchains in ways that gave downstream projects sufficient control over the 191flags, libraries, tools, and sysroot. 192 193To work around the limited configurability of toolchain flags, Pigweed employed 194the following workarounds: 195 196#. Place ``copts`` and ``linkopts`` in ``.bazelrc``: This was problematic 197 because ``.bazelrc`` is not intrinsically shared with or propagated to 198 downstream users of Pigweed. Also, flags here are unilaterally applied 199 without OS-specific considerations. 200#. Attach flags to build targets with custom wrappers: This approach 201 intrinsically requires the existence of the ``pw_cc_library``, which 202 introduces difficulty around consistent interoperability with other Bazel 203 projects (among other issues detailed in 204 `b/267498492 <https://issues.pigweed.dev/issues/267498492>`_). 205 206Some other issues encountered when working with this solution include: 207 208- These rules intended to be modular, but in practice were relatively tightly 209 coupled. 210- Transitive dependencies throughout the toolchain definition process resulted 211 in some hard-to-debug issues (see 212 `this pull request <https://github.com/bazelembedded/rules_cc_toolchain/pull/39>`_ 213 and `b/254518544 <https://issues.pigweed.dev/issues/254518544>`_. 214 215bazelembedded/modular_cc_toolchains 216=================================== 217The `modular_cc_toolchains <https://github.com/bazelembedded/modular_cc_toolchains>`_ 218repository is a new attempt as part of the bazelembedded suite at providing 219truly modular toolchain rules. The proposed direction is much more in-line 220with the needs of Pigweed, but at the moment the repository exists as an 221initial draft of ideas rather than a complete implementation. 222 223This repository greatly inspired Pigweed's initial prototype for modular 224toolchains, but diverges significantly from the underlying Bazel C/C++ 225toolchain building-blocks. If this work was already complete and 226well-established, it probably would have satisfied some of Pigweed's key needs. 227 228lowRISC/crt 229=========== 230The `compiler repository toolkit <https://github.com/lowRISC/crt>`_ is another 231scalable approach at toolchains. This repository strives to be an all-in-one 232repository for embedded toolchains, and does a very good job at providing 233scalable models for establishing toolchains. This repository is relatively 234monolithic, though, and doesn't necessarily address the concern of quickly 235and easily standing up custom toolchains. Instead, it's more suited towards 236contributing new one-size-fits-all toolchains to ``crt`` directly. 237 238Android's toolchain 239=================== 240Android's Bazel-based build has invested heavily in toolchains, but they're 241very tightly coupled to the use cases of Android. For example, 242`this <https://cs.android.com/android/platform/superproject/main/+/main:build/bazel/toolchains/clang/host/linux-x86/cc_toolchain_features.bzl;l=375-389;drc=097d710c349758fc2732497fe5c3d1b0a32fa4a8>`_ binds ``-fstrict-aliasing`` to a condition based on the target architecture. 243These toolchains scale for the purpose of Android, but unfortunately are 244inherently not modular or reusable outside of that context. 245 246Due to the sheer amount of investment in these toolchains, though, they serve 247as a good reference for building out a complete toolchain in Bazel. 248 249Pigweed's modular Bazel toolchain prototype 250=========================================== 251As part of an exploratory phase of getting toolchains set up for Linux and 252macOS, 253`an initial prototype <https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/157634>`_ 254for modular Bazel toolchains was drafted and deployed to Pigweed. This work 255introduced two key build rules: ``pw_cc_toolchain_feature`` and 256``pw_cc_toolchain``. With both of these rules, it’s possible to instantiate a 257vast array of toolchain variants without writing a single line of Starlark. A 258few examples of these building blocks in action are provided below. 259 260.. code-block:: 261 262 # pw_cc_toolchain example taken from https://cs.opensource.google/pigweed/pigweed/+/main:pw_toolchain/host_clang/BUILD.bazel;l=113-143;drc=7df1768d915fe11dae05751f70f143e60acfb17a. 263 264 pw_cc_toolchain( 265 name = "host_toolchain_linux", 266 abi_libc_version = "unknown", 267 abi_version = "unknown", 268 all_files = ":all_linux_files", 269 ar = "@llvm_toolchain//:bin/llvm-ar", 270 271 # TODO: b/305737273 - Globbing all files for every action has a 272 # performance hit, make these more granular. 273 ar_files = ":all_linux_files", 274 as_files = ":all_linux_files", 275 compiler = "unknown", 276 compiler_files = ":all_linux_files", 277 coverage_files = ":all_linux_files", 278 cpp = "@llvm_toolchain//:bin/clang++", 279 dwp_files = ":all_linux_files", 280 feature_deps = [ 281 ":linux_sysroot", 282 "@pw_toolchain//features:no_canonical_prefixes", 283 ], 284 gcc = "@llvm_toolchain//:bin/clang", 285 gcov = "@llvm_toolchain//:bin/llvm-cov", 286 host_system_name = "unknown", 287 ld = "@llvm_toolchain//:bin/clang++", 288 linker_files = ":all_linux_files", 289 objcopy_files = ":all_linux_files", 290 strip = "@llvm_toolchain//:bin/llvm-strip", 291 strip_files = ":all_linux_files", 292 supports_param_files = 0, 293 target_cpu = "unknown", 294 target_libc = "unknown", 295 target_system_name = "unknown", 296 toolchain_identifier = "host-toolchain-linux", 297 ) 298 299 # pw_cc_toolchain_feature examples taken from https://cs.opensource.google/pigweed/pigweed/+/main:pw_toolchain_bazel/features/BUILD.bazel;l=21-34;drc=f96fd31675d136bd37a7f3840102cb256d555cea. 300 301 # Disables linking of the default C++ standard library to allow linking of a 302 # different version. 303 pw_cc_toolchain_feature( 304 name = "no_default_cpp_stdlib", 305 linkopts = ["-nostdlib++"], 306 ) 307 308 # Prevent relative paths from being converted to absolute paths. 309 # Note: This initial prototype made this a feature, but it should instead 310 # exist as a flag_set. 311 pw_cc_toolchain_feature( 312 name = "no_canonical_prefixes", 313 copts = [ 314 "-no-canonical-prefixes", 315 ], 316 ) 317 318What’s worth noting is that the ``pw_cc_toolchain_feature`` build rule looks 319very similar to a GN ``config``. This was no mistake, and was an attempt to 320substantially reduce the boiler plate for creating new sharable compiler flag 321groups. 322 323Unfortunately, it quickly became apparent that this approach limited control 324over the underlying toolchain definition creation process. In order to support 325``always_link`` on macOS, a custom logic and flags had to be directly baked into 326the rule used to declare toolchains 327(`relevant change <https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/168614/17/pw_toolchain_bazel/cc_toolchain/private/cc_toolchain.bzl>`_). 328While workarounds like this should be possible, the fact that this had to be 329upstreamed internally to ``pw_cc_toolchain`` exposed limitations in the 330abstraction patterns that were established. Such limitations could preclude 331some project from using ``pw_cc_toolchain`` at all. 332 333--------------- 334Detailed design 335--------------- 336The core design proposal is to transform the providers used by 337``cc_common.create_cc_toolchain_config_info()`` into build rules. The approach 338has been prototyped 339`here <https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/168351/1>`_, 340and retains API compatibility with the initial prototype as a proof-of-concept. 341 342One core pattern established by this design is transforming content that would 343typically live as Starlark to instead live in build files. This is done to 344make it easier to read and reference existing work. 345 346Implementation requirements 347=========================== 348Compatibility with native C/C++ rules 349------------------------------------- 350The core of Pigweed's toolchain build rules will rely on the providers 351defined as part of Bazel's 352`rules_cc <https://github.com/bazelbuild/rules_cc/blob/main/cc/cc_toolchain_config_lib.bzl>`_. This means that the new rules can interop with 353existing work that directly uses these toolchain primitives. It also provides 354a clear path for migrating existing toolchains piece-by-piece (which may be 355written completely in Starlark). 356 357Any extensions beyond the existing providers (e.g. specifying 358``additional_files`` on a ``pw_cc_tool``) must happen parallel to existing 359providers so that rules that consume the ``cc_toolchain_config_lib`` providers 360can work with vanilla providers. 361 362Compatibility with Bazel rules ecosystem 363---------------------------------------- 364In following with the larger Bazel rules ecosystem, the toolchain building 365blocks will be designed such that they can be used independently from Pigweed. 366This allows this work to be used for non-embedded projects, and reduces the 367overhead for standing up a custom Bazel C/C++ toolchain in any arbitrary 368project. 369 370Initially, the work will live as ``pw_toolchain_bazel`` in the main Pigweed 371repository to facilitate testing. This module must not depend on any other 372aspects of Pigweed. As the toolchain rules mature, they will eventually be 373available as a separate repository to match the modularity patterns used by 374the larger Bazel rules ecosystem. 375 376Introduce ``pw_cc_flag_set`` and ``pw_cc_flag_group`` 377===================================================== 378The majority of build flags would be expressed as ``pw_cc_flag_set`` and 379``pw_cc_flag_group`` pairs. 380 381.. code-block:: 382 383 # A simple flag_set with a single flag. 384 pw_cc_flag_set( 385 name = "werror", 386 # Only applies to C/C++ compile actions (i.e. no assemble/link/ar). 387 actions = ALL_CPP_COMPILER_ACTIONS + ALL_C_COMPILER_ACTIONS, 388 flags = [ 389 "-Werror", 390 ], 391 ) 392 393 # A flag_group that potentially expands to multiple flags. 394 pw_cc_flag_group( 395 name = "user_compile_options_flags", 396 flags = ["%{user_compile_flags}"], 397 iterate_over = "user_compile_flags", 398 expand_if_available = "user_compile_flags", 399 ) 400 401 # A flag_set that relies on a non-trivial or non-constant expression of 402 # flags. 403 pw_cc_flag_set( 404 name = "user_compile_options", 405 actions = ALL_COMPILE_ACTIONS, 406 flag_groups = [ 407 ":user_compile_options_flags", 408 ] 409 ) 410 411These closely mimic the API of ``cc_toolchain_config_lib.flag_set()`` and 412``cc_toolchain_config_lib.flag_group()``, with the following exceptions: 413 414**pw_cc_flag_set** 415 416*Added* 417 418- ``flags`` (added): Express a constant, trivial list of flags. If this is 419 specified, ``flag_groups`` may not be specified. This eliminates the need 420 for specifying a corresponding ``pw_cc_flag_group`` for every 421 ``pw_cc_flag_set`` for most flags. 422 423**pw_cc_flag_group** 424 425*Removed* 426 427- ``expand_if_true``\, ``expand_if_false``\, ``expand_if_equal``\: More complex 428 rules that rely on these should live as custom Starlark rules that provide a 429 ``FlagGroupInfo``\, or ``FlagSetInfo`` (depending on which is more ergonomic 430 to express the intent). See :ref:`pw_cc_flag_set-exceptions` below for an 431 example that illustrates how express more complex ``flag_group``\s that rely 432 on these attributes. 433 434Application of flags 435-------------------- 436Flags can be applied to a toolchain in three ways. This section attempts to 437provide initial guidance for where flags should be applied, though it's likely 438better practices will evolve as this work sees more use. For the latest 439guidance, please consult the official documentation when it rolls out to 440``pw_toolchain_bazel``. 441 442Flags unconditionally applied to a toolchain 443~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 444The majority of flags fall into this category. Architecture flags, 445globally-applied warnings, global defines, and other similar flags should be 446applied in the ``action_config_flag_sets`` attribute of a ``pw_cc_toolchain`` 447(see :ref:`pw_cc_toolchain-toolchain-declarations` for more information). Each 448``pw_cc_flag_set`` (or other rule that provides a ``FlagSetInfo`` provider) 449listed in ``action_config_flag_sets`` is unconditionally applied to every tool 450that matches the ``actions`` listed in the flag set. 451 452.. _application-of-flags-feature-flags: 453 454Feature flags 455~~~~~~~~~~~~~ 456Flag sets applied as features may or may not be enabled even if they are listed 457in the ``features`` attribute of a ``pw_cc_toolchain``. The 458`official Bazel documentation on features <https://bazel.build/docs/cc-toolchain-config-reference#features>`_ 459provides some good guidance on when features should be employed. To summarize, 460features should be used when either they should be controllable by users 461invoking the build, or if they affect build behavior beyond simply 462adding/removing flags (e.g. by introducing additional build actions). 463 464Flags unconditionally applied to a tool 465~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 466These flags are flags that are bound to a particular tool. These are not 467expressed as part of a ``pw_cc_toolchain``, and are instead bound to a 468``pw_cc_action_config``. This means that the flag set is unconditionally 469applied to every user of that action config. These kinds of flag applications 470should be reserved for flags required to assemble a working set of tools (such 471as generating a depfile, or adding support for static library link handling 472:ref:`as illustrated below <pw_cc_flag_set-exceptions>`). 473 474Flag application order 475~~~~~~~~~~~~~~~~~~~~~~ 476When invoking the underlying tools, the intended order of flags is as follows: 477 478#. Flags listed in the ``flag_sets`` list of a ``pw_cc_action_config``. 479#. Flags listed in ``action_config_flag_sets`` of a ``pw_cc_toolchain``. 480#. Flags listed in ``features`` of a ``pw_cc_toolchain``. 481 482These lists are intended to be sensitive to ordering, earlier items in the lists 483should appear in the final tool invocation flags before later items in the list. 484 485As transitive dependencies between features/flags are not supported as part of 486this proposal, exact traversal of transitive flag dependencies will be left 487to be decided if/when that feature is introduced. This proposal suggests 488postorder handling of flags as the most intuitive order. 489 490.. _pw_cc_flag_set-exceptions: 491 492Exceptions 493---------- 494Some flags are too complex to be nicely expressed in a Bazel build file. These 495flag sets or flag groups will need to be expressed in Starlark as custom rules. 496Fortunately, this will interop well with simpler flag sets since the underlying 497providers are all the same. 498 499**Example** 500 501In a Starlark file (e.g. ``//tools/llvm/llvm_ar_patch.bzl``), the required 502``flag_set`` can be defined: 503 504.. code-block:: 505 506 # Starlark rules in a .bzl file for a relatively complicated workaround for 507 # what would normally be inherently managed by Bazel internally. 508 # TODO: b/297413805 - Remove this implementation. 509 510 def _pw_cc_static_libs_to_link_impl(): 511 """Returns a flag_set provider that sets up static libraries to link.""" 512 return flag_set( 513 actions = [ 514 ACTION_NAMES.cpp_link_static_library, 515 ], 516 flag_groups = [ 517 flag_group( 518 expand_if_available = "libraries_to_link", 519 iterate_over = "libraries_to_link", 520 flag_groups = [ 521 flag_group( 522 expand_if_equal = variable_with_value( 523 name = "libraries_to_link.type", 524 value = "object_file", 525 ), 526 flags = ["%{libraries_to_link.name}"], 527 ), 528 flag_group( 529 expand_if_equal = variable_with_value( 530 name = "libraries_to_link.type", 531 value = "object_file_group", 532 ), 533 flags = ["%{libraries_to_link.object_files}"], 534 iterate_over = "libraries_to_link.object_files", 535 ), 536 ], 537 ), 538 ], 539 ) 540 541 pw_cc_static_libs_to_link = rule( 542 implementation = _pw_cc_static_libs_to_link_impl, 543 provides = [FlagSetInfo], 544 ) 545 546And then in the ``BUILD.bazel`` file, the rules would be used as if they 547were a ``pw_cc_flag_set``: 548 549.. code-block:: 550 551 load( 552 "@pw_toolchain//tools/llvm:llvm_ar_patch.bzl", 553 "pw_cc_static_libs_to_link" 554 ) 555 556 pw_cc_static_libs_to_link( 557 name = "static_library_action_flags", 558 ) 559 560 pw_cc_action_config( 561 name = "llvm_ar", 562 actions = ACTION_NAMES.cpp_link_static_library, 563 tools = [ 564 ":llvm_ar_tool", 565 ], 566 flag_sets = [ 567 ":static_library_action_flags", 568 ], 569 ) 570 571Introduce ``pw_cc_feature`` and ``pw_cc_feature_set`` 572===================================================== 573These types are just permutations of the ``cc_toolchain_config_lib.feature()`` 574and ``cc_toolchain_config_lib.with_feature_set()`` API. For guidance on when 575these should be used, see 576:ref:`application of feature flags <application-of-flags-feature-flags>`. 577 578.. code-block:: 579 580 pw_cc_feature_set( 581 name = "static_pie_requirements", 582 with_features = ["pie"], 583 # If this doesn't work when certain features are enabled, they should 584 # be specified as ``without_features``. 585 ) 586 587 pw_cc_feature( 588 name = "static_pie", 589 flag_sets = [ 590 "//flag_sets:static_pie", 591 ], 592 implies = ["static_link_flag"], 593 requires = [ 594 ":static_pie_requirements", 595 ], 596 ) 597 598Introduce ``pw_cc_action_config`` and ``pw_cc_tool`` 599==================================================== 600These are closely related to the ``ActionConfigInfo`` and ``ToolInfo`` 601providers, but allow additional files to be attached and a list of actions to 602be attached rather than a single action. 603 604.. code-block:: 605 606 pw_cc_tool( 607 name = "clang_tool", 608 path = "@llvm_toolchain//:bin/clang", 609 additional_files = [ 610 "@llvm_toolchain//:all", 611 ], 612 ) 613 614 pw_cc_action_config( 615 name = "clang", 616 actions = ALL_ASM_ACTIONS + ALL_C_COMPILER_ACTIONS, 617 tools = [ 618 ":clang_tool", 619 ], 620 flag_sets = [ 621 # Most flags should NOT end up here. Only unconditional flags that 622 # should ALWAYS be bound to this tool (e.g. static library 623 # workaround fix for macOS). 624 "//flag_sets:generate_depfile", 625 ], 626 ) 627 628.. _pw_cc_toolchain-toolchain-declarations: 629 630Toolchain declarations 631====================== 632In following with the other proposed rules, ``pw_cc_toolchain`` largely 633follows the API of ``cc_common.create_cc_toolchain_config_info()``. Most of the 634attributes are logically passed through, with the following exceptions: 635 636- **action_config_flag_sets**: Flag sets to apply to action configs. Since flag 637 sets are intrinsically bound to actions, there’s no need to divide them at 638 this level. 639- **additional_files**: Now that tools can spec out required files, those 640 should be propagated and mostly managed internally. The ``\*_files`` members 641 will still be available, but shouldn’t see much use. additional_files is like 642 “all_files”, but applies to all action_configs. 643 644.. code-block:: 645 646 pw_cc_toolchain( 647 name = "host_toolchain_linux", 648 abi_libc_version = "unknown", # We should consider how to move this out in the future. 649 abi_version = "unknown", 650 action_configs = [ 651 "@llvm_toolchain//tools:clang", 652 "@llvm_toolchain//tools:clang++", 653 "@llvm_toolchain//tools:lld", 654 "@llvm_toolchain//tools:llvm_ar", 655 "@llvm_toolchain//tools:llvm_cov", 656 "@llvm_toolchain//tools:llvm_strip", 657 ], 658 additional_files = ":linux_sysroot_files", 659 action_config_flag_sets = [ 660 ":linux_sysroot", 661 "@pw_toolchain//flag_collections:strict_warnings", 662 "@pw_toolchain//flag_sets:no_canonical_prefixes", 663 ], 664 features = [ 665 "@pw_toolchain//features:c++17", 666 ], 667 host_system_name = "unknown", 668 supports_param_files = 0, # Seems like this should be attached to a pw_cc_action_config... 669 target_cpu = "unknown", 670 target_libc = "unknown", 671 target_system_name = "unknown", 672 toolchain_identifier = "host-toolchain-linux", 673 cxx_builtin_include_directories = [ 674 "%package(@llvm_toolchain//)%/include/x86_64-unknown-linux-gnu/c++/v1", 675 "%package(@llvm_toolchain//)%/include/c++/v1", 676 "%package(@llvm_toolchain//)%/lib/clang/17/include", 677 "%sysroot%/usr/local/include", 678 "%sysroot%/usr/include/x86_64-linux-gnu", 679 "%sysroot%/usr/include", 680 ], 681 ) 682 683------------ 684Alternatives 685------------ 686Improve Bazel's native C/C++ toolchain rules 687============================================ 688Improving Bazel's native rules for defining C/C++ toolchains is out of the 689scope of Pigweed's work. Changing the underlying toolchain API as Bazel 690understands it is a massive undertaking from the perspective of migrating 691existing code. We hope that the custom rule effort can help guide future 692decisions when it comes to toolchain scalability and maintainability. 693 694---------- 695Next steps 696---------- 697Rust toolchain interop 698====================== 699Pigweed's Rust toolchains have some interoperability concerns and requirements. 700The extend of this needs to be thoroughly investigated as a next step to ensure 701that the Rust/C/C++ toolchain experience is relatively unified and ergonomic. 702 703More maintainable ``cxx_builtin_include_directories`` 704===================================================== 705In the future, it would be nice to have a more sharable solution for managing 706``cxx_builtin_include_directories`` on a ``pw_cc_toolchain``. This could 707plausibly be done by allowing ``pw_cc_flag_set`` to express 708``cxx_builtin_include_directories`` so they can be propagated back up to the 709``pw_cc_toolchain``. 710 711Feature name collision guidance 712=============================== 713Features support relatively complex relationships among each other, but 714traditionally rely on string names to express these relationships rather than 715labels. This introduces significant ambiguity, as it's possible for multiple 716features to use the same logical name so long as they aren't both employed in 717the same toolchain. In practice, the only way to tell what features will end up 718enabled is to manually unpack what features a toolchain pulls in, and 719cross-reference it against the output of 720`--experimental_save_feature_state <https://bazel.build/reference/command-line-reference#flag--experimental_save_feature_state>`_. 721 722One potential solution to this problem is to add a mechanism for expressing 723features as labels, which will allow relationships to be expressed more 724concretely, and help prevent unintended naming collisions. This would not 725replace the ability to express relationships with features not accessible via 726labels, but rather live alongside it. 727