在CMake中,如何测试编译器是否为Clang?


151

我们有一组跨平台的CMake构建脚本,并且支持使用Visual C ++GCC进行构建。

我们正在尝试Clang,但我不知道如何使用CMake脚本测试编译器是否为Clang。

我应该测试什么以查看编译器是否为Clang?我们目前正在使用,MSVCCMAKE_COMPILER_IS_GNU<LANG>分别测试Visual C ++和GCC。


您可以通过将CMAKE_C_COMPILER和CMAKE_CXX_COMPILER设置为clang或clang ++的路径来设置编译器。+1表示lang声。
Zaffy 2012年

你为什么要在乎呢?
就可

2
@BasileStarynkevitch因为我们支持MSVC,所以我们需要检测Clang,以便我们知道是打开类似GCC的选项,还是打开类似MSVC的选项。我想起来已经太久了,但是当然也有可能我们使用了Clang不支持的选项。
leedm777 2015年

1
@BasileStarynkevitch-Clang伪装为__GNUC__and _MSC_VER,但不能使用与任何一个编译器相同的程序。检测LLVM Clang和Apple Clang对于确保代码按预期编译和执行至关重要。我对处理Clang的BS感到非常厌倦,我们只是中断了Windows上的编译。我们采用了让用户向LLVM投诉的策略,以便Clang开发人员更改其行为。另请参阅如何告诉Clang停止假装其他编译器?
jww 16/09/13

Answers:


242

可靠的检查是使用CMAKE_<LANG>_COMPILER_ID变量。例如,检查C ++编译器:

if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
  # using Clang
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
  # using GCC
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Intel")
  # using Intel C++
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
  # using Visual Studio C++
endif()

如果使用了像ccache这样的编译器包装器,这些也可以正常工作。

从CMake 3.0.0开始CMAKE_<LANG>_COMPILER_ID,Apple提供的Clang的值现在为AppleClang。要测试Apple提供的Clang和常规Clang,请使用以下if条件:

if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
  # using regular Clang or AppleClang
endif()

另请参阅AppleClang策略说明

CMake 3.15增加了对clang-cl和常规clang前端的支持。您可以通过检查变量来确定前端变体CMAKE_CXX_COMPILER_FRONTEND_VARIANT

if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
  if (CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC")
    # using clang with clang-cl front end
  elseif (CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "GNU")
    # using clang with regular front end
  endif()
endif()

所述cmake的文档状态“这是在确定编译器使用,并受变化”。否则,那将是完美的:-(
leedm777

17
从CMake 2.8.10开始,(最终!)此变量已记录。请参阅:cmake.org/cmake/help/v2.8.10/...
尼克·哈钦森

9
注意,该CMAKE_CXX_COMPILER_ID变量仅在命令之后可用project(Foo CXX)
waldyrious

5
对于gcc和clang都接受的标志,我使用if (CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU") ... endif()
Fred Schoen

4
如果您对为什么无法AppleClang具体检测感到困惑,则@sakra表示已cmake 3.0.0释放AppleClang。但是,仅因为cmake --version报告等于或大于此是不够的cmake_minimum_required(VERSION 3.0.0),所以3.0.0必须使用标准!
svenevs

2

OGRE 3D引擎源代码使用以下检查

if (CMAKE_CXX_COMPILER MATCHES ".*clang")
    set(CMAKE_COMPILER_IS_CLANGXX 1)
endif ()

3
那已经很近了,但是当您使用ccache(即export CXX="ccache clang++")时
不起作用

4
足够亲密,我给你。我曾经if ("${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1}" MATCHES ".*clang")处理过ccache案件。
leedm777

1
这对我来说不起作用${CMAKE_CXX_COMPILER} == /Library/Developer/CommandLineTools/usr/bin/c++。接受的答案有效。
Fred Schoen

1

为了避免出现任何拼写错误的问题,我使用了不区分大小写的比较,例如:

string( TOLOWER "${CMAKE_CXX_COMPILER_ID}" COMPILER_ID )
if (COMPILER_ID STREQUAL "clang")
    set(IS_CLANG_BUILD true)
else ()
    set(IS_CLANG_BUILD false)
endif ()

为了使正则表达式MATCHES不区分大小写,我在这里尝试了所有尝试,但都没有成功(CMake似乎不支持)。


实际上,与今天一样,不区分大小写的匹配是不可能的cmake.org/pipermail/cmake/2017-May/065432.html
fferri

-2

这是针对cmake新手的更详细的答案,从sakra的答案修改而来,只需将以下几行附加到CMakeLists.txt

if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
  MESSAGE("Clang")
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
  MESSAGE("GNU")
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel")
  MESSAGE("Intel")
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
  MESSAGE("MSVC")
endif()

然后cmake .在CMakeLists.txt所在的文件夹中运行。然后,您将看到一堆输出以及答案。

...
-- Detecting CXX compile features
-- Detecting CXX compile features - done
GNU
-- Configuring done
-- Generating done
...
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.