gcc如何找到以下头文件?


10

我已经包含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) 

它正在递归地看/usr/include..您要解决什么问题?
Ramhound 2015年

它看起来像递归浏览。如果确实如此,则无需包含sys /前缀。例如,仅包含ptrace.h无效。
user912083132 2015年

我不认为你包括/sys/ptrace.hsys/ptrace.h,不是吗?
user253751

这几乎可以肯定是GCC的“ multiarch”补丁中的错误。该目录/usr/include/x86_64-linux-gnu 被当作一个系统包括目录和被包括在由打印的搜索路径列表gcc -v。我不确定有人如何解决该错误;如果我没记错的话,添加系统包含目录的最明显方法就是将它们添加到所打印的内容中-v。(我写了大约50%的GCC预处理程序,但这是15年前,所以我可能记错了什么。)
zwol

@Ramhound它最肯定不会递归搜索下面/usr/include。这将破坏世界上几乎所有的C库。
zwol 2015年

Answers:


12

简短的答案。

您的问题是关于的输出的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>在in中查找请求的标头:

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

并在这里进一步解释:

GCC #include "file"首先在包含当前文件的目录中查找请求的标头,然后在-iquoteoptions 指定的目录中查找,然后在相同的位置查找带有尖括号的请求标头。例如,如果 /usr/include/sys/stat.h包含#include "types.h",则GCC 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 Pre-Processor的缩写,它的作用是查找类似的编译器指令 #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

在那儿你可以清楚地看到/usr/include/x86_64-linux-gnu。相比之下,这是/usr/lib/gcc/x86_64-linux-gnu/4.6/cc1 -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

注意如何/usr/include/x86_64-linux-gnu通过初始CPP(C预处理程序)操作将其清楚地插入到混音中。该站点上的帖子进一步解释了这些路径的来源;我再次大胆强调:

该路径实际上是在编译时内置到CPP(它是GCC的一部分)中的;如果由于某种原因而最终删除了这些目录之一,则仍将在每次编译时对其进行检查。每个目录都按照此处列出的顺序进行搜索;如果在中找到文件/usr/local/include,则不会检查接下来的三个目录。

因此,一切归结为CPP(C预处理器)被称为C编译链的第一部分。


为什么x86_64-linux-gnu /被推到中间?
user912083132 2015年

@ user912083132:这就是$TARGET我在回答和评论中提到的部分。它是config.guessGCC编译时的输出,或者configure带有--target标志的GCC 脚本的输出。真正的问题是,该路径如何组装?$TARGET在第一次没有找到标题后,它是否只是回到同一列表,追加到每个列表?
沃伦·杨

@ user912083132使用一些新收集的信息更新了我的答案。请重读;答案说明它来自CPP(C预处理器)。
JakeGould 2015年

2

在没有深入研究GCC源代码的情况下,我不能给您一个“为什么”的信息,但是我可以告诉您,/usr/include/$TARGET在用尽您和JakeGould找到的选择之后,我在这里使用的GCC版本会回退。您可以这样看:

$ 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,在最终尝试成功的目录之前,所有记录的目录都会出错。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.