Hi Gregg,
The basic principle behind them is completely generic: for any (and all) languages in your build, you're targeting one or more platforms for that build. Every language can support a set of toolchains that tell that language where to find its compilers, etc. to for whatever platforms the language supports. Rule sets that want to support all this must define a set of toolchains and register them in a WORKSPACE.
When you start your build,
toolchain resolution looks at the platform you're targeting, looks at the registered toolchains, then feeds the right toolchain into each rule that's appropriate that platform. The toolchain is available to the rule as a
provider. The exact structure of that provider is language-specific, so rule authors are free to use whatever structure fits their particular compilers, compiler flags, etc.
The incentive for rule authors to opt into this process by declaring & registering toolchains is they get to plug into a standardized, cross-language, cross-platform API, and don't have to write custom logic for figuring out which toolchain to use or require special flags like --use_compiler_x or --cpu_for_language_y. This is a much better outcome then having separate ad hoc logic for each language.
But this is
evolving work. The C++ rules predate this work, so they're a prominent counter-example of everything described above: they use special flags like --crosstool_top or --compiler that don't really translate to other languages and have custom rules like
cc_toolchain and
cc_toolchain suite that manually apply the toolchain selection logic that's automated above.
Because of all this, C++ is in the process of being converted to the generic toolchain model (which is an exciting change). This is already available in experimental form, but last I understood there are a few more final pieces required to make it work universally. You can follow the progress at
https://github.com/bazelbuild/bazel/issues/6516.
CROSSTOOL is, and will remain, C++'s own supporting data structure for figuring out what command lines compile and link C++ code. As mentioned above, toolchains are just providers and each language gets to structure its provider however serves that language best. So CROSSTOOL is where most of the C++-specific logic goes. Since C++ predates platforms/toolchains, its platform/toolchain provider wraps CROSSTOOL and is defined
natively instead of in Starlark like for other rules. Its
toolchain_type is
@bazel_tools/tools/cpp:toolchain_type.
As for your second question: if you have extra code the selects (with
select()?) on --cpu, etc., then at some point yes it will be worth converting to platforms. But since full C++ support isn't there yet it may not be possible now.
This document describes plans for keeping backwards compatibility, so --cpu will just be an alias for the right platform when platforms are fully enabled. Once that happens it'll be high time to do a full migration.