Support for multiple toolchains

I have been working on an experimental CMake implementation that supports more
than one toolchain in a single configure, generate, and build operation. I would
like to get feedback on the use cases, terminology, public API, and overall
design before taking the proposal further.

The motivating case is a build that needs both host and target artifacts: for
example, a native code generator or test driver alongside firmware built with a
cross compiler, with target executables optionally run through an emulator.
These workflows currently tend to require nested CMake builds, superbuilds, or
custom external steps, which split the dependency graph.

The proposal keeps CMake’s traditional unnamed build toolchain and adds named
toolchains. At a high level it provides:

  • declaration of named toolchains from CMake code, the command line, or
    configure presets;
  • independent compiler, platform, language, cache, and detection state for each
    toolchain;
  • TOOLCHAINS on executable and library declarations to instantiate one
    logical target for several toolchains;
  • add_subdirectory(... TOOLCHAIN <name>) to place an existing subtree in a
    toolchain context;
  • contextual target and dependency lookup, with
    <toolchain>/<target> addressing in generator expressions;
  • native host-tool selection and per-toolchain emulator handling for custom
    commands, tests, and try_run();
  • toolchain-aware probes, package searches, FetchContent, installation, and
    export; and
  • file API, preset, and compilation-database integration.

The feature is experimental and explicitly gated, so existing projects retain
their current single-toolchain behavior when it is disabled. The current
implementation supports Ninja, Ninja Multi-Config, and Unix Makefiles. It does
not attempt to support cross-toolchain binary linking, independent configuration
sets per toolchain, arbitrary project-variable virtualization, or a new
multi-variant package format.

The design is split into three documents:

a complete example:

and a GitLab issue is here for additional detail and feedback:

I would particularly welcome feedback from projects that currently coordinate
host tools and cross-compiled targets, or that build the same library for
several compilers or platforms. Are the proposed identities, directory binding,
target-instantiation, lookup, and cache-isolation rules understandable? Which
missing use cases or integration points would be most important to address?

The initial prototype implementation is designed for typical cross-compiling
scenarios such as ARM Cortex-M firmware development and testing. However,
future work could include other languages and scenarios such as SPIRV, Rust,
and other languages.