我们有一组跨平台的 CMake构建脚本,并支持使用 Visual C++ 和 GCC 进行构建。
我们正在尝试使用 Clang,但我不知道如何在我们的CMake脚本中测试编译器是否为Clang。
应该测试什么来确定编译器是否为Clang?目前,我们正在使用 MSVC
和 CMAKE_COMPILER_IS_GNU<LANG>
来分别测试Visual C++和GCC。
我们有一组跨平台的 CMake构建脚本,并支持使用 Visual C++ 和 GCC 进行构建。
我们正在尝试使用 Clang,但我不知道如何在我们的CMake脚本中测试编译器是否为Clang。
应该测试什么来确定编译器是否为Clang?目前,我们正在使用 MSVC
和 CMAKE_COMPILER_IS_GNU<LANG>
来分别测试Visual C++和GCC。
可以通过使用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策略描述。
CMake 3.15已经支持了 clang-cl 和常规的clang前端。您可以通过检查变量CMAKE_<LANG>_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_CXX_COMPILER_ID
变量只能在 project(Foo CXX)
命令执行之后使用。 - waldyriousif (CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU") ... endif()
。 - Fred Schoencmake 3.0.0
发布了“AppleClang”。然而,仅仅因为cmake --version
报告相等或更高并不足够--您必须使用cmake_minimum_required(VERSION 3.0.0)
,以便使用“3.0.0”标准! - svenevs这是一个更详细的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()
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
MESSAGE("MSVC")
endif()
如果你不喜欢引用的内容,你可以使用MATCHES
命令:
if (CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
MESSAGE("MSVC")
endif()
如果您指定cmake_minimum_required版本>=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
为避免任何拼写错误问题,我使用不区分大小写的比较,例如:
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中不支持)。
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()
CMAKE_CXX_COMPILER_FRONTEND_VARIANT需要CMake v3.14+。
__GNUC__
和_MSC_VER
,但它不能像任何一个编译器一样处理相同的程序。检测LLVM Clang和Apple Clang对于确保代码编译和执行符合预期至关重要。我已经厌倦了处理Clang的问题,我们只是在Windows上中断编译。我们已经采取了让用户向LLVM抱怨以便Clang开发人员改变其行为的政策。另请参见如何告诉Clang停止假装成其他编译器? - jww