使用CMake在GCC和Clang/LLVM之间切换

我有许多使用CMake构建的项目,我希望能够轻松地在使用GCC或Clang/LLVM之间切换来编译它们。我相信(如果我弄错了请纠正我!)使用Clang我需要设置以下:

    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")

是否有一种简单的方法在这些和默认的GCC变量之间切换,最好是作为一个系统范围的更改,而不是特定于项目(即不只是将它们添加到项目的CMakeLists.txt)?

另外,在使用clang而不是gcc进行编译时,是否有必要使用llvm-*程序而不是系统默认值?有什么不同?

318389 次浏览

你可以在你的CMakeLists.txt中使用语法:$ENV{environment-variable}来访问环境变量。你可以创建脚本,适当地初始化一组环境变量,并在你的CMakeLists.txt文件中引用这些变量。

您可以使用option命令:

option(USE_CLANG "build application with clang" OFF) # OFF is the default

然后将clang-compiler设置包在if()中:

if(USE_CLANG)
SET (...)
....
endif(USE_CLANG)

通过这种方式,它将在gui配置工具中显示为cmake选项。

当然,要使其成为系统范围,您可以使用一个环境变量作为默认值,或者沿用Ferruccio的答案。

在检测到要使用的C和c++编译器时,CMake尊重环境变量CCCXX:

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

编译器特定的标志可以通过将它们放入make覆盖文件并将CMAKE_USER_MAKE_RULES_OVERRIDE变量指向它来覆盖。创建一个包含以下内容的文件~/ClangOverrides.txt:

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        "-O3 -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        "-O3 -DNDEBUG")
SET (CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT "-O2 -g")

后缀_INIT将使CMake用给定值初始化相应的*_FLAGS变量。然后按以下方式调用cmake:

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

最后,为了强制使用LLVM双utils,设置内部变量_CMAKE_TOOLCHAIN_PREFIXCMakeFindBinUtils模块支持这个变量:

$ cmake -D_CMAKE_TOOLCHAIN_PREFIX=llvm- ..

在CMake 3.9或更新版本中不再需要设置_CMAKE_TOOLCHAIN_LOCATION

把这些放在一起,你可以编写一个shell包装器,它设置环境变量CCCXX,然后用上述变量重写调用cmake

也可以在make override文件上看到CMake常见问题解答

你绝对不需要使用各种不同的llvm-ar等程序:

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")

这些是在llvm内部格式上工作的,因此对构建应用程序没有用处。

注意-O4会在你的程序上调用LTO,这可能是你不想要的(这会大大增加编译时间),clang默认为c99模式,所以这个标志也不一定需要。

Ubuntu上系统范围的c++更改:

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

将打印如下内容:

  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

然后选择clang++。

Ubuntu系统范围内的C更改:

sudo update-alternatives --config cc

Ubuntu上系统范围的c++更改:

sudo update-alternatives --config c++

对于以上每一个,按选择号码(1)和Enter选择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:

根据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.

你可以创建像gcc_compiler.txtclang_compiler.txt这样的文件,以包含CMake语法中的所有相关配置。

示例(clang_compiler.txt):

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

然后运行它

GCC:

cmake -C gcc_compiler.txt XXXXXXXX

铿锵声:

cmake -C clang_compiler.txt XXXXXXXX

你可以使用cmake的工具链文件机制来实现这个目的,参见例如在这里。为每个编译器编写包含相应定义的工具链文件。在配置时,运行例如

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

所有编译器信息将在project()调用期间从工具链文件中设置。虽然在文档中仅在交叉编译上下文中提到,但它适用于同一系统上的不同编译器。

如果cmake选择的默认编译器是gcc,并且你已经安装了clang,你可以使用简单的方法用clang编译你的项目:

$ mkdir build && cd build
$ CXX=clang++ CC=clang cmake ..
$ make -j2

或者为cmake指定编译器:

$ cmake -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=clang ..

只需将其添加到~/.bashrc的末尾

export CC=/usr/bin/clang
export CXX=/usr/bin/clang++

重新启动终端,从现在开始,cmake将使用clang构建每个项目。编辑~/。Bashrc切换回gcc。

在CMakelists.txt中最好不要指定编译器。

只需添加以下命令

- d CMAKE_CXX_COMPILER =“xx"- d CMAKE_C_COMPILER =“xx"

例子:

cmake -D CMAKE_CXX_COMPILER="/bin/clang++-xx" -D CMAKE_C_COMPILER="/bin/clang-xx"