207

When I compile a very simple source file with gcc I don't have to specify the path to standard include files such as stdio or stdlib.

How does GCC know how to find these files?

Does it have the /usr/include path hardwired inside, or it will get the paths from other OS components?

5 Answers 5

315

In order to figure out the default paths used by gcc/g++, as well as their priorities, you need to examine the output of the following commands:

  1. For C:
echo | gcc -xc -E -v -
  1. For C++:
echo | gcc -xc++ -E -v -

The credit goes to Qt Creator team.

Here's a breakdown of the flags:

  • -x selects the language, C or C++ respectively

  • -E makes gcc to run the preprocessor only, so no compilation takes place

  • -v prints all the commands run, which is the key to dumping the standard paths

  • - is the "input file" to preprocess, as a convention - stands for stdin (or stdout, depending on the context);

    echo | feeds an empty string to gcc so effectively we preprocess an empty file generated on the fly

Here's a nice explaining it in more detail: https://explainshell.com/explain?cmd=echo+%7C+gcc+-xc+-E+-v+-

Sign up to request clarification or add additional context in comments.

11 Comments

cpp -v /dev/null -o /dev/null
@Ihor - what does the - at the end of the command line do? I've seen questions about these dashes elesewhere on Stack Overflow, but their meaning varies by command. As far as I can tell when experimenting with Cygwin, it means gcc will do nothing and ignore all input except Ctrl-C. But gcc in an actual Bash shell might behave very differently.
- refers to stdin here. So you could also do: echo | gcc -xc++ -E -v - and echo | gcc -xc++ -E -v -
@palapapa, I've updated the answer, hope it helps
@palapapa, I suppose it depends on the version of GCC. I tried omitting some of the flags from the above set, and even though there was some output each time, none of them contained the include ... search starts here piece which is the one we are looking for. Running on Ubuntu 22.04, GCC 11.3.0
|
53

There is a command with a shorter output, which allows to automatically cut the include pathes from lines, starting with a single space:

$ echo | gcc -Wp,-v -x c++ - -fsyntax-only
ignoring nonexistent directory "/usr/lib/gcc/x86_64-redhat-linux/4.8.2/include-fixed"
ignoring nonexistent directory "/usr/lib/gcc/x86_64-redhat-linux/4.8.2/../../../../x86_64-redhat-linux/include"
#include "..." search starts here:
#include <...> search starts here:
 /usr/lib/gcc/x86_64-redhat-linux/4.8.2/../../../../include/c++/4.8.2
 /usr/lib/gcc/x86_64-redhat-linux/4.8.2/../../../../include/c++/4.8.2/x86_64-redhat-linux
 /usr/lib/gcc/x86_64-redhat-linux/4.8.2/../../../../include/c++/4.8.2/backward
 /usr/lib/gcc/x86_64-redhat-linux/4.8.2/include
 /usr/local/include
 /usr/include
End of search list.

The credit goes to the libc++ front-page.

2 Comments

Use /dev/null instead of -, and you'll need no pipe
You only need to run the preprocessor, with -E, no need to run the compiler.
17

To summarise the other answers:

For C++:

c++ -xc++ /dev/null -E -Wp,-v 2>&1 | sed -n 's,^ ,,p'

For C:

cc -xc /dev/null -E -Wp,-v 2>&1 | sed -n 's,^ ,,p'

1 Comment

I would suggest to make this a community wiki.
6

Though I agree with Ihor Kaharlichenko’s answer for considering C++ and with abyss.7’s answer for the compactness of its output, they are still incomplete for the multi-arch versions of gcc because input processing depends on the command line parameters and macros.

Example:

echo | /opt/gcc-arm-none-eabi-9-2019-q4-major/bin/arm-none-eabi-g++ -specs=nano.specs -mcpu=cortex-m4 -march=armv7e-m -mthumb -mfloat-abi=soft -x c++ -E -Wp,-v\ - -fsyntax-only yields

⋮
/opt/gcc-arm-none-eabi-9-2019-q4-major/bin/../arm-none-eabi/include/newlib-nano                                                                                                              
/opt/gcc-arm-none-eabi-9-2019-q4-major/bin/../lib/gcc/arm-none-eabi/9.2.1/../../../../arm-none-eabi/include/c++/9.2.1                                                                        
/opt/gcc-arm-none-eabi-9-2019-q4-major/bin/../lib/gcc/arm-none-eabi/9.2.1/../../../../arm-none-eabi/include/c++/9.2.1/arm-none-eabi/thumb/v7e-m/nofp                                         
/opt/gcc-arm-none-eabi-9-2019-q4-major/bin/../lib/gcc/arm-none-eabi/9.2.1/../../../../arm-none-eabi/include/c++/9.2.1/backward                                                               
/opt/gcc-arm-none-eabi-9-2019-q4-major/bin/../lib/gcc/arm-none-eabi/9.2.1/include                                                                                                            
 /opt/gcc-arm-none-eabi-9-2019-q4-major/bin/../lib/gcc/arm-none-eabi/9.2.1/include-fixed                                                                                                      
/opt/gcc-arm-none-eabi-9-2019-q4-major/bin/../lib/gcc/arm-none-eabi/9.2.1/../../../../arm-none-eabi/include                                                                                  
⋮

whereas echo | /opt/gcc-arm-none-eabi-9-2019-q4-major/bin/arm-none-eabi-g++ -x c++ -E -Wp,-v - -fsyntax-only yields

⋮
/opt/gcc-arm-none-eabi-9-2019-q4-major/bin/../lib/gcc/arm-none-eabi/9.2.1/../../../../arm-none-eabi/include/c++/9.2.1                                                                        
/opt/gcc-arm-none-eabi-9-2019-q4-major/bin/../lib/gcc/arm-none-eabi/9.2.1/../../../../arm-none-eabi/include/c++/9.2.1/arm-none-eabi                                                          
/opt/gcc-arm-none-eabi-9-2019-q4-major/bin/../lib/gcc/arm-none-eabi/9.2.1/../../../../arm-none-eabi/include/c++/9.2.1/backward                                                               
/opt/gcc-arm-none-eabi-9-2019-q4-major/bin/../lib/gcc/arm-none-eabi/9.2.1/include                                                                                                            
/opt/gcc-arm-none-eabi-9-2019-q4-major/bin/../lib/gcc/arm-none-eabi/9.2.1/include-fixed                                                                                                      
/opt/gcc-arm-none-eabi-9-2019-q4-major/bin/../lib/gcc/arm-none-eabi/9.2.1/../../../../arm-none-eabi/include                                                                                  
⋮

The former invocation utilizes newlib (see lines 1 and 3 of the output), the latter goes with the standard includes. The common files at the end of the list are an example for the usage of include_next.

Bottom line: Always consider all macros and compiler options when printing the include directories.

Comments

2

Just run the following to list the default search paths:

$(gcc -print-prog-name=cc1) -v

4 Comments

This doesn't list the include paths. Only programs path and libraries path
cc1 usually can't be called directly because it is an internal command which is not on the PATH. Maybe you want to edit your answer to describe where to find the file.
bash: syntax error near unexpected token `-v'
It only catches half of the include dirs that are found by echo | gcc -Wp,-v -x c++ - -fsyntax-only

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.