Wie kann ich in CMake testen, ob der Compiler Clang ist?


151

Wir haben eine Reihe von plattformübergreifenden CMake-Build-Skripten und unterstützen das Erstellen mit Visual C ++ und GCC .

Wir probieren Clang aus , aber ich kann nicht herausfinden, wie ich mit unserem CMake-Skript testen kann, ob der Compiler Clang ist oder nicht.

Was soll ich testen, um festzustellen, ob der Compiler Clang ist oder nicht? Wir verwenden MSVCund CMAKE_COMPILER_IS_GNU<LANG>testen derzeit Visual C ++ bzw. GCC.


Sie können den Compiler festlegen, indem Sie CMAKE_C_COMPILER und CMAKE_CXX_COMPILER auf den Pfad zu clang oder clang ++ setzen. +1 für Klirren.
Zaffy

Warum sollte es dich interessieren? Clang ist sehr GCC-ähnlich, in Bezug auf akzeptierte Compiler-Optionen ...
Basile Starynkevitch

2
@BasileStarynkevitch Da wir MSVC unterstützten, mussten wir Clang erkennen, damit wir wussten, ob wir die GCC-ähnlichen Optionen oder die MSVC-ähnlichen Optionen aktivieren sollten. Es ist zu lange für mich, um mich zu erinnern, aber es ist sicherlich auch möglich, dass wir Optionen verwendet haben, die auch von Clang nicht unterstützt werden.
leedm777

1
@BasileStarynkevitch - Clang vorgibt beides zu sein __GNUC__und _MSC_VER, aber es kann die gleichen Programme wie jeder Compiler nicht verbrauchen. Das Erkennen von LLVM Clang und Apple Clang ist entscheidend, um sicherzustellen, dass der Code wie erwartet kompiliert und ausgeführt wird. Ich bin es so leid, mich mit Clangs BS zu beschäftigen, dass wir die Kompilierung unter Windows einfach unterbrechen . Wir haben die Richtlinie übernommen, Benutzer bei LLVM beschweren zu lassen, damit die Clang-Entwickler ihr Verhalten ändern. Siehe auch Wie man Clang sagt, er soll aufhören, sich als andere Compiler auszugeben?
JWW

Antworten:


242

Eine zuverlässige Überprüfung besteht darin, die CMAKE_<LANG>_COMPILER_IDVariablen zu verwenden. So überprüfen Sie den C ++ - Compiler:

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

Diese funktionieren auch ordnungsgemäß, wenn ein Compiler-Wrapper wie ccache verwendet wird.

Ab CMake 3.0.0 ist der CMAKE_<LANG>_COMPILER_IDWert für von Apple bereitgestelltes Clang jetzt AppleClang. Verwenden Sie die folgenden if-Bedingungen, um sowohl den von Apple bereitgestellten als auch den regulären Clang zu testen:

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

Siehe auch die Beschreibung der AppleClang-Richtlinie .

CMake 3.15 bietet Unterstützung für das Clang-Cl- und das reguläre Clang-Frontend. Sie können die Front-End-Variante ermitteln, indem Sie die Variable überprüfen 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()

In der cmake-Dokumentation heißt es: "Dies wird zur Bestimmung des Compilers verwendet und kann sich ändern." Ansonsten wäre es perfekt :-(
leedm777

17
Ab CMake 2.8.10 ist diese Variable (endlich!) Dokumentiert. Siehe: cmake.org/cmake/help/v2.8.10/…
Nick Hutchinson

9
Beachten Sie, dass die CMAKE_CXX_COMPILER_IDVariable erst nach dem Befehl verfügbar ist project(Foo CXX).
Waldyrious

5
Und für Flaggen, die sowohl gcc als auch clang akzeptieren, verwende ichif (CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU") ... endif()
Fred Schoen

4
Wenn Sie verwirrt sind, warum Sie nicht AppleClangspezifisch erkennen können, zeigt @sakra an, dass cmake 3.0.0freigegebenAppleClang . Nur weil cmake --versionBerichte gleich oder höher nicht ausreichen, müssen Sie dies tun, cmake_minimum_required(VERSION 3.0.0)damit die 3.0.0Standards verwendet werden können!
Svenevs

2

Der Quellcode der OGRE 3D-Engine verwendet die folgende Prüfung :

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

3
Das ist nah, aber funktioniert nicht, wenn Sie ccache (dh export CXX="ccache clang++") verwenden
leedm777

4
Nah genug, ich werde es dir geben. Ich habe if ("${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1}" MATCHES ".*clang")den Ccache-Fall behandelt.
leedm777

1
Das funktioniert bei mir nicht so ${CMAKE_CXX_COMPILER} == /Library/Developer/CommandLineTools/usr/bin/c++. Die akzeptierte Antwort funktioniert.
Fred Schoen

1

Um Rechtschreibfehler zu vermeiden, verwende ich den Vergleich ohne Berücksichtigung der Groß- und Kleinschreibung, wie z.

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

Um die Regex von MATCHESGroß- und Kleinschreibung zu unterscheiden, habe ich hier alles ohne Erfolg versucht (scheint in CMake nicht unterstützt zu werden).


in der Tat, wie heute, Groß- und Kleinschreibung nicht berücksichtigen
fferri

-2

Dies ist eine etwas detailliertere Antwort für cmake-Neulinge, die von Sakras Antwort geändert wurde. Fügen Sie einfach die folgenden Zeilen an 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()

Führen Sie dann cmake .den Ordner aus, in dem sich CMakeLists.txt befindet. Dann sehen Sie eine Reihe von Ausgaben zusammen mit Ihrer Antwort.

...
-- Detecting CXX compile features
-- Detecting CXX compile features - done
GNU
-- Configuring done
-- Generating done
...
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.