diff options
Diffstat (limited to 'seed/0113-bazel-cc-toolchain-api.rst')
-rw-r--r-- | seed/0113-bazel-cc-toolchain-api.rst | 724 |
1 files changed, 724 insertions, 0 deletions
diff --git a/seed/0113-bazel-cc-toolchain-api.rst b/seed/0113-bazel-cc-toolchain-api.rst new file mode 100644 index 000000000..758e32350 --- /dev/null +++ b/seed/0113-bazel-cc-toolchain-api.rst @@ -0,0 +1,724 @@ +.. _seed-0113: + +=========================================== +0113: Add modular Bazel C/C++ toolchain API +=========================================== +.. seed:: + :number: 0113 + :name: Add modular Bazel C/C++ toolchain API + :status: Accepted + :proposal_date: 2023-09-28 + :cl: 173453 + +------- +Summary +------- +This SEED proposes custom Starlark rules for declaring C/C++ toolchains in +Bazel, and scalable patterns for sharing modular components of C/C++ toolchain +definitions. + +---------- +Motivation +---------- +There is a lot of boilerplate involved in standing up a Bazel C/C++ toolchain. +While a good portion of the verbosity of specifying a new toolchain is +important, necessary machinery, nearly as much suffers from one or more of the +following problems: + +- **Underdocumented patterns**: The + `create_cc_toolchain_config_info() <https://bazel.build/rules/lib/toplevel/cc_common#create_cc_toolchain_config_info>`_ + method has an attribute called ``target_cpu`` that doesn't have an associated + list of expected values, which suggests the argument is for bookkeeping + purposes and doesn't affect Bazel behavior. The reality is this argument + *does* have expected values that change behavior, but these are undocumented + (see `this GitHub issue <https://github.com/bazelbuild/bazel/issues/19353>`_ + for more information). + +- **Not inherently modular**: Bazel expects the overwhelming majority of a + C/C++ toolchain to be specified as part of a call to + ``create_cc_toolchain_config_info()``. Because this is a Starlark method, + there's a lot of flexibility with how you construct a toolchain config, but + very little by way of existing patterns for creating something that is + testable, sharable, or in other ways modular. The existing + `tutorial for creating a C/C++ toolchain <https://bazel.build/tutorials/ccp-toolchain-config#configuring_the_c_toolchain>`_ + illustrates expanding out the toolchain definition as a no-argument Starlark + rule. + +As Pigweed fully embraces multi-platform builds, it is critical for both +Pigweed and users of Pigweed that it is easy to stand up custom toolchain +definitions that work for the relevant hardware project-specific code/libraries. + +This SEED seeks to address the shortcomings in Bazel C/C++ toolchain +declaration by establishing patterns and providing custom build rules that +are owned and maintained by Pigweed. + +-------- +Proposal +-------- +1. Introduce rules for defining C/C++ toolchains +================================================ +In an effort to improve the experience of defining a C/C++ toolchain, Pigweed +will introduce new Bazel rules that allow toolchains to share common boilerplate +without hindering power-user functionality. + +While this work centers around an improved experience for defining a toolchain +via ``create_cc_toolchain_config_info()``, other build rules will be introduced +for closely related aspects of the toolchain definition process. + +An example of what these rules would look like in practice is as follows: + +.. code-block:: + + # A tool that can be used by various build actions. + pw_cc_tool( + name = "clang_tool", + path = "@cipd_llvm_toolchain//:bin/clang", + additional_files = [ + "@cipd_llvm_toolchain//:all", + ], + ) + + # A mapping of a tool to actions, with flag sets that define behaviors. + pw_cc_action_config( + name = "clang", + actions = ALL_ASM_ACTIONS + ALL_C_COMPILER_ACTIONS, + tools = [ + ":clang_tool", + ], + flag_sets = [ + # Most flags should NOT end up here. Only unconditional flags that + # should ALWAYS be bound to this tool (e.g. static library + # workaround fix for macOS). + "@pw_toolchain//flag_sets:generate_depfile", + ], + ) + + # A trivial flag to be consumed by a C/C++ toolchain. + pw_cc_flag_set( + name = "werror", + actions = ALL_COMPILE_ACTIONS, + flags = [ + "-Werror", + ], + ) + + # A list of flags that can be added to a toolchain configuration. + pw_cc_flag_set( + name = "user_compile_options", + actions = ALL_COMPILE_ACTIONS, + flag_groups = [ + ":user_compile_options_flags", + ] + ) + + # A more complex compiler flag that requires template expansion. + pw_cc_flag_group( + name = "user_compile_options_flags", + flags = ["%{user_compile_flags}"], + iterate_over = "user_compile_flags", + expand_if_available = "user_compile_flags", + ) + + # The underlying definition of a complete C/C++ toolchain. + pw_cc_toolchain( + name = "host_toolchain_linux", + action_configs = [ + ":clang", + ":clang++", + # ... + ], + additional_files = ":linux_sysroot_files", + action_config_flag_sets = [ + "@pw_toolchain//flag_sets:no_canonical_prefixes", + ":user_compile_options", + ":werror", + ], + features = [ + "@pw_toolchain//features:c++17", + ], + target_cpu = "x86_64", + target_system_name = "x86_64-unknown-linux-gnu", + toolchain_identifier = "host-toolchain-linux", + ) + + # Toolchain resolution parameters for the above C/C++ toolchain. + toolchain( + name = "host_cc_toolchain_linux", + exec_compatible_with = [ + "@platforms//os:linux", + ], + target_compatible_with = [ + "@platforms//os:linux", + ], + toolchain = ":host_toolchain_linux", + toolchain_type = "@bazel_tools//tools/cpp:toolchain_type", + ) + +2. Provide standard toolchain building-blocks +============================================= +Pigweed will build out a repository of sharable instantiations of the +aforementioned custom rules to give projects the resources they need to quickly +and easily assemble toolchains for desktop and embedded targets. This includes, +but is not limited to: + +- Rules that define tool sets for common toolchains (LLVM/clang, GNU/gcc). +- Fully specified, modular + `features <https://bazel.build/docs/cc-toolchain-config-reference#features>`_. +- Common flag sets that users may want to apply directly to their toolchains. + (enabling/disabling warnings, C++ standard version, etc.) +- Platform/architecture support rules, including host OS SDK integrations + (Xcode, Windows SDK) and architecture-specific flag sets. + +These components will help establish patterns that will make it significantly +easier for Pigweed users (and Bazel users at large) to define their own +toolchains. + +--------------------- +Problem investigation +--------------------- +This section explores previous work, and details why existing solutions don't +meet Pigweed's needs. + +bazelembedded/rules_cc_toolchain +================================ +The `rules_cc_toolchain <https://github.com/bazelembedded/rules_cc_toolchain>`_ +as part of the larger bazelembedded suite was actually the initial foundation +of Pigweed's Bazel build. While this served as a very good initial foundation, +it didn't provide the flexibility needed to easily stand up additional +toolchains in ways that gave downstream projects sufficient control over the +flags, libraries, tools, and sysroot. + +To work around the limited configurability of toolchain flags, Pigweed employed +the following workarounds: + +#. Place ``copts`` and ``linkopts`` in ``.bazelrc``: This was problematic + because ``.bazelrc`` is not intrinsically shared with or propagated to + downstream users of Pigweed. Also, flags here are unilaterally applied + without OS-specific considerations. +#. Attach flags to build targets with custom wrappers: This approach + intrinsically requires the existence of the ``pw_cc_library``, which + introduces difficulty around consistent interoperability with other Bazel + projects (among other issues detailed in + `b/267498492 <https://issues.pigweed.dev/issues/267498492>`_). + +Some other issues encountered when working with this solution include: + +- These rules intended to be modular, but in practice were relatively tightly + coupled. +- Transitive dependencies throughout the toolchain definition process resulted + in some hard-to-debug issues (see + `this pull request <https://github.com/bazelembedded/rules_cc_toolchain/pull/39>`_ + and `b/254518544 <https://issues.pigweed.dev/issues/254518544>`_. + +bazelembedded/modular_cc_toolchains +=================================== +The `modular_cc_toolchains <https://github.com/bazelembedded/modular_cc_toolchains>`_ +repository is a new attempt as part of the bazelembedded suite at providing +truly modular toolchain rules. The proposed direction is much more in-line +with the needs of Pigweed, but at the moment the repository exists as an +initial draft of ideas rather than a complete implementation. + +This repository greatly inspired Pigweed's initial prototype for modular +toolchains, but diverges significantly from the underlying Bazel C/C++ +toolchain building-blocks. If this work was already complete and +well-established, it probably would have satisfied some of Pigweed's key needs. + +lowRISC/crt +=========== +The `compiler repository toolkit <https://github.com/lowRISC/crt>`_ is another +scalable approach at toolchains. This repository strives to be an all-in-one +repository for embedded toolchains, and does a very good job at providing +scalable models for establishing toolchains. This repository is relatively +monolithic, though, and doesn't necessarily address the concern of quickly +and easily standing up custom toolchains. Instead, it's more suited towards +contributing new one-size-fits-all toolchains to ``crt`` directly. + +Android's toolchain +=================== +Android's Bazel-based build has invested heavily in toolchains, but they're +very tightly coupled to the use cases of Android. For example, +`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. +These toolchains scale for the purpose of Android, but unfortunately are +inherently not modular or reusable outside of that context. + +Due to the sheer amount of investment in these toolchains, though, they serve +as a good reference for building out a complete toolchain in Bazel. + +Pigweed's modular Bazel toolchain prototype +=========================================== +As part of an exploratory phase of getting toolchains set up for Linux and +macOS, +`an initial prototype <https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/157634>`_ +for modular Bazel toolchains was drafted and deployed to Pigweed. This work +introduced two key build rules: ``pw_cc_toolchain_feature`` and +``pw_cc_toolchain``. With both of these rules, it’s possible to instantiate a +vast array of toolchain variants without writing a single line of Starlark. A +few examples of these building blocks in action are provided below. + +.. code-block:: + + # pw_cc_toolchain example taken from https://cs.opensource.google/pigweed/pigweed/+/main:pw_toolchain/host_clang/BUILD.bazel;l=113-143;drc=7df1768d915fe11dae05751f70f143e60acfb17a. + + pw_cc_toolchain( + name = "host_toolchain_linux", + abi_libc_version = "unknown", + abi_version = "unknown", + all_files = ":all_linux_files", + ar = "@llvm_toolchain//:bin/llvm-ar", + + # TODO: b/305737273 - Globbing all files for every action has a + # performance hit, make these more granular. + ar_files = ":all_linux_files", + as_files = ":all_linux_files", + compiler = "unknown", + compiler_files = ":all_linux_files", + coverage_files = ":all_linux_files", + cpp = "@llvm_toolchain//:bin/clang++", + dwp_files = ":all_linux_files", + feature_deps = [ + ":linux_sysroot", + "@pw_toolchain//features:no_canonical_prefixes", + ], + gcc = "@llvm_toolchain//:bin/clang", + gcov = "@llvm_toolchain//:bin/llvm-cov", + host_system_name = "unknown", + ld = "@llvm_toolchain//:bin/clang++", + linker_files = ":all_linux_files", + objcopy_files = ":all_linux_files", + strip = "@llvm_toolchain//:bin/llvm-strip", + strip_files = ":all_linux_files", + supports_param_files = 0, + target_cpu = "unknown", + target_libc = "unknown", + target_system_name = "unknown", + toolchain_identifier = "host-toolchain-linux", + ) + + # 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. + + # Disables linking of the default C++ standard library to allow linking of a + # different version. + pw_cc_toolchain_feature( + name = "no_default_cpp_stdlib", + linkopts = ["-nostdlib++"], + ) + + # Prevent relative paths from being converted to absolute paths. + # Note: This initial prototype made this a feature, but it should instead + # exist as a flag_set. + pw_cc_toolchain_feature( + name = "no_canonical_prefixes", + copts = [ + "-no-canonical-prefixes", + ], + ) + +What’s worth noting is that the ``pw_cc_toolchain_feature`` build rule looks +very similar to a GN ``config``. This was no mistake, and was an attempt to +substantially reduce the boiler plate for creating new sharable compiler flag +groups. + +Unfortunately, it quickly became apparent that this approach limited control +over the underlying toolchain definition creation process. In order to support +``always_link`` on macOS, a custom logic and flags had to be directly baked into +the rule used to declare toolchains +(`relevant change <https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/168614/17/pw_toolchain_bazel/cc_toolchain/private/cc_toolchain.bzl>`_). +While workarounds like this should be possible, the fact that this had to be +upstreamed internally to ``pw_cc_toolchain`` exposed limitations in the +abstraction patterns that were established. Such limitations could preclude +some project from using ``pw_cc_toolchain`` at all. + +--------------- +Detailed design +--------------- +The core design proposal is to transform the providers used by +``cc_common.create_cc_toolchain_config_info()`` into build rules. The approach +has been prototyped +`here <https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/168351/1>`_, +and retains API compatibility with the initial prototype as a proof-of-concept. + +One core pattern established by this design is transforming content that would +typically live as Starlark to instead live in build files. This is done to +make it easier to read and reference existing work. + +Implementation requirements +=========================== +Compatibility with native C/C++ rules +------------------------------------- +The core of Pigweed's toolchain build rules will rely on the providers +defined as part of Bazel's +`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 +existing work that directly uses these toolchain primitives. It also provides +a clear path for migrating existing toolchains piece-by-piece (which may be +written completely in Starlark). + +Any extensions beyond the existing providers (e.g. specifying +``additional_files`` on a ``pw_cc_tool``) must happen parallel to existing +providers so that rules that consume the ``cc_toolchain_config_lib`` providers +can work with vanilla providers. + +Compatibility with Bazel rules ecosystem +---------------------------------------- +In following with the larger Bazel rules ecosystem, the toolchain building +blocks will be designed such that they can be used independently from Pigweed. +This allows this work to be used for non-embedded projects, and reduces the +overhead for standing up a custom Bazel C/C++ toolchain in any arbitrary +project. + +Initially, the work will live as ``pw_toolchain_bazel`` in the main Pigweed +repository to facilitate testing. This module must not depend on any other +aspects of Pigweed. As the toolchain rules mature, they will eventually be +available as a separate repository to match the modularity patterns used by +the larger Bazel rules ecosystem. + +Introduce ``pw_cc_flag_set`` and ``pw_cc_flag_group`` +===================================================== +The majority of build flags would be expressed as ``pw_cc_flag_set`` and +``pw_cc_flag_group`` pairs. + +.. code-block:: + + # A simple flag_set with a single flag. + pw_cc_flag_set( + name = "werror", + # Only applies to C/C++ compile actions (i.e. no assemble/link/ar). + actions = ALL_CPP_COMPILER_ACTIONS + ALL_C_COMPILER_ACTIONS, + flags = [ + "-Werror", + ], + ) + + # A flag_group that potentially expands to multiple flags. + pw_cc_flag_group( + name = "user_compile_options_flags", + flags = ["%{user_compile_flags}"], + iterate_over = "user_compile_flags", + expand_if_available = "user_compile_flags", + ) + + # A flag_set that relies on a non-trivial or non-constant expression of + # flags. + pw_cc_flag_set( + name = "user_compile_options", + actions = ALL_COMPILE_ACTIONS, + flag_groups = [ + ":user_compile_options_flags", + ] + ) + +These closely mimic the API of ``cc_toolchain_config_lib.flag_set()`` and +``cc_toolchain_config_lib.flag_group()``, with the following exceptions: + +**pw_cc_flag_set** + +*Added* + +- ``flags`` (added): Express a constant, trivial list of flags. If this is + specified, ``flag_groups`` may not be specified. This eliminates the need + for specifying a corresponding ``pw_cc_flag_group`` for every + ``pw_cc_flag_set`` for most flags. + +**pw_cc_flag_group** + +*Removed* + +- ``expand_if_true``\, ``expand_if_false``\, ``expand_if_equal``\: More complex + rules that rely on these should live as custom Starlark rules that provide a + ``FlagGroupInfo``\, or ``FlagSetInfo`` (depending on which is more ergonomic + to express the intent). See :ref:`pw_cc_flag_set-exceptions` below for an + example that illustrates how express more complex ``flag_group``\s that rely + on these attributes. + +Application of flags +-------------------- +Flags can be applied to a toolchain in three ways. This section attempts to +provide initial guidance for where flags should be applied, though it's likely +better practices will evolve as this work sees more use. For the latest +guidance, please consult the official documentation when it rolls out to +``pw_toolchain_bazel``. + +Flags unconditionally applied to a toolchain +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The majority of flags fall into this category. Architecture flags, +globally-applied warnings, global defines, and other similar flags should be +applied in the ``action_config_flag_sets`` attribute of a ``pw_cc_toolchain`` +(see :ref:`pw_cc_toolchain-toolchain-declarations` for more information). Each +``pw_cc_flag_set`` (or other rule that provides a ``FlagSetInfo`` provider) +listed in ``action_config_flag_sets`` is unconditionally applied to every tool +that matches the ``actions`` listed in the flag set. + +.. _application-of-flags-feature-flags: + +Feature flags +~~~~~~~~~~~~~ +Flag sets applied as features may or may not be enabled even if they are listed +in the ``features`` attribute of a ``pw_cc_toolchain``. The +`official Bazel documentation on features <https://bazel.build/docs/cc-toolchain-config-reference#features>`_ +provides some good guidance on when features should be employed. To summarize, +features should be used when either they should be controllable by users +invoking the build, or if they affect build behavior beyond simply +adding/removing flags (e.g. by introducing additional build actions). + +Flags unconditionally applied to a tool +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +These flags are flags that are bound to a particular tool. These are not +expressed as part of a ``pw_cc_toolchain``, and are instead bound to a +``pw_cc_action_config``. This means that the flag set is unconditionally +applied to every user of that action config. These kinds of flag applications +should be reserved for flags required to assemble a working set of tools (such +as generating a depfile, or adding support for static library link handling +:ref:`as illustrated below <pw_cc_flag_set-exceptions>`). + +Flag application order +~~~~~~~~~~~~~~~~~~~~~~ +When invoking the underlying tools, the intended order of flags is as follows: + +#. Flags listed in the ``flag_sets`` list of a ``pw_cc_action_config``. +#. Flags listed in ``action_config_flag_sets`` of a ``pw_cc_toolchain``. +#. Flags listed in ``features`` of a ``pw_cc_toolchain``. + +These lists are intended to be sensitive to ordering, earlier items in the lists +should appear in the final tool invocation flags before later items in the list. + +As transitive dependencies between features/flags are not supported as part of +this proposal, exact traversal of transitive flag dependencies will be left +to be decided if/when that feature is introduced. This proposal suggests +postorder handling of flags as the most intuitive order. + +.. _pw_cc_flag_set-exceptions: + +Exceptions +---------- +Some flags are too complex to be nicely expressed in a Bazel build file. These +flag sets or flag groups will need to be expressed in Starlark as custom rules. +Fortunately, this will interop well with simpler flag sets since the underlying +providers are all the same. + +**Example** + +In a Starlark file (e.g. ``//tools/llvm/llvm_ar_patch.bzl``), the required +``flag_set`` can be defined: + +.. code-block:: + + # Starlark rules in a .bzl file for a relatively complicated workaround for + # what would normally be inherently managed by Bazel internally. + # TODO: b/297413805 - Remove this implementation. + + def _pw_cc_static_libs_to_link_impl(): + """Returns a flag_set provider that sets up static libraries to link.""" + return flag_set( + actions = [ + ACTION_NAMES.cpp_link_static_library, + ], + flag_groups = [ + flag_group( + expand_if_available = "libraries_to_link", + iterate_over = "libraries_to_link", + flag_groups = [ + flag_group( + expand_if_equal = variable_with_value( + name = "libraries_to_link.type", + value = "object_file", + ), + flags = ["%{libraries_to_link.name}"], + ), + flag_group( + expand_if_equal = variable_with_value( + name = "libraries_to_link.type", + value = "object_file_group", + ), + flags = ["%{libraries_to_link.object_files}"], + iterate_over = "libraries_to_link.object_files", + ), + ], + ), + ], + ) + + pw_cc_static_libs_to_link = rule( + implementation = _pw_cc_static_libs_to_link_impl, + provides = [FlagSetInfo], + ) + +And then in the ``BUILD.bazel`` file, the rules would be used as if they +were a ``pw_cc_flag_set``: + +.. code-block:: + + load( + "@pw_toolchain//tools/llvm:llvm_ar_patch.bzl", + "pw_cc_static_libs_to_link" + ) + + pw_cc_static_libs_to_link( + name = "static_library_action_flags", + ) + + pw_cc_action_config( + name = "llvm_ar", + actions = ACTION_NAMES.cpp_link_static_library, + tools = [ + ":llvm_ar_tool", + ], + flag_sets = [ + ":static_library_action_flags", + ], + ) + +Introduce ``pw_cc_feature`` and ``pw_cc_feature_set`` +===================================================== +These types are just permutations of the ``cc_toolchain_config_lib.feature()`` +and ``cc_toolchain_config_lib.with_feature_set()`` API. For guidance on when +these should be used, see +:ref:`application of feature flags <application-of-flags-feature-flags>`. + +.. code-block:: + + pw_cc_feature_set( + name = "static_pie_requirements", + with_features = ["pie"], + # If this doesn't work when certain features are enabled, they should + # be specified as ``without_features``. + ) + + pw_cc_feature( + name = "static_pie", + flag_sets = [ + "//flag_sets:static_pie", + ], + implies = ["static_link_flag"], + requires = [ + ":static_pie_requirements", + ], + ) + +Introduce ``pw_cc_action_config`` and ``pw_cc_tool`` +==================================================== +These are closely related to the ``ActionConfigInfo`` and ``ToolInfo`` +providers, but allow additional files to be attached and a list of actions to +be attached rather than a single action. + +.. code-block:: + + pw_cc_tool( + name = "clang_tool", + path = "@llvm_toolchain//:bin/clang", + additional_files = [ + "@llvm_toolchain//:all", + ], + ) + + pw_cc_action_config( + name = "clang", + actions = ALL_ASM_ACTIONS + ALL_C_COMPILER_ACTIONS, + tools = [ + ":clang_tool", + ], + flag_sets = [ + # Most flags should NOT end up here. Only unconditional flags that + # should ALWAYS be bound to this tool (e.g. static library + # workaround fix for macOS). + "//flag_sets:generate_depfile", + ], + ) + +.. _pw_cc_toolchain-toolchain-declarations: + +Toolchain declarations +====================== +In following with the other proposed rules, ``pw_cc_toolchain`` largely +follows the API of ``cc_common.create_cc_toolchain_config_info()``. Most of the +attributes are logically passed through, with the following exceptions: + +- **action_config_flag_sets**: Flag sets to apply to action configs. Since flag + sets are intrinsically bound to actions, there’s no need to divide them at + this level. +- **additional_files**: Now that tools can spec out required files, those + should be propagated and mostly managed internally. The ``\*_files`` members + will still be available, but shouldn’t see much use. additional_files is like + “all_files”, but applies to all action_configs. + +.. code-block:: + + pw_cc_toolchain( + name = "host_toolchain_linux", + abi_libc_version = "unknown", # We should consider how to move this out in the future. + abi_version = "unknown", + action_configs = [ + "@llvm_toolchain//tools:clang", + "@llvm_toolchain//tools:clang++", + "@llvm_toolchain//tools:lld", + "@llvm_toolchain//tools:llvm_ar", + "@llvm_toolchain//tools:llvm_cov", + "@llvm_toolchain//tools:llvm_strip", + ], + additional_files = ":linux_sysroot_files", + action_config_flag_sets = [ + ":linux_sysroot", + "@pw_toolchain//flag_collections:strict_warnings", + "@pw_toolchain//flag_sets:no_canonical_prefixes", + ], + features = [ + "@pw_toolchain//features:c++17", + ], + host_system_name = "unknown", + supports_param_files = 0, # Seems like this should be attached to a pw_cc_action_config... + target_cpu = "unknown", + target_libc = "unknown", + target_system_name = "unknown", + toolchain_identifier = "host-toolchain-linux", + cxx_builtin_include_directories = [ + "%package(@llvm_toolchain//)%/include/x86_64-unknown-linux-gnu/c++/v1", + "%package(@llvm_toolchain//)%/include/c++/v1", + "%package(@llvm_toolchain//)%/lib/clang/17/include", + "%sysroot%/usr/local/include", + "%sysroot%/usr/include/x86_64-linux-gnu", + "%sysroot%/usr/include", + ], + ) + +------------ +Alternatives +------------ +Improve Bazel's native C/C++ toolchain rules +============================================ +Improving Bazel's native rules for defining C/C++ toolchains is out of the +scope of Pigweed's work. Changing the underlying toolchain API as Bazel +understands it is a massive undertaking from the perspective of migrating +existing code. We hope that the custom rule effort can help guide future +decisions when it comes to toolchain scalability and maintainability. + +---------- +Next steps +---------- +Rust toolchain interop +====================== +Pigweed's Rust toolchains have some interoperability concerns and requirements. +The extend of this needs to be thoroughly investigated as a next step to ensure +that the Rust/C/C++ toolchain experience is relatively unified and ergonomic. + +More maintainable ``cxx_builtin_include_directories`` +===================================================== +In the future, it would be nice to have a more sharable solution for managing +``cxx_builtin_include_directories`` on a ``pw_cc_toolchain``. This could +plausibly be done by allowing ``pw_cc_flag_set`` to express +``cxx_builtin_include_directories`` so they can be propagated back up to the +``pw_cc_toolchain``. + +Feature name collision guidance +=============================== +Features support relatively complex relationships among each other, but +traditionally rely on string names to express these relationships rather than +labels. This introduces significant ambiguity, as it's possible for multiple +features to use the same logical name so long as they aren't both employed in +the same toolchain. In practice, the only way to tell what features will end up +enabled is to manually unpack what features a toolchain pulls in, and +cross-reference it against the output of +`--experimental_save_feature_state <https://bazel.build/reference/command-line-reference#flag--experimental_save_feature_state>`_. + +One potential solution to this problem is to add a mechanism for expressing +features as labels, which will allow relationships to be expressed more +concretely, and help prevent unintended naming collisions. This would not +replace the ability to express relationships with features not accessible via +labels, but rather live alongside it. |