No CMake, como posso testar se o compilador é Clang?

151

Temos um conjunto de scripts de construção CMake de plataforma cruzada e oferecemos suporte à criação com Visual C ++ e GCC .

Estamos testando o Clang , mas não consigo descobrir como testar se o compilador é ou não o Clang com nosso script CMake.

O que devo testar para ver se o compilador é Clang ou não? No momento, estamos usando MSVCe CMAKE_COMPILER_IS_GNU<LANG>para testar o Visual C ++ e o GCC, respectivamente.

leedm777
fonte
Você pode definir o compilador, definindo CMAKE_C_COMPILER e CMAKE_CXX_COMPILER como caminho para clang ou clang ++. +1 para clang.
Zaffy 06/04
Por que você deveria se importar? Clang é muito GCC como, em termos de opções do compilador aceita ...
Basile Starynkevitch
2
@BasileStarynkevitch Como apoiamos o MSVC, precisávamos detectar o Clang para saber se ativávamos as opções do tipo GCC ou do MSVC. Faz muito tempo que eu lembro, mas também é certamente possível que estivéssemos usando opções não suportadas pelo Clang também.
precisa saber é o seguinte
1
@BasileStarynkevitch - Clang finge ser ambos __GNUC__e _MSC_VER, mas não pode consumir os mesmos programas que qualquer compilador. A detecção do LLVM Clang e do Apple Clang é crucial para garantir que o código seja compilado e executado conforme o esperado. Estou tão cansado de lidar com o BS de Clang que acabamos de quebrar a compilação no Windows . Adotamos a política de permitir que os usuários se queixem ao LLVM para que os desenvolvedores do Clang alterem seu comportamento. Veja também Como dizer ao Clang para parar de fingir ser outros compiladores?
jww 13/09/16

Respostas:

242

Uma verificação confiável é usar as CMAKE_<LANG>_COMPILER_IDvariáveis. Por exemplo, para verificar o compilador 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()

Eles também funcionam corretamente se um wrapper de compilador como o ccache for usado.

A partir do CMake 3.0.0, o CMAKE_<LANG>_COMPILER_IDvalor do Clang fornecido pela Apple é agora AppleClang. Para testar o Clang fornecido pela Apple e o Clang normal, use o seguinte se a condição:

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

Consulte também a descrição da política AppleClang .

O CMake 3.15 adicionou suporte para o front-end clang-cl e o clang regular. Você pode determinar a variante do front-end inspecionando a variável 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
fonte
A documentação do cmake indica "Isso é usado na determinação do compilador e está sujeito a alterações". Caso contrário, seria perfeito :-(
leedm777
17
A partir do CMake 2.8.10, essa variável (finalmente!) Está documentada. Veja: cmake.org/cmake/help/v2.8.10/…
Nick Hutchinson
9
Observe que a CMAKE_CXX_COMPILER_IDvariável está disponível apenas após o comando project(Foo CXX).
waldyrious
5
E para bandeiras que tanto gcc e clang aceitam, eu usoif (CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU") ... endif()
Fred Schoen
4
Se você está confuso por que não consegue detectar AppleClangespecificamente, @sakra indica que foi cmake 3.0.0lançadoAppleClang . No entanto, apenas porque os cmake --versionrelatórios iguais ou superiores não são suficientes - você precisa fazer isso cmake_minimum_required(VERSION 3.0.0)para que os 3.0.0padrões sejam usados!
Svenevs
2

O código-fonte do mecanismo OGRE 3D usa a seguinte verificação :

if (CMAKE_CXX_COMPILER MATCHES ".*clang")
    set(CMAKE_COMPILER_IS_CLANGXX 1)
endif ()
arrowd
fonte
3
Que está perto, mas não funciona quando você usar ccache (ou seja, export CXX="ccache clang++")
leedm777
4
Perto o suficiente, eu vou dar a você. Eu costumava if ("${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1}" MATCHES ".*clang")lidar com o caso ccache.
precisa saber é o seguinte
1
Isso não funciona para mim como ${CMAKE_CXX_COMPILER} == /Library/Developer/CommandLineTools/usr/bin/c++. A resposta aceita funciona.
Fred Schoen
1

Apenas para evitar qualquer problema de ortografia incorreta, estou usando a comparação que não diferencia maiúsculas de 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 tornar a expressão regular sem distinção entre MATCHESmaiúsculas e minúsculas, tentei de tudo aqui sem sucesso (não parece ser suportado no CMake).

Antonio
fonte
de fato, como hoje, a correspondência sem distinção entre
fferri
-2

Esta é uma resposta um pouco mais detalhada para iniciantes cmake, modificada a partir da resposta do sakra, basta anexar as seguintes linhas 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()

Em seguida, execute cmake .a pasta onde está o CMakeLists.txt. Então você verá várias saídas junto com sua resposta.

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