我已将其纳入sys/ptrace.h
我的 C 程序中。
输出/usr/lib/gcc/x86_64-linux-gnu/4.8/cc1 -v
给出了 gcc 查找头文件的以下路径
#include "..." search starts here:
#include <...> search starts here:
/usr/lib/gcc/x86_64-linux-gnu/4.8/include
/usr/local/include
/usr/lib/gcc/x86_64-linux-gnu/4.8/include-fixed
/usr/include
End of search list.
我的程序的输出gcc -M
给出了以下头文件位置
pt.o: pt.c /usr/include/stdc-predef.h /usr/include/stdio.h \
/usr/include/features.h /usr/include/x86_64-linux-gnu/sys/cdefs.h \
/usr/include/x86_64-linux-gnu/bits/wordsize.h \
/usr/include/x86_64-linux-gnu/gnu/stubs.h \
/usr/include/x86_64-linux-gnu/gnu/stubs-64.h \
/usr/lib/gcc/x86_64-linux-gnu/4.8/include/stddef.h \
/usr/include/x86_64-linux-gnu/bits/types.h \
/usr/include/x86_64-linux-gnu/bits/typesizes.h /usr/include/libio.h \
/usr/include/_G_config.h /usr/include/wchar.h \
/usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdarg.h \
/usr/include/x86_64-linux-gnu/bits/stdio_lim.h \
/usr/include/x86_64-linux-gnu/bits/sys_errlist.h \
/usr/include/x86_64-linux-gnu/sys/ptrace.h
由于/usr/include/x86_64-linux-gnu/
第一个输出中不包含,gcc 如何找到sys/ptrace.h
?
编辑:
echo '#include <sys/ptrace.h>' | gcc -fsyntax-only -xc -v -H -
结果输出
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.8.4-2ubuntu1~14.04' --with-bugurl=file:///usr/share/doc/gcc-4.8/README.Bugs --enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.8 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.8 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --disable-libmudflap --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.8-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04)
答案1
简短的回答。
您的问题是关于 的输出cc1 -v
,但其中没有考虑 CPP(C 预处理器)及其混入整个编译链的包含项。如果您cpp -v
在系统上运行,您应该会看到包含项的混合,其看起来类似于 的输出,cc1 -v
但至少/usr/include/x86_64-linux-gnu
在其中添加了路径。
较长的答案。
由于
/usr/include/x86_64-linux-gnu/
第一个输出中不包含,gcc 如何找到sys/ptrace.h
?
从技术上讲,/usr/include/x86_64-linux-gnu/
第一个输出中没有明确设置,但/usr/include/
肯定是。这是一个默认搜索路径如官方 GNU GCC 文档中所述:
GCC 在几个不同的地方查找标头。在普通的 Unix 系统上,如果您没有另行指示,它将
#include <file>
在以下位置查找请求的标头:
- /usr/local/包含
- libdir/gcc/目标/版本/包含
- /usr/目标/包含
- /usr/include
这里进一步解释:
GCC
#include "file"
首先在包含当前文件的目录中查找 所请求的头文件,然后在选项指定的目录中-iquote
查找,然后在与查找尖括号所请求的头文件相同的位置查找。例如,如果/usr/include/sys/stat.h
包含 # ,GCC首先在 中include "types.h"
查找 ,然后在其通常的搜索路径中查找。types.h
/usr/include/sys
所以这意味着x86_64-linux-gnu/
路径简单地插入/usr/include/*/sys/
如下:
/usr/include/x86_64-linux-gnu/sys/ptrace.h
至少我最初是这么想的该问题的早期版本。 但在查看此网站后对正在发生的事情的解释更为详细,该网站对与我上面发布的内容等效的内容的直接回应已转载如下;粗体强调是我的:
但这是一个模棱两可的答案(而且不完整)。肯定有办法让 GCC 准确地告诉你它最终会在哪里寻找它的头文件吧?好吧,虽然把 GCC 想象成一个单一的整体应用程序很方便,它接收源代码文件并输出工作程序,但从技术上讲,它是其他程序的集合,这些程序链接在一起生成最终编译的目标文件。其中第一个是 CPP,是C 预处理器,其工作是查找类似的编译器指令
#include
并根据其指定修改源代码;对于包含,通过将另一个文件的内容复制到当前文件中。您可以通过传递 -v 标志来查看它在哪里查找这些文件:
知道 CPP(C 预处理器)是编译器流程的第一步,让我们看看cpp -v
我的 Ubuntu 12.04.5 测试系统上的“include”输出:
#include "..." search starts here:
#include <...> search starts here:
/usr/lib/gcc/x86_64-linux-gnu/4.6/include
/usr/local/include
/usr/lib/gcc/x86_64-linux-gnu/4.6/include-fixed
/usr/include/x86_64-linux-gnu
/usr/include
在那里你可以清楚地看到。为了比较,这里是在同一个 Ubuntu 12.04.5 测试系统上/usr/include/x86_64-linux-gnu
的类似“include”输出:/usr/lib/gcc/x86_64-linux-gnu/4.6/cc1 -v
#include "..." search starts here:
#include <...> search starts here:
/usr/lib/gcc/x86_64-linux-gnu/4.6/include
/usr/local/include
/usr/lib/gcc/x86_64-linux-gnu/4.6/include-fixed
/usr/include
请注意,初始 CPP(C 预处理器)操作如何/usr/include/x86_64-linux-gnu
明确地插入到混合中。该网站上的帖子进一步解释了这些路径的来源;再次强调:
这个路径实际上是在编译时内置到 CPP(GCC 的一部分)中的;如果由于某种原因您最终删除了其中一个目录,它仍然会在每次编译时进行检查。每个目录都按照此处列出的顺序进行搜索;如果在中找到文件
/usr/local/include
,则不会检查接下来的三个目录。
因此,一切都归结为 CPP(C 预处理器)被称为 C 编译链的第一部分。
答案2
/usr/include/$TARGET
除非深入研究 GCC 源代码,否则我无法告诉你“为什么”,但我可以告诉你,在你用尽所有选择之后,我这里使用的 GCC 版本会退化为和 Giacomo1968 发现。您可以看到如下内容:
$ strace -f -e open gcc -c foo.c -o foo.o 2>&1 | grep ptrace.h
其中foo.c
包含#include <sys/ptrace.h>
。
这里需要-f
参数,因为gcc
会生成子进程来完成实际的编译工作。需要参数,2>&1
因为strace
会将其结果写入 stderr,而不是 stdout。
请注意,ENOENT
在最终尝试成功的目录之前,所有记录的目录都会出现错误。