Switching between GCC and Clang/LLVM using CMake
我有许多使用cmake构建的项目,我希望能够轻松地在使用gcc或clang/llvm编译它们之间切换。我相信(如果我错了请纠正我!)要使用clang,我需要设置以下内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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进行编译时,是否需要使用
CSEAL在检测C和C++编译器时使用环境变量EDCOX1、3和EDCOX1 4。
1 2 3 4 5 | $ 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变量指向它来重写。创建包含以下内容的文件
1 2 3 4 5 6 7 8 9 10 11 | 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用给定的值初始化相应的
1 | $ cmake -DCMAKE_USER_MAKE_RULES_OVERRIDE=~/ClangOverrides.txt .. |
最后,为了强制使用llvm binutils,设置内部变量
1 | $ cmake -D_CMAKE_TOOLCHAIN_PREFIX=llvm- .. |
综上所述,您可以编写一个shell包装器,它设置环境变量
Ubuntu上的系统级C++更改:
1 2 | sudo apt-get install clang sudo update-alternatives --config c++ |
将打印如下内容:
1 2 3 4 5 | 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++。
您可以使用选项命令:
1 |
然后在if()s中包装clang编译器设置:
这样,它在GUI配置工具中显示为cmake选项。
为了使它在系统范围内,您当然可以使用一个环境变量作为默认值,或者使用ferrocio的答案。
Ubuntu上的系统范围C更改:
Ubuntu上的系统级C++更改:
对于上述每一项,按选择编号(1)并输入以选择Clang:
1 2 3 4 5 6 | 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: |
您绝对不需要使用各种不同的llvm ar etc程序:
这些都是为了在LLVM内部格式上工作,因此对应用程序的构建没有帮助。
注意-O4将在您的程序上调用您可能不需要的LTO(它将大大增加编译时间),clang默认为c99模式,因此也不必使用该标志。
为此,可以使用cmake的工具链文件机制,请参见此处的示例。为每个编译器编写一个包含相应定义的工具链文件。在配置时,您运行例如
1 | cmake -DCMAKE_TOOLCHAIN_FILE=/path/to/clang-toolchain.cmake .. |
所有编译器信息都将在从工具链文件调用project()的过程中设置。尽管在文档中只提到交叉编译的上下文,但它也适用于同一系统上的不同编译器。
根据
1 2 3 4 5 6 | -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. |
您可以创建像
clang示例(clang_compiler.txt):
1 |
然后运行它作为
海湾合作委员会:
1 | cmake -C gcc_compiler.txt XXXXXXXX |
Clang:
1 | cmake -C clang_compiler.txt XXXXXXXX |
您可以在
如果
1 2 3 | $ mkdir build && cd build $ CXX=clang++ CC=clang cmake .. $ make -j2 |