【问题标题】:In CMake, how can I test if the compiler is Clang?在 CMake 中,如何测试编译器是否为 Clang?
【发布时间】:2012-04-20 05:26:29
【问题描述】:

我们有一组cross-platform CMake build scripts,我们支持用Visual C++GCC构建。

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

我应该测试一下编译器是否是 Clang?我们目前正在使用MSVCCMAKE_COMPILER_IS_GNU<LANG> 分别测试Visual C++ 和GCC。

【问题讨论】:

  • 您可以通过将 CMAKE_C_COMPILER 和 CMAKE_CXX_COMPILER 设置为 clang 或 clang++ 的路径来设置编译器。 +1 铿锵声。
  • 你为什么要关心?就可接受的编译器选项而言,Clang 非常类似于 GCC ...
  • @BasileStarynkevitch 由于我们支持 MSVC,我们需要检测 Clang,因此我们知道是打开类似 GCC 的选项,还是打开类似 MSVC 的选项。我记起来太久了,但我们当然也有可能使用了 Clang 不支持的选项。
  • @BasileStarynkevitch - Clang 伪装成 __GNUC___MSC_VER,但它不能使用与任一编译器相同的程序。检测 LLVM Clang 和 Apple Clang 对于确保代码按预期编译和执行至关重要。我已经厌倦了与 Clang 的 BS 打交道,我们只是 break the compile on Windows。我们采用了让用户向 LLVM 投诉的政策,以便 Clang 开发人员改变他们的行为。另见How to tell Clang to stop pretending to be other compilers?

标签: c++ c cmake clang


【解决方案1】:

一个可靠的检查是使用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 开始,Apple 提供的 Clang 的 CMAKE_<LANG>_COMPILER_ID 值现在是 AppleClang。要测试 Apple 提供的 Clang 和常规 Clang,请使用以下 if 条件:

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

另见AppleClang policy description

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 documentation 声明“这用于确定编译器并且可能会更改”。否则,这将是完美的:-(
  • 从 CMake 2.8.10 开始,这个变量(终于!)记录在案了。见:cmake.org/cmake/help/v2.8.10/…
  • 请注意,CMAKE_CXX_COMPILER_ID 变量仅在命令project(Foo CXX) 之后可用。
  • 对于 gcc 和 clang 都接受的标志,我使用if (CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU") ... endif()
  • 如果您对为什么无法具体检测到AppleClang 感到困惑,@sakra 表示cmake 3.0.0 released AppleClang。然而,仅仅因为cmake --version 报告等于或更高是不够的——您必须cmake_minimum_required(VERSION 3.0.0) 才能使用3.0.0 标准!
【解决方案2】:

如果您的 cmake_minimum_required VERSION 小于 3.1,那么您必须使用带引号的变量来确定编译器,如果与STREQUAL 命令一起使用,即

if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
  MESSAGE("MSVC")
endif()

或者,如果你不喜欢引用的东西,你可以使用MATCHES 命令:

if (CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
  MESSAGE("MSVC")
endif()

如果您指定 cmake_minimum_required VERSION >= 3.1,那么您可以愉快地使用不带引号的STREQUAL

if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
  MESSAGE("MSVC")
endif()

cmake 3.1 版本问题,记录在这里:https://cmake.org/cmake/help/latest/policy/CMP0054.html

【讨论】:

    【解决方案3】:

    这是针对 cmake 新手的更详细的答案,根据 sakra 的答案进行了修改。 3.1 的最低版本似乎很重要,因为它改变了 CMake 处理引用的“MSVC”字符串的方式(根据策略 CMP0054)。

    cmake_minimum_required(VERSION 3.1)
    project(MyProject CXX)
    
    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()
    

    【讨论】:

      【解决方案4】:

      您可以像这样测试 Clang 和它的前端:

      if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
        if (CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC") # clang-cl
          # ...
        elseif (CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "GNU") # clang native
          # ...
        endif()
      elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU") # both
          # ...
      endif()
      

      【讨论】:

        【解决方案5】:

        为了避免拼写错误,我使用了不区分大小写的比较,例如:

        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 的正则表达式不区分大小写,我尝试了所有here 都没有成功(CMake 似乎不支持)。

        【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-01-05
        • 2013-11-12
        • 2014-12-10
        • 1970-01-01
        • 1970-01-01
        • 2013-11-13
        • 2012-10-12
        相关资源
        最近更新 更多