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

时间:2011-08-11 18:42:06

标签: cmake llvm clang

我有许多使用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-*程序而不是系统默认值?有什么区别?

9 个答案:

答案 0 :(得分:305)

在检测到要使用的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

可以通过将编译器特定标志放入系统范围的CMake文件并将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        "-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")

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

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

最后,为了强制使用LLVM binutils,设置内部变量_CMAKE_TOOLCHAIN_PREFIXCMakeFindBinUtils模块支持此变量:

$ cmake -D_CMAKE_TOOLCHAIN_PREFIX=llvm- ..

将这一切放在一起你可以编写一个shell包装器来设置环境变量CCCXX,然后使用上面提到的变量覆盖来调用cmake。

答案 1 :(得分:114)

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

答案 2 :(得分:21)

您可以使用选项命令:

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

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

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

这样它在gui-configuration工具中显示为cmake选项。

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

答案 3 :(得分:16)

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:

答案 4 :(得分:9)

你绝对不需要使用各种不同的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(它将大大增加编译时间)并且将默认值设置为c99模式,因此也不一定需要标记。

答案 5 :(得分:7)

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

  imageGrid.Children.Add(new BoxView() { BackgroundColor = Color.Red }, newrow, newcol);

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

答案 6 :(得分:4)

根据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示例(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

答案 7 :(得分:3)

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

答案 8 :(得分:2)

如果cmake选择的默认编译器为gcc且您已安装clang,则可以使用简单方法使用clang编译项目:

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