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


当前回答

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

其他回答

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

布景(CMAKE_AR /usr/bin/llvm-ar) 集(CMAKE_LINKER "/usr/bin/llvm-ld") 布景(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模式,所以这个标志也不一定需要。

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

$ 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=c11")
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 -std=c++17")
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二进制代码,设置内部变量_CMAKE_TOOLCHAIN_PREFIX。这个变量由CMakeFindBinUtils模块提供:

$ cmake -D_CMAKE_TOOLCHAIN_PREFIX=llvm- ..

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

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

也请参阅这个CMake常见问题解答关于重写文件。

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

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

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

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的工具链文件机制来达到这个目的,参见这里的例子。为每个编译器编写包含相应定义的工具链文件。在配置时,运行例如

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

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