gcc在哪里查找C和C++头文件?

222

在Unix系统中,gcc在哪里查找头文件?

今天早上我花了一点时间寻找一些系统头文件,所以我认为将这些信息放在这里会很有用。


顺便说一下,如果你想知道.h文件的位置,请参见https://dev59.com/nW025IYBdhLWcg3wvIcn#18593344。 - bronze man
10个回答

263
`gcc -print-prog-name=cc1plus` -v

这个命令询问gcc正在使用哪个C++预处理器,然后询问该预处理器在哪里查找包含文件。

您将获得有关您特定设置的可靠答案。

同样,对于C预处理器:

`gcc -print-prog-name=cpp` -v

3
“`s”是什么意思?我发现很难搜索到相关信息。 - mijiturka
8
在Bash中,反引号(也称为重音符号)用于将命令的输出插入到另一个命令中。例如,可以使用反引号运算符执行一个命令,并将其输出作为另一个命令的参数,如command1 command2``。在较新的版本中,推荐使用 $() 代替反引号进行命令替换。 - Drew Dormann
5
我猜C语言的预处理器cpp而不是cc1?在我的Debian Jessie系统上,通过运行命令$(gcc -print-prog-name=cpp) -v,会得到一个额外的路径/usr/include/x86_64-linux-gnu(正确的)。 - wlnirvana
4
如果您希望程序不会等待输入,可以将输入重定向到 /dev/null,这样就可以使用以下命令:\gcc -print-prog-name=cc1` -v < /dev/null`。 - Steve Jorgensen
但是你无法在shell脚本中按Ctrl+D。 - Steve Jorgensen
显示剩余4条评论

48
此外,gcc会在-I选项之后指定的目录中查找文件。



5
请检查您的字体!这个回答使用的是大写字母"I"而不是小写字母"l"。 - user2423516
4
-I 是用于包含角括号中的头文件 <anglebracketed.h>,而 -iquote 则用于包含双引号中的头文件 "quotedfiles.h"。 - jcomeau_ictx

37

您可以创建一个试图包含虚假系统头文件的文件。如果您在这样的源代码上以详细模式运行gcc,则它将列出所有系统包含位置,因为它寻找虚假标头。

$ echo "#include <bogus.h>" > t.c; gcc -v t.c; rm t.c

[..]

#include "..." search starts here:
#include <...> search starts here:
 /usr/local/include
 /usr/lib/gcc/i686-apple-darwin9/4.0.1/include
 /usr/include
 /System/Library/Frameworks (framework directory)
 /Library/Frameworks (framework directory)
End of search list.

[..]

t.c:1:32: error: bogus.h: No such file or directory

5
如果你只说“使用-v选项”,那会更有帮助。 - Jay Conrod
如果您使用“-v”而没有包含不存在的系统头文件的C文件,那么您不会导致gcc遍历所有包含路径。 我的答案关键在于bogus.h被列为系统头文件。 - diciu
10
不使用临时文件: echo "#include <bogus.h>" | gcc -v -x c - - thejoshwolfe
2
gcc -v -E - < /dev/nullcpp -v < /dev/null 就足够了。你只需要让预处理器运行,它看到的输入是无关紧要的。(搜索路径在启动时打印,在它查看输入之前。) - zwol
@zwol,谢谢你的回复,这样更加直接明了,我认为它应该作为一个独立的答案。 - Etheryte
显示剩余2条评论

20

GCC手册CPP部分指出头文件可以位于以下目录中。来自搜索路径页面:

GCC在几个不同的位置查找头文件。在普通的Unix系统上,如果您没有另外指示,它将在以下位置查找使用#include请求的头文件:

 /usr/local/include
 libdir/gcc/target/version/include
 /usr/target/include
 /usr/include

对于 C++ 程序,它还会首先查找 /usr/include/g++-v3

这对于您当前版本的gcc来说是可以的。它实际查找的目录取决于构建gcc时指定的选项。有关更好的解决方案,请参见Shmoopty的答案。 - Martin York
我的C++头文件在:/usr/include/c++/4.0.0。 - Martin York
3
@Martin: 你是老派的。我的文件在 /usr/include/c++/4.2 中 :) - Bill the Lizard
1
这是递归完成的吗?也就是说,如果我在/usr/include/subdir/中有一个库,它会被捕捉到吗? - Base64__
1
@Base64__ 是的,您可以将头文件排列在 /usr/include 下的子目录中,它们会被找到。 - Bill the Lizard

13

要让GCC打印出完整的目录集合,在寻找系统头文件时,使用以下方法调用:

如有需要,请参考翻译。

$ LC_ALL=C gcc -v -E -xc - < /dev/null 2>&1 | 
  LC_ALL=C sed -ne '/starts here/,/End of/p'

这将会产生以下形式的输出

#include "..." search starts here:
#include <...> search starts here:
 /usr/lib/gcc/x86_64-linux-gnu/5/include
 /usr/local/include
 /usr/lib/gcc/x86_64-linux-gnu/5/include-fixed
 /usr/include/x86_64-linux-gnu
 /usr/include
End of search list.
如果你在命令行上使用了-I家族选项,它们会影响输出内容。(sed命令是为了清除此调用打印的所有其他垃圾,LC_ALL=C是为了确保sed命令能够运行--"starts here"和"End of search list"短语已被翻译,如果我没记错的话。)

12
g++ -print-search-dirs
gcc -print-search-dirs

7
这些命令会打印出链接库和编译器内部组件的默认搜索路径;它们并不涉及头文件的信息。 - zwol

9

编译器查找头文件的路径集合可以通过以下命令检查:

cpp -v

如果您声明 #include "",编译器首先在源文件的当前目录中搜索,如果没有找到,则继续在上述检索到的目录中搜索。

如果您声明 #include <>,编译器直接在从上述命令获取的那些目录中搜索。

来源: http://commandlinefanatic.com/cgi-bin/showarticle.cgi?article=art026


1
这些是gcc默认查找指定头文件的目录(假设头文件用尖括号<>包含): 1. /usr/local/include/ - 用于第三方头文件。 2. /usr/include/ - 用于系统头文件。
如果您决定将自定义头文件放在上述目录之外的其他位置,则可以按如下方式包含它们: 1. 在include语句中使用带有文件路径的引号("./custom_header_files/foo.h"),而不是尖括号。 2. 在编译代码时使用-I开关。 例如:gcc -I /home/user/custom_headers/ -c foo.c -p foo.o -I开关告诉编译器首先查找-I开关指定的目录(在检查标准目录之前)。使用-I开关时,头文件可以使用尖括号包含。

1

可以通过以下方式从bash中查看C程序的(额外)包含路径:

echo $C_INCLUDE_PATH

如果这个为空,可以通过以下方式修改以添加默认的包含位置:
export C_INCLUDE_PATH=$C_INCLUDE_PATH:/usr/include

正如您所指出的,它适用于其他用户指定的目录,但对于标准的包含路径来说,它是不起作用的,这也是OP的问题所在。 - undefined

0

我的系统默认安装了gcc9,并且我已经从源代码编译了gcc12。我认为被接受的答案不正确,即 gcc -print-prog-name = cc1plus -v 不能提供真正的包含路径。

我的构建配置是

Configured with: /home/tian/playground/gcc_build_play/objdir/../gcc-12.1.0/configure --prefix=/home/tian/GCC-12.1.0 --disable-multilib

无论我将 gcc12 目录移动到我的机器上的任何位置,它都可以始终正确地包含自己的 C++ 头文件。


如果我在原始安装目录中键入./gcc -print-prog-name=cc1plus -v,它会返回:
tian@tian-B250M-Wind:~/GCC-12.1.0/bin$ `./gcc -print-prog-name=cc1plus` -v
ignoring nonexistent directory "/home/tian/GCC-12.1.0/lib/gcc/x86_64-pc-linux-gnu/12.1.0/../../../../x86_64-pc-linux-gnu/include"
#include "..." search starts here:
#include <...> search starts here:
 /home/tian/GCC-12.1.0/lib/gcc/x86_64-pc-linux-gnu/12.1.0/../../../../include/c++/12.1.0
 /home/tian/GCC-12.1.0/lib/gcc/x86_64-pc-linux-gnu/12.1.0/../../../../include/c++/12.1.0/x86_64-pc-linux-gnu
 /home/tian/GCC-12.1.0/lib/gcc/x86_64-pc-linux-gnu/12.1.0/../../../../include/c++/12.1.0/backward
 /home/tian/GCC-12.1.0/lib/gcc/x86_64-pc-linux-gnu/12.1.0/include
 /usr/local/include
 /home/tian/GCC-12.1.0/include
 /home/tian/GCC-12.1.0/lib/gcc/x86_64-pc-linux-gnu/12.1.0/include-fixed
 /usr/include
End of search list.

mv my gcc12 到 ~/Desktop/,再次运行,输出:

tian@tian-B250M-Wind:~/Desktop/GCC-12.1.0/bin$ `./gcc -print-prog-name=cc1plus` -v
ignoring nonexistent directory "/home/tian/GCC-12.1.0/include/c++/12.1.0"
ignoring nonexistent directory "/home/tian/GCC-12.1.0/include/c++/12.1.0/x86_64-pc-linux-gnu"
ignoring nonexistent directory "/home/tian/GCC-12.1.0/include/c++/12.1.0/backward"
ignoring nonexistent directory "/home/tian/GCC-12.1.0/lib/gcc/x86_64-pc-linux-gnu/12.1.0/include"
ignoring nonexistent directory "/home/tian/GCC-12.1.0/include"
ignoring nonexistent directory "/home/tian/GCC-12.1.0/lib/gcc/x86_64-pc-linux-gnu/12.1.0/include-fixed"
ignoring nonexistent directory "/home/tian/GCC-12.1.0/x86_64-pc-linux-gnu/include"
#include "..." search starts here:
#include <...> search starts here:
 /usr/local/include
 /usr/include
End of search list.

如果是这样的话,那么我使用./g++编译程序时,它应该使用/usr/include/usr/local/include中的C++头文件。但它没有。

这里省略了实验。您可以尝试使用mv重命名gcc12的任何头文件,让您的测试程序使用或向头文件添加一些垃圾代码。然后,你会看到gcc12的./g++抱怨gcc12的C++头文件,而不是我的系统gcc9的C++头文件在/usr/include/usr/local/include

因此,在这两个地方./g++都能正确找到它的gcc12 C++头文件。


所以我猜测gccg++在相对目录中查找头文件,相对于/path_to_gcc12/bin/gcc

尝试使用./g++ -g -Wall --verbose -o test test.cpp获取实际的包含路径:

tian@tian-B250M-Wind:~/Desktop/GCC-12.1.0/bin$ ./g++ -g -Wall --verbose -o test test.cpp
Using built-in specs.
COLLECT_GCC=./g++
COLLECT_LTO_WRAPPER=/home/tian/Desktop/GCC-12.1.0/bin/../libexec/gcc/x86_64-pc-linux-gnu/12.1.0/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: /home/tian/playground/gcc_build_play/objdir/../gcc-12.1.0/configure --prefix=/home/tian/GCC-12.1.0 --disable-multilib
Thread model: posix
Supported LTO compression algorithms: zlib
gcc version 12.1.0 (GCC) 
COLLECT_GCC_OPTIONS='-g' '-Wall' '-v' '-o' 'test' '-shared-libgcc' '-mtune=generic' '-march=x86-64'
 /home/tian/Desktop/GCC-12.1.0/bin/../libexec/gcc/x86_64-pc-linux-gnu/12.1.0/cc1plus -quiet -v -imultiarch x86_64-linux-gnu -iprefix /home/tian/Desktop/GCC-12.1.0/bin/../lib/gcc/x86_64-pc-linux-gnu/12.1.0/ -D_GNU_SOURCE test.cpp -quiet -dumpbase test.cpp -dumpbase-ext .cpp -mtune=generic -march=x86-64 -g -Wall -version -o /tmp/ccrg0qhG.s
GNU C++17 (GCC) version 12.1.0 (x86_64-pc-linux-gnu)
        compiled by GNU C version 12.1.0, GMP version 6.2.1, MPFR version 4.1.0, MPC version 1.2.1, isl version isl-0.24-GMP

GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
ignoring nonexistent directory "/home/tian/Desktop/GCC-12.1.0/bin/../lib/gcc/x86_64-pc-linux-gnu/12.1.0/../../../../x86_64-pc-linux-gnu/include"
ignoring duplicate directory "/home/tian/Desktop/GCC-12.1.0/bin/../lib/gcc/../../lib/gcc/x86_64-pc-linux-gnu/12.1.0/../../../../include/c++/12.1.0"
ignoring duplicate directory "/home/tian/Desktop/GCC-12.1.0/bin/../lib/gcc/../../lib/gcc/x86_64-pc-linux-gnu/12.1.0/../../../../include/c++/12.1.0/x86_64-pc-linux-gnu"
ignoring duplicate directory "/home/tian/Desktop/GCC-12.1.0/bin/../lib/gcc/../../lib/gcc/x86_64-pc-linux-gnu/12.1.0/../../../../include/c++/12.1.0/backward"
ignoring duplicate directory "/home/tian/Desktop/GCC-12.1.0/bin/../lib/gcc/../../lib/gcc/x86_64-pc-linux-gnu/12.1.0/include"
ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu"
ignoring duplicate directory "/home/tian/Desktop/GCC-12.1.0/bin/../lib/gcc/../../lib/gcc/x86_64-pc-linux-gnu/12.1.0/include-fixed"
ignoring nonexistent directory "/home/tian/Desktop/GCC-12.1.0/bin/../lib/gcc/../../lib/gcc/x86_64-pc-linux-gnu/12.1.0/../../../../x86_64-pc-linux-gnu/include"
#include "..." search starts here:
#include <...> search starts here:
 /home/tian/Desktop/GCC-12.1.0/bin/../lib/gcc/x86_64-pc-linux-gnu/12.1.0/../../../../include/c++/12.1.0
 /home/tian/Desktop/GCC-12.1.0/bin/../lib/gcc/x86_64-pc-linux-gnu/12.1.0/../../../../include/c++/12.1.0/x86_64-pc-linux-gnu
 /home/tian/Desktop/GCC-12.1.0/bin/../lib/gcc/x86_64-pc-linux-gnu/12.1.0/../../../../include/c++/12.1.0/backward
 /home/tian/Desktop/GCC-12.1.0/bin/../lib/gcc/x86_64-pc-linux-gnu/12.1.0/include
 /home/tian/Desktop/GCC-12.1.0/bin/../lib/gcc/x86_64-pc-linux-gnu/12.1.0/include-fixed
 /usr/local/include
 /home/tian/Desktop/GCC-12.1.0/bin/../lib/gcc/../../include
 /usr/include/x86_64-linux-gnu
 /usr/include
End of search list.

所以我想我的猜测是正确的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接