300

Is there a way for gcc/g++ to dump its default preprocessor defines from the command line? I mean things like __GNUC__, __STDC__, and so on.

rogerdpack
  • 62,887
  • 36
  • 269
  • 388
Anycorn
  • 50,217
  • 42
  • 167
  • 261

6 Answers6

379

Yes, use -E -dM options instead of -c. Example (outputs them to stdout):

 echo | gcc -dM -E -
 echo | clang -dM -E -

For C++

 echo | g++ -dM -E -x c++ -
 echo | clang++ -dM -E -x c++ -

From the gcc manual:

Instead of the normal output, generate a list of `#define' directives for all the macros defined during the execution of the preprocessor, including predefined macros. This gives you a way of finding out what is predefined in your version of the preprocessor. Assuming you have no file foo.h, the command

touch foo.h; cpp -dM foo.h

will show all the predefined macros.

If you use -dM without the -E option, -dM is interpreted as a synonym for -fdump-rtl-mach.

proski
  • 3,603
  • 27
  • 27
philant
  • 34,748
  • 11
  • 69
  • 112
  • 5
    gcc exists on systems where /dev/null means nothing. – Pavel P Jan 12 '14 at 01:29
  • 6
    @Pavel then you can use an empty file, either with gcc or the preprocessor - cpp. – philant Jan 12 '14 at 09:16
  • 23
    I added a more portable approach as an alternative answer: `echo | gcc -dM -E -` works on windows as well. – Pavel P Jan 13 '14 at 20:30
  • 4
    Is it possible to determine where (i.e., in which file) those defines came from? – edam Apr 17 '14 at 14:18
  • 2
    @edam To determine source of macro, look here: http://stackoverflow.com/questions/11257455/how-to-find-the-source-of-some-macros – Mark Lakata Jan 27 '17 at 00:40
  • 3
    Alternatively, on Windows, `cpp -dM -E - < NUL` can be used. – René Nyffenegger Mar 08 '17 at 07:41
  • 3
    Don't forget the '-x c++' command line flag if you're printing c++ define macros. The complete command is: 'g++ -x c++ -dM -E - < /dev/null' for C++ specific macros. –  Nov 28 '17 at 00:21
  • 1
    One of the most useful answers, ever. I keep coming back here to get the incantation. – Mark Adler Dec 17 '18 at 18:40
  • How do I find the list of available macros like \__FILE__ \__DATE__ \__TIMESTAMP__ etc? A few are listed in the docs [here](https://gcc.gnu.org/onlinedocs/cpp/Standard-Predefined-Macros.html#Standard-Predefined-Macros) but is that it? – Eric Nelson Feb 12 '20 at 15:35
  • @EricNelson I think it is – philant Feb 13 '20 at 09:29
  • Does armcc have a similar feature? – AlphaGoku Apr 17 '20 at 09:40
  • Note that you can add command line arguments to the command given in this answer, some may add defines which will then show up. For example, adding `-mavx2` adds the defines `#define __AVX__ 1` `#define __AVX2__ 1` on x86 architectures. – doug65536 Oct 23 '20 at 02:41
  • See also [this question](https://stackoverflow.com/q/27686382/1593077) about doing the same with NVCC for CUDA. – einpoklum Jun 25 '21 at 19:12
  • No need to rely on shell redirection. *nix: `gcc -dM -E /dev/null`, Windows: `gcc -dM -E nul`. Specify an input file instead of stdin. – Cameron Tacklind Oct 06 '22 at 23:24
  • I've tried this with a few builds of `g++`, and `__cplusplus` is never included in the output, even though the standard mandates that it be defined. – AJM Mar 10 '23 at 09:31
  • 1
    Just saw user402642's comment above. Adding -x c++ causes `__cplusplus` to be shown in the output. – AJM Mar 10 '23 at 13:34
  • This has been working fine for me on most gcc, but MinGW's gcc 12.2.0 doesn't print anything (works, compiles, does its job, `-dumpersion` works but `-dM` doesn't). – vesperto Mar 31 '23 at 12:20
  • Using `-x c++` obviates the need for switching to the `g++` and `clang++` frontends respectively (i.e. `gcc` and `clang` will also work this way). The reason is that without a file name the language cannot be deduced. – 0xC0000022L May 03 '23 at 10:47
86

I usually do it this way:

$ gcc -dM -E - < /dev/null

Note that some preprocessor defines are dependent on command line options - you can test these by adding the relevant options to the above command line. For example, to see which SSE3/SSE4 options are enabled by default:

$ gcc -dM -E - < /dev/null | grep SSE[34]
#define __SSE3__ 1
#define __SSSE3__ 1

and then compare this when -msse4 is specified:

$ gcc -dM -E -msse4 - < /dev/null | grep SSE[34]
#define __SSE3__ 1
#define __SSE4_1__ 1
#define __SSE4_2__ 1
#define __SSSE3__ 1

Similarly you can see which options differ between two different sets of command line options, e.g. compare preprocessor defines for optimisation levels -O0 (none) and -O3 (full):

$ gcc -dM -E -O0 - < /dev/null > /tmp/O0.txt
$ gcc -dM -E -O3 - < /dev/null > /tmp/O3.txt
$ sdiff -s /tmp/O0.txt /tmp/O3.txt 
#define __NO_INLINE__ 1        <
                               > #define __OPTIMIZE__ 1
Paul R
  • 208,748
  • 37
  • 389
  • 560
49

Late answer - I found the other answers useful - and wanted to add a bit extra.


How do I dump preprocessor macros coming from a particular header file?

echo "#include <sys/socket.h>" | gcc -E -dM -

or (thanks to @mymedia for the suggestion):

gcc -E -dM -include sys/socket.h - < /dev/null

In particular, I wanted to see what SOMAXCONN was defined to on my system. I know I could just open up the standard header file, but sometimes I have to search around a bit to find the header file locations. Instead I can just use this one-liner:

$ gcc -E -dM -include sys/socket.h - < /dev/null | grep SOMAXCONN
#define SOMAXCONN 128
$ 
Digital Trauma
  • 15,475
  • 3
  • 51
  • 83
  • 6
    you can use [-include](https://gcc.gnu.org/onlinedocs/gcc-9.2.0/gcc/Preprocessor-Options.html) compiler option to avoid pipes – mymedia Mar 11 '20 at 09:35
  • You can specify `/dev/null` (or `nul` on Windows) as the "input file" (instead of the `-`, which means `stdin`) and not need any pipe or `<`. – Cameron Tacklind Oct 06 '22 at 23:30
34

The simple approach (gcc -dM -E - < /dev/null) works fine for gcc but fails for g++. Recently I required a test for a C++11/C++14 feature. Recommendations for their corresponding macro names are published at https://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations. But:

g++ -dM -E - < /dev/null | fgrep __cpp_alias_templates

always fails, because it silently invokes the C-drivers (as if invoked by gcc). You can see this by comparing its output against that of gcc or by adding a g++-specific command line option like (-std=c++11) which emits the error message cc1: warning: command line option ‘-std=c++11’ is valid for C++/ObjC++ but not for C.

Because (the non C++) gcc will never support "Templates Aliases" (see http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2258.pdf) you must add the -x c++ option to force the invocation of the C++ compiler (Credits for using the -x c++ options instead of an empty dummy file go to yuyichao, see below):

g++ -dM -E -x c++ /dev/null | fgrep __cpp_alias_templates

There will be no output because g++ (revision 4.9.1, defaults to -std=gnu++98) does not enable C++11-features by default. To do so, use

g++ -dM -E -x c++ -std=c++11 /dev/null | fgrep __cpp_alias_templates

which finally yields

#define __cpp_alias_templates 200704

noting that g++ 4.9.1 does support "Templates Aliases" when invoked with -std=c++11.

hermannk
  • 745
  • 8
  • 12
  • 8
    You don't have to use a dummy file. GCC supports the `-x` argument so `g++ -x c++ -dM -E -std=c++11 - < /dev/null | grep cpp` should work. – yuyichao Feb 16 '15 at 03:56
  • @yuyichao Thank you, this makes it easier to use. I wasn't aware of the -x option. Upvoted your comment and integrated it into the original answer. – hermannk Feb 17 '15 at 07:43
26

A portable approach that works equally well on Linux or Windows (where there is no /dev/null):

echo | gcc -dM -E -

For c++ you may use (replace c++11 with whatever version you use):

echo | gcc -x c++ -std=c++11 -dM -E -

It works by telling gcc to preprocess stdin (which is produced by echo) and print all preprocessor defines (search for -dletters). If you want to know what defines are added when you include a header file you can use -dD option which is similar to -dM but does not include predefined macros:

echo "#include <stdlib.h>" | gcc -x c++ -std=c++11 -dD -E -

Note, however, that empty input still produces lots of defines with -dD option.

Pavel P
  • 15,789
  • 11
  • 79
  • 128
  • 7
    @rubenvb it's irrelevant. the point is to have cmd line that works equally well on windows and unix at least. If you use `NUL`, you are back to square one: it won't work on systems that do not have it. – Pavel P Jan 29 '14 at 18:42
  • 4
    adding full answer for C++, works on both Windows and Linux (although `sort` behaves little different): `echo | gcc -x c++ -std=c++17 -dM -E - | sort` – Xeverous Jul 30 '17 at 11:56
  • This produces empty output in git-bash. – Mr. Developerdude Jul 25 '18 at 19:45
  • @LennartRolland does it have gcc? In my git-bash I cannot run gcc – Pavel P Jul 26 '18 at 00:59
  • @pavel I use mingw32 gcc that comes with Qt5 binary distribution for windows. – Mr. Developerdude Jul 26 '18 at 07:23
  • Don't know what to say. Mingw64 that comes with msys2 works for me: `echo | x86_64-w64-mingw32-gcc.exe -dM -E -`. Try to run it in cmd.exe to verify that it all works properly? – Pavel P Jul 26 '18 at 21:53
4

While working in a big project which has complex build system and where it is hard to get (or modify) the gcc/g++ command directly there is another way to see the result of macro expansion. Simply redefine the macro, and you will get output similiar to following:

file.h: note: this is the location of the previous definition
#define MACRO current_value