133

How can I tell where g++ was able to find an include file? Basically if I

#include <foo.h>

g++ will scan the search path, using any include options to add or alter the path. But, at the end of days, is there a way I can tell the absolute path of foo.h that g++ chose to compile? Especially relevant if there is more than one foo.h in the myriad of search paths.

Short of a way of accomplishing that... is there a way to get g++ to tell me what its final search path is after including defaults and all include options?

jww
  • 97,681
  • 90
  • 411
  • 885
harschware
  • 13,006
  • 17
  • 55
  • 87
  • 1
    Related: is there any way to tell which parent include file(s) a child include file was included from? I.e. to show the included-from graph (Hint: gcc -E isn't quite there... might be processed to yield it.) – Krazy Glew Jan 08 '13 at 22:53

6 Answers6

154
g++ -H ...

will also print the full path of include files in a format which shows which header includes which

Bulletmagnet
  • 5,665
  • 2
  • 26
  • 56
  • 10
    This seems to be more helpful than -M in my experience. I like the hierarchical display of what includes what. – Brian Minton Dec 18 '13 at 13:17
  • 2
    This is the best answer. You can add it to your build process without changing anything else. – Timmmm Jun 03 '15 at 13:29
  • 4
    This really answers the question more than the accepted answer. Only unfortunate problem is that I couldn't get it to stop Clang from trying to compile the file normally, so I ended up using `clang++ -MM -H` (which is a slightly useful combination). – rookie1024 Feb 17 '17 at 17:36
  • @rookie1024 Use `clang++ -H -fsyntax-only ...` if you would like to avoid generating output files (works for `gcc` too). – Lekensteyn Apr 18 '18 at 10:16
  • 1
    This looks like the counterpart of `/showIncludes` in MSVC. – Thomson Sep 22 '18 at 00:44
  • With Clang, you can also get repeated includes with `-H -fshow-skipped-includes`. – Paul Groke May 21 '22 at 12:00
93

This will give make dependencies which list absolute paths of include files:

gcc  -M showtime.c

If you don't want the system includes (i.e. #include <something.h>) then use:

gcc  -MM showtime.c
Viet
  • 17,944
  • 33
  • 103
  • 135
Sodved
  • 8,428
  • 2
  • 31
  • 43
  • 20
    It should be noted that if you use in conjunction with "-o myObj.o", the output, not the compiled binary, goes into "myObj.o". -M has an implicit -E, so the compilation is not peformed. I found -MD is a very useful option instead, it performs the compile and puts the output in myObj.d instead. Making a suitable param for just prepending to your compile line without strange effects like *.o now contains the output instead of the binary. Thanks for your help. – harschware Apr 29 '11 at 17:33
  • All related gcc options are described [here](https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/4/html/Using_the_GNU_Compiler_Collection/preprocessor-options.html). – akhan Sep 20 '19 at 23:20
13

Sure use

g++ -E -dI  ... (whatever the original command arguments were)
wallyk
  • 56,922
  • 16
  • 83
  • 148
  • 3
    There are several benefits to this solution: 1. You can discover multiple inclusions of a single header file (-H and -M print each included file only once) 2. You can see where it is included (name and line number of the original include instruction). 3. Thereby you can reliably(!) distinguish whether a header is included directly or indirectly or both (This is important for cleanups.) – hagello Dec 14 '18 at 14:19
  • @hagello Unfortunately with `-E -dI`, GCC only gives you the raw source line of the include if the header was already included - not the annotation with the resolved full path. For manual analysis this may be enough. But for automated analysis it makes things awkward. – Paul Groke May 21 '22 at 11:54
7

If you use -MM or one of the related options (-M, etc), you get just the list of headers that are included without having all the other preprocessor output (which you seem to get with the suggested g++ -E -dI solution).

You can also use the -H option. It prints the headers as they are included with one dot . as a prefix for each level of nesting in the headers. What you include directly is prefixed by a dot and a space; files that those files include are prefixed with two dots and a space, and so on. This can be helpful. The output appears on stderr rather than stdout. (See also the answer, which suggests -H but doesn't include information about the format of the output.)

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • `g++ -MM t.cc` shows no inclusion at all, just `t.o: t.cc`. Does it need something else? – wallyk Apr 29 '11 at 16:59
  • 6
    Nice - for completeness, you can get similar with MSVC using the `/showIncludes` option. MSVC will even indent to show you the nesting of headers (I dont see that with `-M` on GCC). – Michael Burr Apr 29 '11 at 17:02
7

If your build process is very complicated...

constexpr static auto iWillBreak = 
#include "where/the/heck/is/this/file.h"

This will (almost certainly) cause a compilation error near the top of the file in question. That should show you a compiler error with the path the compiler sees.

Obviously this is worse than the other answers, but sometimes this kind of hack is useful.

sudo rm -rf slash
  • 1,156
  • 2
  • 16
  • 27
1

For MSVC you can use the /showInclude option, which will display the files that are included.


(This was stated in a comment of Michael Burr on this answer but I wanted to make it more visible and therefore added it as a separate answer.)


Usability note: The compiler will emit this information to the standard error output which seems to be suppressed by default when using the windows command prompt. Use 2>&1 to redirect stderr to stdout to see it nonetheless.

Raven
  • 2,951
  • 2
  • 26
  • 42