我有许多使用 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-*
程序而不是系统默认程序?有什么不同?
CMake 在检测到要使用的 C 和 C++ 编译器时尊重环境变量 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=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")
后缀 _INIT
将使 CMake 使用给定值初始化相应的 *_FLAGS
变量。然后按以下方式调用 cmake
:
$ cmake -DCMAKE_USER_MAKE_RULES_OVERRIDE=~/ClangOverrides.txt ..
最后要强制使用 LLVM binutils,设置内部变量 _CMAKE_TOOLCHAIN_PREFIX
。 CMakeFindBinUtils
模块支持此变量:
$ cmake -D_CMAKE_TOOLCHAIN_PREFIX=llvm- ..
将所有这些放在一起,您可以编写一个 shell 包装器,它设置环境变量 CC
和 CXX
,然后使用提到的变量覆盖调用 cmake
。
另请参阅有关 make 覆盖文件的 CMake FAQ。
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++。
There is only one alternative in link group cc (providing /usr/bin/cc): /usr/bin/gcc
为此,您可以使用 cmake 的工具链文件机制,参见例如 here。您为每个编译器编写一个包含相应定义的工具链文件。在配置时,您运行例如
cmake -DCMAKE_TOOLCHAIN_FILE=/path/to/clang-toolchain.cmake ..
并且所有编译器信息都将在工具链文件的 project() 调用期间设置。尽管在文档中仅在交叉编译的上下文中提及,但它也适用于同一系统上的不同编译器。
您可以使用选项命令:
option(USE_CLANG "build application with clang" OFF) # OFF is the default
然后将 clang-compiler 设置包装在 if()s 中:
if(USE_CLANG)
SET (...)
....
endif(USE_CLANG)
这样,它在 gui 配置工具中显示为 cmake 选项。
要使其在系统范围内使用,您当然可以使用环境变量作为默认值或保留 Ferruccio 的答案。
cmake -DCMAKE_COMPILER_DEFINITIONS=MyLlvmDefinitions.cmake
这样的命令。
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:
/opt/clang-llvm-3.5/
中,则首先安装一个新的替代方案:sudo update-alternatives --install /usr/bin/c++ c++ /opt/clang-llvm-3.5/bin/clang++ 30
如果 cmake
选择的默认编译器是 gcc
并且您已经安装了 clang
,您可以使用简单的方法通过 clang
编译您的项目:
$ mkdir build && cd build
$ CXX=clang++ CC=clang cmake ..
$ make -j2
或为 cmake 指定编译器:
$ cmake -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=clang ..
您绝对不需要使用各种不同的 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") 设置 (CMAKE_RANLIB "/usr/bin/llvm-ranlib")
它们适用于 llvm 内部格式,因此对构建应用程序没有用处。
注意 -O4 将在您的程序上调用您可能不想要的 LTO(它会大大增加编译时间)并且 clang 默认为 c99 模式,因此也不一定需要该标志。
根据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.txt
和 clang_compiler.txt
这样的文件,以在 CMake 语法中包含所有相关配置。
Clang 示例(clang_compiler.txt):
set(CMAKE_C_COMPILER "/usr/bin/clang" CACHE string "clang compiler" FORCE)
然后运行它
海合会:
cmake -C gcc_compiler.txt XXXXXXXX
铛:
cmake -C clang_compiler.txt XXXXXXXX
您可以在 CMakeLists.txt
中使用语法:$ENV{environment-variable}
来访问环境变量。您可以创建适当初始化一组环境变量的脚本,并且只在 CMakeLists.txt
文件中引用这些变量。
-DCMAKE_C_COMPILER ...
等调用 cmake?
CMakeLists.txt
并让它查询新变量。我希望有一种方便的方法可以在系统范围内进行,而无需修改任何项目文件。类似于传递 CMAKE_TOOLCHAIN_FILE
。
只需在 ~/.bashrc 的末尾添加即可
export CC=/usr/bin/clang
export CXX=/usr/bin/clang++
重新启动终端,从现在开始,cmake 将使用 clang 来构建每个项目。编辑 ~/.bashrc 以切换回 gcc。
最好不要在 CMakelists.txt 中指定编译器。
只需添加以下命令
-D CMAKE_CXX_COMPILER="xx" -D CMAKE_C_COMPILER="xx"
例子:
cmake -D CMAKE_CXX_COMPILER="/bin/clang++-xx" -D CMAKE_C_COMPILER="/bin/clang-xx"
CMAKE_USER_MAKE_RULES_OVERRIDE
之外的所有内容都有效。似乎该文件被忽略了(即,尽管在覆盖文件中将CMAKE_C_FLAGS_RELEASE
设置为-O4
,但它在 cmake 中显示了-O3 -DNDEBUG
的默认值)。src/build-clang
目录中执行此操作,也会忽略覆盖。CC
和CXX
变量时遇到问题,可能是因为您需要先从构建目录中删除所有文件。rm CMakeCache.txt
可能不够。