En CMake, ¿cómo puedo probar si el compilador es Clang?

151

Tenemos un conjunto de scripts de compilación CMake multiplataforma y admitimos la compilación con Visual C ++ y GCC .

Estamos probando Clang , pero no puedo entender cómo probar si el compilador es Clang con nuestro script CMake.

¿Qué debo probar para ver si el compilador es Clang o no? Actualmente estamos usando MSVCy CMAKE_COMPILER_IS_GNU<LANG>para probar Visual C ++ y GCC, respectivamente.

leedm777
fuente
Puede configurar el compilador configurando CMAKE_C_COMPILER y CMAKE_CXX_COMPILER en la ruta a clang o clang ++. +1 por sonido metálico.
Zaffy
¿Por qué te debe importar? Clang es muy parecido al CCG, en términos de opciones de compilación aceptadas ...
Basile Starynkevitch
2
@BasileStarynkevitch Dado que admitíamos MSVC, necesitábamos detectar Clang para saber si activar las opciones tipo GCC o las opciones tipo MSVC. Ha sido demasiado tiempo para recordarlo, pero también es posible que estuviéramos usando opciones que Clang tampoco admite.
leedm777
1
@BasileStarynkevitch: Clang pretende ser ambos __GNUC__y _MSC_VER, pero no puede consumir los mismos programas que cualquiera de los compiladores. Detectar LLVM Clang y Apple Clang es crucial para garantizar que el código se compile y se ejecute como se espera. Estoy tan cansado de lidiar con BS de Clang que simplemente rompemos la compilación en Windows . Hemos adoptado la política de permitir que los usuarios se quejen ante LLVM para que los desarrolladores de Clang cambien su comportamiento. También vea ¿Cómo decirle a Clang que deje de fingir ser otros compiladores?
jww

Respuestas:

242

Una verificación confiable es usar las CMAKE_<LANG>_COMPILER_IDvariables. Por ejemplo, para verificar el compilador de 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()

Estos también funcionan correctamente si se utiliza un contenedor de compilación como ccache .

A partir de CMake 3.0.0, el CMAKE_<LANG>_COMPILER_IDvalor para Clang proporcionado por Apple es ahora AppleClang. Para probar tanto el Clang proporcionado por Apple como el Clang regular, use la siguiente condición if:

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

Consulte también la descripción de la política AppleClang .

CMake 3.15 ha agregado soporte para el clang-cl y el front-end clang regular. Puede determinar la variante de front-end inspeccionando la variable 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()
sakra
fuente
La documentación de cmake dice "Esto se usa para determinar el compilador y está sujeto a cambios". De lo contrario, sería perfecto :-(
leedm777
17
A partir de CMake 2.8.10, esta variable está (¡finalmente!) Documentada. Ver: cmake.org/cmake/help/v2.8.10/…
Nick Hutchinson el
9
Tenga en cuenta que la CMAKE_CXX_COMPILER_IDvariable solo está disponible después del comando project(Foo CXX).
waldyrious
55
Y para las banderas que aceptan gcc y clang, usoif (CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU") ... endif()
Fred Schoen
44
Si está confundido por qué no puede detectar AppleClangespecíficamente, @sakra indica que se cmake 3.0.0liberóAppleClang . Sin embargo, solo porque los cmake --versioninformes iguales o superiores no son suficientes, ¡debe hacerlo para poder utilizar cmake_minimum_required(VERSION 3.0.0)los 3.0.0estándares!
svenevs
2

El código fuente del motor OGRE 3D utiliza lo siguiente verificación :

if (CMAKE_CXX_COMPILER MATCHES ".*clang")
    set(CMAKE_COMPILER_IS_CLANGXX 1)
endif ()
arrowd
fuente
3
Eso está cerca, pero no funciona cuando usa ccache (es decir, export CXX="ccache clang++")
leedm777
44
Lo suficientemente cerca, te lo daré. Solía if ("${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1}" MATCHES ".*clang")manejar el caso de ccache.
leedm777
1
Esto no funciona para mí como ${CMAKE_CXX_COMPILER} == /Library/Developer/CommandLineTools/usr/bin/c++. La respuesta aceptada funciona.
Fred Schoen
1

Solo para evitar cualquier problema de ortografía, estoy usando una comparación que no distingue entre mayúsculas y minúsculas, como:

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 ()

Para hacer que la expresión regular no distinga entre MATCHESmayúsculas y minúsculas, probé todo aquí sin éxito (no parece ser compatible con CMake).

Antonio
fuente
de hecho, como hoy, la coincidencia entre mayúsculas y minúsculas no es posible cmake.org/pipermail/cmake/2017-May/065432.html
fferri
-2

Esta es una respuesta un poco más detallada para los novatos de cmake, modificada de la respuesta de sakra, solo agregue las siguientes líneas a 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()

Luego, ejecute cmake .en la carpeta donde se encuentra CMakeLists.txt. Luego verá un montón de resultados junto con su respuesta.

...
-- Detecting CXX compile features
-- Detecting CXX compile features - done
GNU
-- Configuring done
-- Generating done
...
Searene
fuente