Detect gcc as opposed to msvc / clang with macro

40,365

Solution 1

__GNUC__
__GNUC_MINOR__
__GNUC_PATCHLEVEL__

These macros are defined by all GNU compilers that use the C preprocessor: C, C++, Objective-C and Fortran. Their values are the major version, minor version, and patch level of the compiler, as integer constants. For example, GCC 3.2.1 will define __GNUC__ to 3, __GNUC_MINOR__ to 2, and __GNUC_PATCHLEVEL__ to 1. These macros are also defined if you invoke the preprocessor directly.

Also:

__GNUG__

The GNU C++ compiler defines this. Testing it is equivalent to testing (__GNUC__ && __cplusplus).

Source

Apparently, clang uses them too. However it also defines:

__clang__
__clang_major__
__clang_minor__
__clang_patchlevel__

So you can do:

#ifdef __GNUC__
    #ifndef __clang__
...

Or even better (note the order):

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

Solution 2

With Boost, this becomes very simple:

#include <boost/predef.h>
#if BOOST_COMP_GNUC
// do this *only* for gcc
#endif

See also the Using the predefs section of the boost documentation.

(credit to rubenvb who mentioned this in a comment, to Alberto M for adding the include, and to Frederik Aalund for correcting #ifdef to #if)

Solution 3

I use this define:

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

And test with it:

#if GCC_COMPILER
...
#endif
Share:
40,365
ValarDohaeris
Author by

ValarDohaeris

Updated on July 05, 2022

Comments

  • ValarDohaeris
    ValarDohaeris 11 months

    I am working on a project that has been built with both gcc and msvc so far. We recently started building with clang as well.

    There are some parts in the code, where platform-specific things are done:

    #ifndef _WIN32
    // ignore this in msvc
    #endif
    

    Since gcc has previously been the only non-windows build, this was equivalent to saying "do this only for gcc". But now it means "do this only for gcc and clang".

    However there are still situations, where I would like to handle something specifically for gcc, and not for clang. Is there a simple and robust way to detect gcc, i.e.

    #ifdef ???
    // do this *only* for gcc
    #endif
    
  • rubenvb
    rubenvb over 8 years
    These things are all collected in the much more robust Boost.Predef, and the (now outdated) original wiki that sprung that Boost library is located here. Note that the Intel compiler will define __GNUC__ or _MSC_VER on the relevant platforms as well.
  • Peter Cordes
    Peter Cordes over 6 years
    All compilers that support the GNU C set of language extensions define those macros, right down to __GNUC_PATCHLEVEL__. So to detect support for a specific GNU C feature on any compiler, you check those macros. On gcc itself, they also map to the actual version of the compiler you're using, but they're best used to tell you what version of the GNU C language is supported, more than the compiler type / version.
  • Alberto M
    Alberto M about 6 years
    The header to include to get the symbol is <boost/predef.h>.
  • Frederik Aalund
    Frederik Aalund over 5 years
    You're supposed to use #if BOOST_COMP_GNUC and not #ifdef since the macro is always defined (but may be zero). See boost.org/doc/libs/1_66_0/doc/html/predef/…
  • ValarDohaeris
    ValarDohaeris over 5 years
    Yes, thanks for pointing it out, I thought I tested this when I first posted the answer, but it looks like #ifdef probably never worked, at least not for boost versions 1.55 or later.
  • Peter Cordes
    Peter Cordes over 4 years
    That won't exclude ICC.
  • Ayxan Haqverdili
    Ayxan Haqverdili about 4 years
    @PeterCordes why not
  • Peter Cordes
    Peter Cordes about 4 years
    @Ayxan: because ICC supports GNU extensions, and thus defines __GNUC__. You'd also have to check for !defined(__INTEL_COMPILER), like for clang. software.intel.com/en-us/forums/intel-c-compiler/topic/28180‌​2
  • SimonC
    SimonC almost 4 years
    Note that using Boost isn't always the correct solution. Boost can be handy, indeed, but thanks to its size and complexity, can add a large amount of overhead.#
  • Knitschi
    Knitschi about 2 years
    This does not seem to work when using clang-cl. In this case __clang__ and _MSC_VER is defined.