使用CMake在GCC和Clang / LLVM之间切换
我有一些使用CMake构build的项目,我希望能够轻松地使用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")
是否有一个简单的方法来切换这些和默认的GCCvariables,最好是作为一个系统范围的变化,而不是项目特定的(即不只是将它们添加到项目的CMakeLists.txt)?
另外,使用clang而不是gcc编译时,是否需要使用llvm-*
程序而不是系统默认值? 有什么不同?
CMake在检测到C和C ++编译器使用时CXX
环境variablesCC
和CXX
:
$ 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_OVERRIDEvariables指向它来覆盖。 使用以下内容创build一个文件~/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
variables。 然后以下面的方式调用cmake:
$ cmake -DCMAKE_USER_MAKE_RULES_OVERRIDE=~/ClangOverrides.txt ..
最后强制使用LLVM binutils,设置内部variables_CMAKE_TOOLCHAIN_PREFIX
。 这个variables被CMakeFindBinUtils
模块所尊敬:
$ cmake -D_CMAKE_TOOLCHAIN_PREFIX=llvm- ..
把这一切放在一起,你可以编写一个shell包装,它设置环境variablesCC
和CXX
,然后用上面提到的variables覆盖调用cmake。
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
然后,只需select铛++。
您可以使用选项命令:
option(USE_CLANG "build application with clang" OFF) # OFF is the default
然后在if()s中包装clang编译器设置:
if(USE_CLANG) SET (...) .... endif(USE_CLANG)
这样它就在guiconfiguration工具中显示为一个cmake选项。
为了使系统在整个系统范围内,你当然可以使用一个环境variables作为默认值,或者留在Ferruccio的答案中。
在Ubuntu上进行系统C的更改:
sudo update-alternatives --config cc
Ubuntu系统范围的C ++更改:
sudo update-alternatives --config c++
对于上面的每一个,按select号码(1)和回车键来selectClang:
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等程序:
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内部格式下工作的,因此对于构build你的应用程序是没有用的。
注意-O4会在你的程序上调用你不想要的LTO(这会大大增加编译时间),并且叮当默认为c99模式,所以标志也不一定需要。
您可以使用CMakeLists.txt
的语法$ENV{environment-variable}
来访问环境variables。 您可以创build脚本来适当地初始化一组环境variables,并在CMakeLists.txt
文件中引用这些variables。
根据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.
你可以创build像gcc_compiler.txt
和clang_compiler.txt
这样的文件来包含CMake语法中的所有相关configuration。
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
你可以使用cmake的工具链文件机制来实现这个目的,参见这里 。 您为每个包含相应定义的编译器编写一个工具链文件。 在configuration的时候,你运行例如
cmake -DCMAKE_TOOLCHAIN_FILE=/path/to/clang-toolchain.cmake ..
所有的编译器信息将在工具链文件的project()调用中设置。 虽然在文档中只提到了交叉编译的情况,但是对于同一系统中的不同编译器也是如此。
如果由cmake
select的默认编译器是gcc
并且已经安装了clang
,那么可以使用简单的方法用clang
编译你的项目:
$ mkdir build && cd build $ CXX=clang++ CC=clang cmake .. $ make -j2