Switching between GCC and Clang/LLVM using CMake

2019-01-05 06:22发布

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?

标签: cmake llvm clang
9条回答
戒情不戒烟
2楼-- · 2019-01-05 07:03

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.

查看更多
Melony?
3楼-- · 2019-01-05 07:05

According to the help of cmake:

-C <initial-cache>
     Pre-load a script to populate the cache.

     When cmake is first run in an empty build tree, it creates a CMakeCache.txt file and populates it with customizable settings for the project.  This option may be used to specify a  file  from
     which to load cache entries before the first pass through the project's cmake listfiles.  The loaded entries take priority over the project's default values.  The given file should be a CMake
     script containing SET commands that use the CACHE option, not a cache-format file.

You make be able to create files like gcc_compiler.txt and clang_compiler.txt to includes all relative configuration in CMake syntax.

Clang Example (clang_compiler.txt):

 set(CMAKE_C_COMPILER "/usr/bin/clang" CACHE string "clang compiler" FORCE)

Then run it as

GCC:

cmake -C gcc_compiler.txt XXXXXXXX

Clang:

cmake -C clang_compiler.txt XXXXXXXX
查看更多
家丑人穷心不美
4楼-- · 2019-01-05 07:12

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.

查看更多
可以哭但决不认输i
5楼-- · 2019-01-05 07:17

If the default compiler chose by cmake is gcc and you have installed clang, you can use the easy way to compile your project with clang:

$ mkdir build && cd build
$ CXX=clang++ CC=clang cmake ..
$ make -j2
查看更多
倾城 Initia
6楼-- · 2019-01-05 07:22

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++.

查看更多
ゆ 、 Hurt°
7楼-- · 2019-01-05 07:23

CMake honors the environment variables CC and CXX upon detecting the C and C++ compiler to use:

$ export CC=/usr/bin/clang
$ export CXX=/usr/bin/clang++
$ cmake ..
-- The C compiler identification is Clang
-- The CXX compiler identification is Clang

The compiler specific flags can be overridden by putting them into a system wide CMake file and pointing the CMAKE_USER_MAKE_RULES_OVERRIDE variable to it. Create a file ~/ClangOverrides.txt with the following contents:

SET (CMAKE_C_FLAGS_INIT                "-Wall -std=c99")
SET (CMAKE_C_FLAGS_DEBUG_INIT          "-g")
SET (CMAKE_C_FLAGS_MINSIZEREL_INIT     "-Os -DNDEBUG")
SET (CMAKE_C_FLAGS_RELEASE_INIT        "-O4 -DNDEBUG")
SET (CMAKE_C_FLAGS_RELWITHDEBINFO_INIT "-O2 -g")

SET (CMAKE_CXX_FLAGS_INIT                "-Wall")
SET (CMAKE_CXX_FLAGS_DEBUG_INIT          "-g")
SET (CMAKE_CXX_FLAGS_MINSIZEREL_INIT     "-Os -DNDEBUG")
SET (CMAKE_CXX_FLAGS_RELEASE_INIT        "-O4 -DNDEBUG")
SET (CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT "-O2 -g")

The suffix _INIT will make CMake initialize the corresponding *_FLAGS variable with the given value. Then invoke cmake in the following way:

$ cmake -DCMAKE_USER_MAKE_RULES_OVERRIDE=~/ClangOverrides.txt ..

Finally to force the use of the LLVM binutils, set the internal variable _CMAKE_TOOLCHAIN_PREFIX. This variable is honored by the CMakeFindBinUtils module:

$ cmake -D_CMAKE_TOOLCHAIN_PREFIX=llvm- ..

Putting this all together you can write a shell wrapper which sets up the environment variables CC and CXX and then invokes cmake with the mentioned variable overrides.

查看更多
登录 后发表回答