web-dev-qa-db-ja.com

gccは次のヘッダーファイルをどのように見つけますか?

Cプログラムにsys/ptrace.hを含めました。

/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) 
10
user912083132

より短い答え。

あなたの質問は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/include
  • libdir/gcc/target/version/include
  • / usr/target/include
  • / usr/include

さらにここで説明:

GCCは#include "file"で要求されたヘッダーを最初に現在のファイルを含むディレクトリで検索し、次に-iquoteオプションで指定されたディレクトリで検索し、次に同じ場所で山かっこで要求されたヘッダーを検索します。たとえば、/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プリプロセッサー)がコンパイラーのプロセスの最初のステップであることを知っているので、Ubuntu 12.04.5テストシステムでのcpp -vの「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がはっきりと見えます。比較のために、同じUbuntu 12.04.5テストシステムでの/usr/lib/gcc/x86_64-linux-gnu/4.6/cc1 -vの同様の「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

最初のCPP(Cプリプロセッサ)アクションによって/usr/include/x86_64-linux-gnuが明確にミックスに挿入されていることに注意してください。そして、そのサイトの投稿はさらに、それらのパスがどこから来たのかを説明するために続きます。再び大胆な強調は私のものです:

このパスは実際にはコンパイル時にCPP(GCCの一部)に組み込まれます。何らかの理由でこれらのディレクトリの1つを削除してしまった場合でも、コンパイルごとにチェックされます。各ディレクトリは、ここにリストされている順序で検索されます。 /usr/local/includeにファイルが見つかった場合、次の3つのディレクトリはチェックされません。

つまり、Cコンパイルチェーンの最初の部分として呼び出されるCPP(Cプリプロセッサ)に要約されます。

12
JakeGould

GCCのソースコードを掘り下げるのではなく、「理由」をお伝えすることはできませんが、ここで使用しているGCCのバージョンは、選択肢を使い尽くした後で/usr/include/$TARGETにフォールバックしていることはわかります とJakeGouldが見つかりました 。次のように表示されます。

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

ここで、foo.cには#include <sys/ptrace.h>が含まれます。

gccは実際のコンパイル作業を行うために子を生成するため、ここで-f引数が必要です。 straceは結果をstdoutではなくstderrに書き込むため、2>&1が必要です。

成功したディレクトリを最終的に試行する前に、ドキュメント化されたすべてのディレクトリでENOENTエラーが発生することに注意してください。

2
Warren Young