Using multiple toolchains in the same project?

I’m looking at adding proper support for WebAssembly to the CMake build files for a project (Halide) and am a little unclear as to whether there is a simple way to make this happen. Here’s the problem:

  • Halide is, itself, a cross-compiler; any instance of libHalide can generate object code for any of the supported targets for which it is configured.

  • For performance reasons, it’s extremely desirable that libHalide be compiled to the native ‘host’ configuration, so on (say) x64-Linux, we always produce with x86-64 object code.

  • When we cross-compile to WebAssembly, the process gets complicated, because some (but not all) parts of our project (and test suite) now need to be compiled into WebAssembly (.wasm) files, and executed via an external tool (e.g. node.js).

My past experimentation with crosscompiling things in CMake seemed to indicate it was largely all-or-nothing, done via specifying a CMAKE_TOOLCHAIN_FILE at the toplevel. As mentioned above, though, this isn’t helpful for our problem (we need to be able to specify on a per-library/per-executable basis, potentially).

(Up to now, we have only supported our WebAssembly build-and-test setup via Make and Blaze/Bazel; in the former, everything must be done explicitly, which gives us lots of flexibility but little portability; in the latter, there is a clear distinction between the ‘host target’ vs the ‘desired target’ that makes this easy to achieve.)

Has anyone else attempted something like this in CMake? Is there anything that will make this sort of mixed-crosscompilation easier to understand and maintain in CMake? (And what about the implications for CTest, which we use to drive our tests?)

(Note, in case someone suggests it: yes, it’s theoretically possible for us to compile everything, including libHalide, into WebAssembly as well and run it that way, but it would be a nontrivial performance degradation, and we are not willing to consider this a useful option.)


CMake does not support more than one toolchain per language. It’s just a fundamental design decision baked in at the very early days that isn’t possible to feasibly fix today.

The typical fix is to build the project twice (via ExternalProject), once for the host and then for the cross-compilation step. You can see this in VTK’s iOS and Android build setups.

This question has already been answered before: