27

It seems like CMake is fairly entrenched in its view that there should be one, and only one, CMAKE_CXX_COMPILER for all C++ source files. I can't find a way to override this on a per-target basis. This makes a mix of host-and-cross compiling in a single CMakeLists.txt very difficult with the built-in CMake facilities.

So, my question is: what's the best way to use multiple compilers for the same language (i.e. C++)?

cdleary
  • 69,512
  • 53
  • 163
  • 191
  • Does this answer your question? [CMake: how to change compiler for individual target](https://stackoverflow.com/questions/27168094/cmake-how-to-change-compiler-for-individual-target) – ChrisB Apr 26 '23 at 09:04

5 Answers5

14

It's impossible to do this with CMake.

CMake only keeps one set of compiler properties which is shared by all targets in a CMakeLists.txt file. If you want to use two compilers, you need to run CMake twice. This is even true for e.g. building 32bit and 64bit binaries from the same compiler toolchain.

The quick-and-dirty way around this is using custom commands. But then you end up with what are basically glorified shell-scripts, which is probably not what you want.

The clean solution is: Don't put them in the same CMakeLists.txt! You can't link between different architectures anyway, so there is no need for them to be in the same file. You may reduce redundancies by refactoring common parts of the CMake scripts into separate files and include() them.

The main disadvantage here is that you lose the ability to build with a single command, but you can solve that by writing a wrapper in your favorite scripting language that takes care of calling the different CMake-makefiles.

ComicSansMS
  • 51,484
  • 14
  • 155
  • 166
  • 2
    Seems like add_directory(other_build_kind_folder) is a possibility as well, as opposed to making a custom wrapper, since that's what I've been doing and it seems to work. :-) – cdleary Mar 04 '12 at 17:51
  • 2
    @cdleary Could you clarify how that works? How does `add_subdirectory` (or did you really mean `add_directory`?) allow you to switch toolchains? – Kyle Strand Apr 27 '15 at 21:56
  • 1
    Mostly correct, but there are techniques to massage CMake to use both a host and a toolchain set of compilers controlled from the one build. See [this question](http://stackoverflow.com/q/36084785/1938798) and [answer](http://stackoverflow.com/a/36084786/1938798) for a similar scenario which I've been using successfully in a couple of real world projects for some time now. @Bill's answer recommending ExternalProject is also good advice. – Craig Scott Jul 16 '16 at 02:46
  • 1
    @ComicSancMs I strongly disagree on the reasoning behind the 3rd paragraph ,Indeed you can't link with different architectures but that's not the only reason to have diffrent c++ compilers, for example I used to use [templight](https://github.com/mikael-s-persson/templight) as a wrapper for clang and ccache is also a compiler wrapper , both these projects count as different compilers but there are just different tools that by principal you can use at will at any separate cpp files you want – Spyros Mourelatos Feb 09 '21 at 12:44
  • In VS it's fine to have one solution with even static library projects compiled with different compilers. Because they all binary compatible. Compilers are VC, Intel, Clang. They all use the same VC stl. Designed to be binary compatible. – Антон Сергунов Oct 12 '21 at 03:23
  • See my answer below. It's not impossible. – Daniel Garcia Aug 27 '22 at 17:31
  • This is no longer true. The answer you're looking for is [here](https://stackoverflow.com/questions/27168094/cmake-how-to-change-compiler-for-individual-target/75777519#75777519). – ChrisB Apr 26 '23 at 09:02
5

You might want to look at ExternalProject: http://www.kitware.com/media/html/BuildingExternalProjectsWithCMake2.8.html

E-rich
  • 9,243
  • 11
  • 48
  • 79
Bill Hoffman
  • 1,742
  • 11
  • 12
3

Not impossible as the top answer suggests. I have the same problem as OP. I have some sources for cross compiling for a raspberry pi pico, and then some unit tests that I am running on my host system.

To make this work, I'm using the very shameful "set" to override the compiler in the CMakeLists.txt for my test folder. Works great.

if(DEFINED ENV{HOST_CXX_COMPILER})
  set(CMAKE_CXX_COMPILER $ENV{HOST_CXX_COMPILER})
else()
  set(CMAKE_CXX_COMPILER "g++")
endif()

set(CMAKE_CXX_FLAGS "")

The cmake devs/community seems very against using set to change the compiler since for some reason. They assume that you need to use one compiler for the entire project which is an incorrect assumption for embedded systems projects.

My solution above works, and fits the philosophy I think. Users can still change their chosen compiler via environment variables, if it's not set then I do assume g++. set only changes variables for the current scope, so this doesn't affect the rest of the project.

Daniel Garcia
  • 462
  • 3
  • 8
0

To extend @Bill Hoffman's answer: Build your project as a super-build, by using some kind of template like the one here https://github.com/Sarcasm/cmake-superbuild which will configure both the dependencies and your project as an ExternalProject (standalone cmake configure/build/install environment).

Gabriel
  • 8,990
  • 6
  • 57
  • 101
0

For those who are using a modern (CMake >= v3.19), take a look at presets.

With these you can have a preset that is used for building with one compiler and another preset for another compiler.

It does not completely solve the problem, but with modern editors (vs code), the switching between the compilers becomes a breeze.

SupAl
  • 517
  • 3
  • 12