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

Rez*_*zie 256 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")
Run Code Online (Sandbox Code Playgroud)

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

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

sak*_*kra 327

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

$ export CC=/usr/bin/clang
$ export CXX=/usr/bin/clang++
$ cmake ..
-- The C compiler identification is Clang
-- The CXX compiler identification is Clang
Run Code Online (Sandbox Code Playgroud)

可以通过将编译器特定标志放入系统范围的CMake文件并将CMAKE_USER_MAKE_RULES_OVERRIDE变量指向它来覆盖它们.创建CMAKE_USER_MAKE_RULES_OVERRIDE包含以下内容的文件:

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")
Run Code Online (Sandbox Code Playgroud)

后缀_INIT将使CMake ~/ClangOverrides.txt使用给定值初始化相应的变量.然后以下列方式调用cmake:

$ cmake -DCMAKE_USER_MAKE_RULES_OVERRIDE=~/ClangOverrides.txt ..
Run Code Online (Sandbox Code Playgroud)

最后强制使用LLVM binutils,设置内部变量_INIT.该变量受以下*_FLAGS模块的尊重:

$ cmake -D_CMAKE_TOOLCHAIN_PREFIX=llvm- ..
Run Code Online (Sandbox Code Playgroud)

把所有这些组合起来,你可以写一个shell封装程序设置环境变量cmake_CMAKE_TOOLCHAIN_PREFIX再调用与所提到的变量覆盖cmake的.

  • 请注意,大部分此类信息都缓存在构建树顶层的文件CMakeCache.txt中.要在gcc和clang之间切换,你应该有两个完全独立的构建树,只需来回cd来"切换"编译器.使用给定的编译器生成构建树后,无法切换该构建树的编译器. (14认同)
  • 读者注意.如果您遇到CMake没有遵守`CC`和`CXX`变量的问题,可能是因为您需要先从构建目录中删除所有文件.`rm CMakeCache.txt`可能不是很麻烦. (7认同)
  • 我已遵循您的回答,除了“CMAKE_USER_MAKE_RULES_OVERRIDE”之外的所有内容都有效。似乎该文件被忽略(即尽管在覆盖文件中将“CMAKE_C_FLAGS_RELEASE”设置为“-O4”,但它在 cmake 中显示了“-O3 -DNDEBUG”的默认值)。 (2认同)

小智 120

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

sudo apt-get install clang
sudo update-alternatives --config c++
Run Code Online (Sandbox Code Playgroud)

将打印这样的东西:

  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
Run Code Online (Sandbox Code Playgroud)

然后选择clang ++.

  • 谢谢,我不知道这个!虽然我猜这取决于cmake在哪里寻找编译器,对吧? (3认同)
  • 我得到一个答复,"链接组c ++中只有一个替代方案".请扩展您的答案,以包括如何将clang添加到此列表中 (2认同)
  • 请谨慎使用此替代方法,因为它可能导致系统副作用。nvidia驱动程序之类的软件包已经遇到问题,该软件包在安装过程中会重新编译某些内核模块,并且与clang不兼容。 (2认同)
  • 如果你想安装 clang-3.5、clang-3.6 等,请使用它来设置默认 http://stackoverflow.com/a/30742451/1427533 否则你会得到`链接组cc中只有一个选择(提供/usr/bin/cc):/usr/bin/gcc` (2认同)

Tob*_*gel 23

您可以使用选项命令:

option(USE_CLANG "build application with clang" OFF) # OFF is the default
Run Code Online (Sandbox Code Playgroud)

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

if(USE_CLANG)
    SET (...)
    ....
endif(USE_CLANG)
Run Code Online (Sandbox Code Playgroud)

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

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


Vic*_*sky 17

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:
Run Code Online (Sandbox Code Playgroud)

  • 如果您已手动安装了clang并将其放在非标准位置,则可能无法显示--config.例如,如果它在`/ opt/clang-llvm-3.5 /`中,那么首先安装一个新的替代方案:`sudo update-alternatives --install/usr/bin/c ++ c ++ /opt/clang-llvm-3.5/bin/clang++ 30` (7认同)

小智 11

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

 cmake -DCMAKE_TOOLCHAIN_FILE=/path/to/clang-toolchain.cmake ..
Run Code Online (Sandbox Code Playgroud)

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

  • 我仍然很惊讶如何只能在SO的线程底部找到正确的答案。 (3认同)

yee*_*yee 10

如果选择的默认编译器cmakegcc并且您已经安装clang,您可以使用简单的方法来编译您的项目clang

$ mkdir build && cd build
$ CXX=clang++ CC=clang cmake ..
$ make -j2
Run Code Online (Sandbox Code Playgroud)


ech*_*sto 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")
Run Code Online (Sandbox Code Playgroud)

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

作为注释-O4将在您的程序上调用您可能不需要的LTO(它将大大增加编译时间)并且将默认值设置为c99模式,因此也不一定需要该标志.


Enz*_*Chi 5

根据的帮助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.
Run Code Online (Sandbox Code Playgroud)

您可以创建CMake语法之类的文件,gcc_compiler.txtclang_compiler.txt包括所有相关配置。

lang示例(clang_compiler.txt):

 set(CMAKE_C_COMPILER "/usr/bin/clang" CACHE string "clang compiler" FORCE)
Run Code Online (Sandbox Code Playgroud)

然后以

GCC:

cmake -C gcc_compiler.txt XXXXXXXX
Run Code Online (Sandbox Code Playgroud)

铛:

cmake -C clang_compiler.txt XXXXXXXX
Run Code Online (Sandbox Code Playgroud)


Sup*_*oob 5

只需将这些行添加到 ~/.bashrc 的末尾

export CC=/usr/bin/clang
export CXX=/usr/bin/clang++
Run Code Online (Sandbox Code Playgroud)

重新启动终端或source ~/.bashrc在终端中执行操作。从现在开始,cmake将使用clang来构建每个项目。编辑 ~/.bashrc 以切换回 gcc。请记住,这仅适用于 Bash shell。要使其在 Fish 或 Zsh 等其他 shell 中工作,您必须使用它们自己的导出方法。