2015-01-27 22 views
24

Pracuję nad projektem, który do tej pory został zbudowany z gcc i msvc. Niedawno zaczęliśmy też budować z klangiem.Wykryj gcc w przeciwieństwie do msvc/clang z makro

Istnieją pewne elementy w kodzie, gdzie rzeczy dla konkretnych platform są wykonywane:

#ifndef _WIN32 
// ignore this in msvc 
#endif 

Ponieważ gcc była wcześniej jedynym nie-windows budowę, było to równoznaczne z powiedzeniem „to zrobić tylko dla gcc ". Ale teraz oznacza to "rób to tylko dla gcc i clang".

Jednak nadal istnieją sytuacje, w których chciałbym obsłużyć coś specjalnie dla gcc, a nie dla klang. Czy istnieje prosty i solidny sposób wykryć gcc, tj

#ifdef ??? 
// do this *only* for gcc 
#endif 
+0

Dlaczego budujesz z mnóstwem kompilatorów? –

+0

możliwy duplikat [Jak do #ifdef przez CompilerType? GCC lub VC++] (http://stackoverflow.com/questions/15127522/how-to-ifdef-by-compilertype-gcc-or-vc) – sashoalm

+0

nie, inne pytanie nawet nie wspomina o klang ... – ValarDohaeris

Odpowiedz

34
__GNUC__ 
__GNUC_MINOR__ 
__GNUC_PATCHLEVEL__ 

Makra te są definiowane przez wszystkich kompilatorów GNU wykorzystujących preprocesora C: C, C++, Objective-C i Fortran. Ich wartości to główna wersja, wersja drugorzędna i poziom poprawki kompilatora, jako stałe całkowite. Na przykład GCC 3.2.1 zdefiniuje __GNUC__ na 3, __GNUC_MINOR__ na 2, a __GNUC_PATCHLEVEL__ na 1. Te makra są również zdefiniowane, jeśli bezpośrednio wywołasz preprocesor.

również:

__GNUG__ 

GNU kompilator C++ definiuje go. Testowanie jest równoznaczne z testowaniem (__GNUC__ & & __cplusplus).

Source

Najwyraźniej clang używa ich zbyt. Jednak to określa również:

__clang__ 
__clang_major__ 
__clang_minor__ 
__clang_patchlevel__ 

Więc można zrobić:

#ifdef __GNUC__ 
    #ifndef __clang__ 
... 

Albo jeszcze lepiej (uwaga na zamówienie):

#if defined(__clang__) 
.... 
#elif defined(__GNUC__) || defined(__GNUG__) 
.... 
#elif defined(_MSC_VER) 
.... 
+3

Te rzeczy są zebrane w dużo bardziej rozbudowany sposób [Boost.Predef] (http: //www.boost .org/doc/libs/release/libs/predef/doc/html/index.html) i (obecnie nieaktualne) oryginalne wiki, które wyskoczyło z biblioteki Boost [tutaj] (http://sourceforge.net/p/predef/wiki/Compilers /). Należy zauważyć, że kompilator Intel zdefiniuje również '__GNUC__' lub' _MSC_VER' na odpowiednich platformach. – rubenvb

+0

Wszystkie kompilatory obsługujące zestaw rozszerzeń językowych GNU C definiują te makra, aż do "__GNUC_PATCHLEVEL__". Aby wykryć obsługę określonej funkcji GNU C w dowolnym kompilatorze, należy sprawdzić te makra. W samym gcc mapują one również do aktualnej wersji używanego kompilatora, ale najlepiej użyć ich, aby powiedzieć, która wersja języka GNU jest obsługiwana, bardziej niż typ/wersja kompilatora. –

1

__GNUG__ może być najlepszym - patrz here. To testy specjalnie dla GNU C++, a nie tylko kompilator GNU C/C++/FORTRAN na __GNUC__ - tj. "równoważny testowaniu (__GNUC__ && __cplusplus)".

+1

Clang również definiuje zarówno '__GNUC__' oraz' __cplusplus', więc to nie pomaga. – user2023370

6

Z Boost to staje się bardzo prosta:

#include <boost/predef.h> 

#if BOOST_COMP_GNUC 
// do this *only* for gcc 
#endif 

Zobacz także sekcję Using the predefs dokumentacji boost.

(kredyt do rubenvb który wspomniał o tym w komentarzu, Alberto M dodając include oraz Frederik Aalund do korygowania #ifdef do #if)

+0

Nagłówek, który należy dołączyć, aby uzyskać symbol, to ''. –

+0

Powinieneś użyć '#if BOOST_COMP_GNUC' oraz * not *' # ifdef', ponieważ makro jest * zawsze * zdefiniowane (ale może wynosić zero). Zobacz http://www.boost.org/doc/libs/1_66_0/doc/html/predef/using_the_predefs.html –

+0

Tak, dzięki za wskazanie, myślałem, że testowałem to, kiedy po raz pierwszy opublikowałem odpowiedź, ale wygląda jak '# ifdef' prawdopodobnie nigdy nie działało, przynajmniej nie dla wersji boost 1.55 lub nowszej. – ValarDohaeris

1

Używam tego określić:

#define GCC_COMPILER (defined(__GNUC__) && !defined(__clang__)) 

I przetestuj:

#if GCC_COMPILER 
... 
#endif 
Powiązane problemy