bazel: incompatible_enable_cc_toolchain_resolution: Turn on toolchain resolution for cc rules

Flag: --incompatible_enable_cc_toolchain_resolution Available since: 0.23 Will be flipped in: 7.0.0

Description

C++ toolchain resolution is an improved mechanism that selects a proper C++ toolchain (compiler) based on a pair of target and execution platforms (think cross compilation from linux to mac). It’s an improvement over the old mechanism that sets the --crosstool_top flag. More information about platforms and toolchain resolution on https://bazel.build/reference/be/platforms-and-toolchains

Current status

  • C++ toolchain resolution has been in use at large repository at Google for a year without significant problems.
  • rules_apple and rules_swift lack toolchainization, however they work using platform_mapping
  • Bazel’s C++ toolchain autoconfiguration already supports toolchain resolution.

Migration

If you’re not using C++, or custom --crosstool_top, --cpu, or --compiler, you don’t use select on these options, you can stop reading now, there is nothing to migrate for you.

Migration before the flag is flipped (only in case you’re building for custom platforms, using custom C++ toolchains or using custom rules invoking cc_common.compile and cc_common.link):

  1. Add C++ platform definitions, register C++ toolchains
  2. Add missing C++ toolchain requirements to rules (Already added to OSS rules)
  3. Update blazerc configuration to use custom platforms
  4. Update Starlark configuration transitions to use platforms (ones affecting --cpu and --crostool_top, in cases platform_mappings isn’t used)
  5. Update or fix configurations (bazelrc) to use --platforms (where --cpu or --crosstool_top is used)

Migration after the flag is flipped:

  1. Replace cpu and os based selects with platform based selects (for example selects cc_target_os, target_cpu and other)
  2. Remove --crosstool_top, --cpu flags from bazelrcs and from Starlark configuration transitions
  3. Remove part of platform_mappings configuration needed for C++
  4. Remove _cc_toolchain implicit dependency

Additional details

1. Add C++ platform definitions, register C++ toolchains

Please use constraint_settings and constraint_values from the canonical Bazel Platforms Repository (don’t hesitate to propose missing targets!). If there is a need for C++ specific constraints, feel free to upload a PR to the rules_cc repository. It is extremely important that the whole ecosystem uses the same constraints, we can only reuse libraries and toolchains when we speak the same language.

2. Add missing C++ toolchain requirements to rules

For Starlark rules owners who depend on C++ toolchain it will be necessary to declare dependency on C++ toolchain type.

Before:

foo = rule(
    implementation = _foo_impl,
    attrs = {
        "_cc_toolchain": attr.label(default = Label("@bazel_tools//tools/cpp:current_cc_toolchain")),
    },
)

After:

foo = rule(
    implementation = _foo_impl,
    attrs = {
        "_cc_toolchain": attr.label(default = Label("@bazel_tools//tools/cpp:current_cc_toolchain")),
    },
    toolchains = use_cpp_toolchain(),
  )

See the docs and use @rules_cc//cc:find_cc_toolchain.bzl (if using Bazel >= 0.27) or @bazel_tools//tools/cpp:toolchain_utils.bzl to locate current C++ toolchain (otherwise). Also see examples for general usage.

About this issue

  • Original URL
  • State: open
  • Created 5 years ago
  • Reactions: 2
  • Comments: 66 (55 by maintainers)

Commits related to this issue

Most upvoted comments

The best approach would be to continue to use the --compiler flag, with the new target_settings attribute on the toolchain rule, like this:

config_setting(
    name = "is_msvc",
    values = {"compiler": "msvc"},
)
config_setting(
    name = "is_clang",
    values = {"compiler": "clang"},
)
config_setting(
    name = "is_gcc",
    values = {"compiler": "gcc"},
)

