Dans CMake, comment puis-je tester si le compilateur est Clang?

151

Nous avons un ensemble de scripts de construction CMake multiplateformes et nous prenons en charge la construction avec Visual C ++ et GCC .

Nous essayons Clang , mais je ne peux pas comprendre comment tester si le compilateur est ou non Clang avec notre script CMake.

Que dois-je tester pour voir si le compilateur est Clang ou non? Nous utilisons actuellement MSVCet CMAKE_COMPILER_IS_GNU<LANG>pour tester respectivement Visual C ++ et GCC.

leedm777
la source
Vous pouvez définir le compilateur en définissant CMAKE_C_COMPILER et CMAKE_CXX_COMPILER sur le chemin vers clang ou clang ++. +1 pour clang.
Zaffy
Pourquoi devriez-vous vous en soucier? Clang est très GCC, en termes d'options de compilation acceptées ...
Basile Starynkevitch
2
@BasileStarynkevitch Puisque nous prenions en charge MSVC, nous devions détecter Clang afin de savoir s'il fallait activer les options de type GCC ou celles de type MSVC. Cela fait trop longtemps pour moi de m'en souvenir, mais il est également possible que nous utilisions des options non prises en charge par Clang.
leedm777
1
@BasileStarynkevitch - Clang prétend être les deux __GNUC__et _MSC_VER, mais il ne peut pas consommer les mêmes programmes que l'un ou l'autre des compilateurs. La détection de LLVM Clang et Apple Clang est cruciale pour garantir que le code se compile et s'exécute comme prévu. Je suis tellement fatigué de traiter avec BS de Clang que nous cassons la compilation sous Windows . Nous avons adopté la politique de laisser les utilisateurs se plaindre à LLVM afin que les développeurs de Clang changent de comportement. Voir aussi Comment dire à Clang d'arrêter de se faire passer pour d'autres compilateurs?
jww

Réponses:

242

Une vérification fiable consiste à utiliser les CMAKE_<LANG>_COMPILER_IDvariables. Par exemple, pour vérifier le compilateur 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()

Celles-ci fonctionnent également correctement si un wrapper de compilateur tel que ccache est utilisé.

À partir de CMake 3.0.0, la CMAKE_<LANG>_COMPILER_IDvaleur de Clang fournie par Apple est désormais AppleClang. Pour tester à la fois le Clang fourni par Apple et le Clang normal, utilisez la condition if suivante:

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

Consultez également la description de la politique AppleClang .

CMake 3.15 a ajouté le support pour le clang-cl et le front-end clang régulier. Vous pouvez déterminer la variante frontale en inspectant 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
la source
La documentation cmake indique "Ceci est utilisé pour déterminer le compilateur et est sujet à changement". Sinon, ce serait parfait :-(
leedm777
17
Depuis CMake 2.8.10, cette variable est (enfin!) Documentée. Voir: cmake.org/cmake/help/v2.8.10/…
Nick Hutchinson
9
Notez que la CMAKE_CXX_COMPILER_IDvariable n'est disponible qu'après la commande project(Foo CXX).
waldyrious
5
Et pour les drapeaux que gcc et clang acceptent, j'utiliseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU") ... endif()
Fred Schoen
4
Si vous ne savez pas pourquoi vous ne pouvez pas détecter AppleClangspécifiquement, @sakra indique que cmake 3.0.0libéréAppleClang . Cependant, juste parce que des cmake --versionrapports égaux ou supérieurs ne suffisent pas, vous devezcmake_minimum_required(VERSION 3.0.0) pour que les 3.0.0normes soient utilisées!
svenevs
2

Le code source du moteur OGRE 3D utilise la vérification suivante :

if (CMAKE_CXX_COMPILER MATCHES ".*clang")
    set(CMAKE_COMPILER_IS_CLANGXX 1)
endif ()
arrowd
la source
3
C'est proche, mais ne fonctionne pas lorsque vous utilisez ccache (ie, export CXX="ccache clang++")
leedm777
4
Assez proche, je vais vous le donner. J'avais l'habitude if ("${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1}" MATCHES ".*clang")de gérer l'affaire ccache.
leedm777
1
Cela ne fonctionne pas pour moi comme ${CMAKE_CXX_COMPILER} == /Library/Developer/CommandLineTools/usr/bin/c++. La réponse acceptée fonctionne.
Fred Schoen
1

Juste pour éviter tout problème de faute d'orthographe, j'utilise la comparaison insensible à la casse, comme:

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

Pour rendre l'expression rationnelle MATCHESinsensible à la casse, j'ai tout essayé ici sans succès (ne semble pas être pris en charge dans CMake).

Antonio
la source
en effet, comme aujourd'hui, la correspondance insensible à la casse n'est pas possible cmake.org/pipermail/cmake/2017-Mai/065432.html
fferri
-2

Ceci est une réponse un peu plus détaillée pour les débutants cmake, modifiée à partir de la réponse de sakra, ajoutez simplement les lignes suivantes à 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()

Ensuite, exécutez cmake .dans le dossier où se trouve CMakeLists.txt. Ensuite, vous verrez un tas de sorties avec votre réponse.

...
-- Detecting CXX compile features
-- Detecting CXX compile features - done
GNU
-- Configuring done
-- Generating done
...
Searene
la source