Como o gcc encontra o seguinte arquivo de cabeçalho?

8

Eu incluí sys/ptrace.h no meu programa em C.

A saída de /usr/lib/gcc/x86_64-linux-gnu/4.8/cc1 -v fornece os seguintes caminhos onde o gcc procura por arquivos de cabeçalho

#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.

a saída de gcc -M do meu programa fornece os seguintes locais de arquivo de cabeçalho

    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

Como /usr/include/x86_64-linux-gnu/ não está contido na primeira saída, como o gcc encontra sys/ptrace.h ?

EDITAR:

A saída de echo '#include <sys/ptrace.h>' | gcc -fsyntax-only -xc -v -H - resulta em

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) 
    
por user912083132 03.10.2015 / 20:00

2 respostas

8

Resposta mais curta.

Sua pergunta é sobre a saída de cc1 -v , mas isso não leva em consideração o CPP (C Pre-Processor) e os includes que são misturados em toda a cadeia de compilação. Se você executar cpp -v em seu sistema, uma mistura de inclusões será semelhante à saída de cc1 -v , mas com pelo menos o caminho /usr/include/x86_64-linux-gnu adicionado lá.

Resposta mais longa.

Since /usr/include/x86_64-linux-gnu/ is not contained in the first output, how does gcc find sys/ptrace.h?

Tecnicamente, /usr/include/x86_64-linux-gnu/ não é explicitamente definido na primeira saída, mas /usr/include/ é definitivamente. E esse é um caminho de pesquisa padrão conforme explicado na documentação oficial do GNU GCC :

GCC looks in several different places for headers. On a normal Unix system, if you do not instruct it otherwise, it will look for headers requested with #include <file> in:

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

E mais explicado aqui:

GCC looks for headers requested with #include "file" first in the directory containing the current file, then in the directories as specified by -iquote options, then in the same places it would have looked for a header requested with angle brackets. For example, if /usr/include/sys/stat.h contains #include "types.h", GCC looks for types.h first in /usr/include/sys, then in its usual search path.

Isso implica que o caminho x86_64-linux-gnu/ é simplesmente inserido em /usr/include/*/sys/ da seguinte forma:

/usr/include/x86_64-linux-gnu/sys/ptrace.h

Pelo menos é o que eu pensava inicialmente em uma versão anterior desta questão . Mas depois de verificar este site , a explicação do que está acontecendo é um pouco mais detalhada e direta. resposta desse site para o conteúdo equivalente ao que eu postei acima é repostado abaixo; ênfase ousada é minha:

but that's sort of a wishy-washy answer (and also incomplete). Surely there must be a way to get GCC to tell you exactly where it's going to end up looking for its header files? Well, although it's convenient to think of GCC as a single monolithic application that takes in source code files and spits out working programs, it's technically a collection of other programs which chain together to produce the final compiled object file. The first of these is CPP, short for C Pre-Processor, whose job is to look for compiler directives like #include and modify the source code as specified by them; in the case of include, by copying the contents of another file into the current one. You can see where it looks for these files by passing it the -v flag:

Saiba que o CPP (C Pre-Processor) é o primeiro passo no processo do compilador, vamos ver a saída "include" de cpp -v no meu sistema de testes do Ubuntu 12.04.5:

#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

Lá você pode ver claramente /usr/include/x86_64-linux-gnu . E para comparar, aqui está a saída “include” similar de /usr/lib/gcc/x86_64-linux-gnu/4.6/cc1 -v no mesmo sistema de teste do Ubuntu 12.04.5:

#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

Observe como /usr/include/x86_64-linux-gnu é claramente inserido na mistura pela ação inicial CPP (C Pre-Processor). E o post nesse site continua a explicar de onde vêm esses caminhos; mais uma vez a ênfase ousada é minha:

this path is actually built into CPP (which is part of GCC) at compile time; if for whatever reason you end up deleting one of those directories, it will still be checked for on each compile. Each directory is searched in the order it's listed here; if a file is found in /usr/local/include, the next three directories won't be checked.

Portanto, tudo se resume ao CPP (C Pre-Processor) sendo chamado como a primeira parte de uma cadeia de compilação C.

    
por 03.10.2015 / 20:27
2

Antes de investigar o código-fonte do GCC, não posso dar um "porquê", mas posso dizer-lhe que a versão do GCC que tenho aqui cai para /usr/include/$TARGET depois de esgotar as opções que você e JakeGould encontraram . Você pode ver assim:

$ strace -f -e open gcc -c foo.c -o foo.o 2>&1 | grep ptrace.h

em que foo.c contém #include <sys/ptrace.h> .

Você precisa do argumento -f aqui porque gcc gera filhos para fazer o trabalho de compilação real. Você precisa do 2>&1 porque strace está gravando seus resultados para stderr, não stdout.

Observe que você recebe ENOENT erros para todos os diretórios documentados antes de finalmente tentar o que é bem-sucedido.

    
por 03.10.2015 / 20:36

Tags