toolchain(
    name = "msvc_toolchain",
    toolchain = "msvc_cc_toolchain",
    toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
    exec_compatible_with = ...,
    target_compatible_with = ....,
    target_settings = [":is_msvc"],
)
toolchain(
    name = "clang_toolchain",
    toolchain = "clang_cc_toolchain",
    toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
    exec_compatible_with = ...,
    target_compatible_with = ....,
    target_settings = [":is_clang"],
)
toolchain(
    name = "gcc_toolchain",
    toolchain = "gcc_cc_toolchain",
    toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
    exec_compatible_with = ...,
    target_compatible_with = ....,
    target_settings = [":is_gcc"],
)
toolchain(
    name = "default_toolchain",
    toolchain = "clang_cc_toolchain", # Or whichever is the default
    toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
    exec_compatible_with = ...,
    target_compatible_with = ....,
    # No target_settings present
)

This will allow you to pass --compiler=msvc to select the msvc toolchain, etc, while still respecting your other constraints for the execution and target platform.

Hi all, confirming if we still plan to flip this flag in 7.0?

The rules_foreign_cc breakage is due to the rules_android_ndk breakage as it is just one of the examples that use rules_android_ndk that is broken.

No, we don’t have any plans to fix this short of enabling toolchain resolution and removing the legacy support. You can file a feature request for this and the C++ team can prioritize it, if you’d like.

@katre in https://github.com/bazelbuild/bazel/issues/7260#issuecomment-813381150 you wrote about using target_settings to select the right compiler. How would this work when different compilers should be used on the host/exec and target platform?

Example:

  • Host and target platform constraints are for both @platforms//cpu:x86_64 and @platforms//os:linux
  • For the exec/host platform gcc compiler should be used
  • For the target platform clang should be used

You said you provided your own toolchains? Try using --toolchain_resolution_debug to see what toolchains are being considered and why they aren’t being used.

Thanks @hlopko for the precision. Managed to turn on the incompatible_enable_cc_toolchain_resolution flag and have everything compiling without any issues (given I have a platform_mappings file).

Hello everyone. I’ve observed the toolchain resolution mechanism ignores the --platforms and --host_platform command line options. The case is the following: I wish to select MSVC or clang-cl on Windows from the command line. I’ve defined two platforms in my BUILD:

platform(
    name = "x64_windows-clang-cl",
    constraint_values = [
        "@platforms//cpu:x86_64",
        "@platforms//os:windows",
        "@bazel_tools//tools/cpp:clang-cl",
    ],
)

platform(
    name = "x64_windows-msvc",
    constraint_values = [
        "@platforms//cpu:x86_64",
        "@platforms//os:windows",
        "@bazel_tools//tools/cpp:msvc",
    ],
)

And registered both in WORKSPACE:

register_execution_platforms(
    ":x64_windows-msvc",
    ":x64_windows-clang-cl",
)

register_toolchains(
    "@local_config_cc//:cc-toolchain-x64_windows-clang-cl",
)

The order in register_execution_platforms does matter: Bazel just takes the first and looks for a toolchain that satisfies all the constraints defined by the platform. If there is a such toolchain, Bazel just uses it. And If I wish to use the second one platform and do:

$ bazel build ... --incompatible_enable_cc_toolchain_resolution --host_platform=//:x64_windows-clang-cl --platforms=//:x64_windows-clang-cl

Bazel just ignores it and still uses x64_windows-msvc as the execution platform.

Maybe it is because the toolchain resolution depends on execution platform, not on a host or target one while the --host_platform and '–platforms` command line options are for host and target platforms respectively.

Now I see only one workaround: not to register execution platforms in WORKSPACE but to use --extra_execution_platforms option and when one wish to set a config_setting for the platform, the --platform option should also been used.

Should I open a new issue about this?

SGTM. As long as the code path is being tested regularly to prevent rot, I am fine with this.

Yay for surprises 😃 So the osx C++ toolchain doesn’t yet work with platforms because of this TODO. @katre kindly volunteered to fix it 😃