0

There are so many ways to set the compiler in CMake. (CMAKE_CXX_COMPILER, CXX, etc)

What takes precedence?

  • CXX
  • CMAKE_CXX_COMPILER
  • etc
  • The questions in the **title** don't correspond to the ones in the question **body**. And at least the 2nd and the 3rd questions (from the body) should be asked as **separate** question posts. – Tsyvarev Mar 28 '21 at 20:44
  • I've updated the question and answer. Is it better now? –  Mar 28 '21 at 20:59
  • 2
    It is better, but the part "How does CMake find compilers and linkers?" is already covered in that question: https://stackoverflow.com/questions/45933732/how-to-specify-a-compiler-in-cmake. (If you feel that the referenced question lacks for some answer, then just add the answer for it). So, the only "What takes precedence?" part remains. – Tsyvarev Mar 28 '21 at 22:46
  • Gotcha. Updated to only be a "What takes precedence?" question. –  Mar 28 '21 at 23:02

1 Answers1

2

After using CMake for a year I just ended up asking the devs.

Here is the answer they provided on discourse:

What takes precedence?

This is ordered in terms of most specific to least specific.

1. CMAKE_TOOLCHAIN_FILE

This variable must be set before the very first project call in your cmake project.

To be clear the toolchain file will just be setting CMAKE_<LANG>_COMPILER inside the file. It would be more correct to say that a toolchain could change the ways for setting a compiler.

2. CMAKE_<LANG>_COMPILER

These variable must be set before the very first project call in your cmake project.

3. Environment Variables

a. CC / CXX

You can also specify your compilers by setting environment variables.

CC specifies the C compiler: https://cmake.org/cmake/help/latest/envvar/CC.html

CXX specifies the CXX compiler: https://cmake.org/cmake/help/latest/envvar/CXX.html?highlight=cxx

b. The environment PATH

As a last resort CMake tries to check your path and searches for known/common binary names in the PATH.

Tip: Using the PATH to shorten your commands!

Having things in your path can also shorten the above commands so you don't have to use absolute paths.

For example if clang++ is in your path you can also do this.

cmake -S . -B build -D CMAKE_CXX_COMPILER=clang++

Why doesn't the above advice work for the Visual Studio generator?

The above advice is only intended for command-line generators. (Ninja, Unix Makefiles, etc)

The VS generator doesn't pay attention to CMAKE_<LANG>_COMPILER, so setting it does nothing for that generator.

Visual Studio handles things slightly differently. Because of course it does. It's Visual Studio. Visual studio plays by it's own rules because it likes to make everything difficult.

Visual Studio is designed around toolsets.

Toolsets files are essentially how Visual Studio solutions describe the compiler/linker.

You can find your toolchains on your computer if you want.

Here is where they are located on my machine.

C:\Program Files (x86)\Microsoft Visual Studio\2019\Preview\MSBuild\Microsoft\VC\v160\Platforms

enter image description here enter image description here

CMake gives you the ability to specify the toolsets and architecture you are targeting via Visual Studio.

See the necessary CMake documentation here:

Wow that's an annoying workflow for Visual Studio only. How can I use CMake + Visual Studio + Ninja

What an oddly specific question that now has an answer: https://learn.microsoft.com/en-us/cpp/build/cmakesettings-reference?view=msvc-160

The Visual Studio team has added official CMake support. So you can use Visual Studio with CMake in a much less annoying way.

DuckDuckGo or Google "CMake projects in Visual Studio"

  • 1
    #2 ex1 is absolutely unacceptable for production or open source code. It should be clearly signposted as such. It makes it impossible for other people to consume the project without exactly replicating the environment or editing the CMakeLists.txt files. None of the other options have this problem. – Alex Reinking Mar 29 '21 at 01:39
  • I updated to get rid of the examples which might encourage bad practice. I meant it as an example to highlight the project call, but you bring up a good point. –  Mar 29 '21 at 02:23
  • 1
    If the question just about **ordering**, then why these examples are ever needed? Also, I don't think that it is correct to talk about *precedence* of a toolchain. E.g. a toolchain could define `CMAKE_CXX_COMPILER` as a **cache** variable, so it would be possible to redefine a C++ compiler (but not other properties of the toolchain) via setting this variable in the command line or before the project call. It would be more correct to say that a toolchain **could change the ways** for setting a compiler. – Tsyvarev Mar 29 '21 at 07:48