In CMake, come posso verificare se il compilatore è Clang?


151

Abbiamo una serie di script di build CMake multipiattaforma e supportiamo la creazione con Visual C ++ e GCC .

Stiamo provando Clang , ma non riesco a capire come testare se il compilatore è Clang con il nostro script CMake.

Cosa devo testare per vedere se il compilatore è Clang o no? Al momento stiamo utilizzando MSVCe CMAKE_COMPILER_IS_GNU<LANG>di prova per Visual C ++ e GCC, rispettivamente.


È possibile impostare il compilatore impostando CMAKE_C_COMPILER e CMAKE_CXX_COMPILER sul percorso per clang o clang ++. +1 per clang.
Zaffy,

Perché dovresti preoccuparti? Clang è molto simile a GCC, in termini di opzioni di compilatore accettate ...
Basile Starynkevitch

2
@BasileStarynkevitch Dato che abbiamo supportato MSVC, dovevamo rilevare Clang, quindi sapevamo se attivare le opzioni simili a GCC o quelle simili a MSVC. È passato troppo tempo da ricordare, ma è anche possibile che stessimo utilizzando opzioni non supportate da Clang.
leedm777,

1
@BasileStarynkevitch - Clang finge di essere entrambi __GNUC__e _MSC_VER, ma non può utilizzare gli stessi programmi di entrambi i compilatori. Rilevare LLVM Clang e Apple Clang è fondamentale per garantire che il codice venga compilato ed eseguito come previsto. Sono così stanco di avere a che fare con BS di Clang che interrompiamo la compilazione su Windows . Abbiamo adottato la politica di consentire agli utenti di lamentarsi con LLVM in modo che gli sviluppatori di Clang cambino il loro comportamento. Vedi anche Come dire a Clang di smettere di fingere di essere altri compilatori?
1616

Risposte:


242

Un controllo affidabile consiste nell'utilizzare le CMAKE_<LANG>_COMPILER_IDvariabili. Ad esempio, per controllare il compilatore 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()

Funzionano anche correttamente se viene utilizzato un wrapper del compilatore come ccache .

A partire da CMake 3.0.0 il CMAKE_<LANG>_COMPILER_IDvalore per Clang fornito da Apple è ora AppleClang. Per verificare sia il Clang fornito da Apple sia il Clang normale, utilizzare la seguente condizione if:

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

Vedi anche la descrizione della politica AppleClang .

CMake 3.15 ha aggiunto il supporto sia per il clang-cl che per il normale front-end clang. È possibile determinare la variante del front-end controllando la variabile 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()

La documentazione di cmake afferma "Questo è usato per determinare il compilatore ed è soggetto a modifiche". Altrimenti, sarebbe perfetto :-(
leedm777

17
A partire da CMake 2.8.10, questa variabile è (finalmente!) Documentata. Vedi: cmake.org/cmake/help/v2.8.10/…
Nick Hutchinson,

9
Si noti che la CMAKE_CXX_COMPILER_IDvariabile è disponibile solo dopo il comando project(Foo CXX).
waldyrious

5
E per le bandiere che accettano sia gcc che clang, io usoif (CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU") ... endif()
Fred Schoen il

4
Se sei confuso perché non riesci a rilevare in modo AppleClangspecifico, @sakra indica che è stato cmake 3.0.0rilasciatoAppleClang . Tuttavia, solo perché cmake --versionrapporti uguali o superiori non sono sufficienti, è necessario per cmake_minimum_required(VERSION 3.0.0)poter utilizzare gli 3.0.0standard!
svenevs,

2

Il codice sorgente del motore OGRE 3D utilizza il seguente controllo :

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

3
È vicino, ma non funziona quando si utilizza ccache (ovvero, export CXX="ccache clang++")
leedm777

4
Abbastanza vicino, te lo darò. Ho usato if ("${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1}" MATCHES ".*clang")per gestire il caso ccache.
leedm777,

1
Questo non funziona per me come ${CMAKE_CXX_COMPILER} == /Library/Developer/CommandLineTools/usr/bin/c++. La risposta accettata funziona.
Fred Schoen,

1

Solo per evitare qualsiasi errore di ortografia, sto usando il confronto senza distinzione tra maiuscole e minuscole, come:

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

Per rendere la regex MATCHESinsensibile alle maiuscole, ho provato tutto qui senza successo (non sembra essere supportato in CMake).


anzi, come oggi, la cassa di corrispondenza insensibile non è possibile cmake.org/pipermail/cmake/2017-May/065432.html
fferri

-2

Questa è una risposta leggermente più dettagliata per i neofiti di cmake, modificata dalla risposta di sakra, basta aggiungere le seguenti righe 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()

Quindi esegui cmake .nella cartella in cui si trova CMakeLists.txt. Quindi vedrai un sacco di risultati insieme alla tua risposta.

...
-- Detecting CXX compile features
-- Detecting CXX compile features - done
GNU
-- Configuring done
-- Generating done
...
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.