Switching between GCC and Clang/LLVM using CMake



Answers

System wide C++ change on Ubuntu:

sudo apt-get install clang
sudo update-alternatives --config c++

Will print something like this:

  Selection    Path              Priority   Status
------------------------------------------------------------
* 0            /usr/bin/g++       20        auto mode
  1            /usr/bin/clang++   10        manual mode
  2            /usr/bin/g++       20        manual mode

Then just select clang++.

Question

I have a number of projects built using CMake and I'd like to be able to easily switch between using GCC or Clang/LLVM to compile them. I believe (please correct me if I'm mistaken!) that to use Clang I need to set the following:

    SET (CMAKE_C_COMPILER             "/usr/bin/clang")
    SET (CMAKE_C_FLAGS                "-Wall -std=c99")
    SET (CMAKE_C_FLAGS_DEBUG          "-g")
    SET (CMAKE_C_FLAGS_MINSIZEREL     "-Os -DNDEBUG")
    SET (CMAKE_C_FLAGS_RELEASE        "-O4 -DNDEBUG")
    SET (CMAKE_C_FLAGS_RELWITHDEBINFO "-O2 -g")

    SET (CMAKE_CXX_COMPILER             "/usr/bin/clang++")
    SET (CMAKE_CXX_FLAGS                "-Wall")
    SET (CMAKE_CXX_FLAGS_DEBUG          "-g")
    SET (CMAKE_CXX_FLAGS_MINSIZEREL     "-Os -DNDEBUG")
    SET (CMAKE_CXX_FLAGS_RELEASE        "-O4 -DNDEBUG")
    SET (CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g")

    SET (CMAKE_AR      "/usr/bin/llvm-ar")
    SET (CMAKE_LINKER  "/usr/bin/llvm-ld")
    SET (CMAKE_NM      "/usr/bin/llvm-nm")
    SET (CMAKE_OBJDUMP "/usr/bin/llvm-objdump")
    SET (CMAKE_RANLIB  "/usr/bin/llvm-ranlib")

Is there an easy way of switching between these and the default GCC variables, preferably as a system-wide change rather than project specific (i.e. not just adding them into a project's CMakeLists.txt)?

Also, is it necessary to use the llvm-* programs rather than the system defaults when compiling using clang instead of gcc? What's the difference?




You can use the toolchain file mechanism of cmake for this purpose, see e.g. here. You write a toolchain file for each compiler containing the corresponding definitions. At config time, you run e.g

 cmake -DCMAKE_TOOLCHAIN_FILE=/path/to/clang-toolchain.cmake ..

and all the compiler information will be set during the project() call from the toolchain file. Though in the documentation is mentionend only in the context of cross-compiling, it works as well for different compilers on the same system.




System wide C change on Ubuntu:

sudo update-alternatives --config cc

System wide C++ change on Ubuntu:

sudo update-alternatives --config c++

For each of the above, press Selection number (1) and Enter to select Clang:

  Selection    Path            Priority   Status
------------------------------------------------------------
* 0            /usr/bin/gcc     20        auto mode
  1            /usr/bin/clang   10        manual mode
  2            /usr/bin/gcc     20        manual mode
Press enter to keep the current choice[*], or type selection number:



You can use the syntax: $ENV{environment-variable} in your CMakeLists.txt to access environment variables. You could create scripts which initialize a set of environment variables appropriately and just have references to those variables in your CMakeLists.txt files.




Links