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


10

sys/ptrace.hCプログラムに組み込みました。

の出力は/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.. を見ています。どのような問題を解決しようとしていますか?
ラムハウンド、2015年

再帰的に調べているようには見えません。含まれている場合は、sys /プレフィックスを含める必要はありません。たとえば、ptrace.hだけを含めても機能しません。
user912083132

含まれていないと思います/sys/ptrace.hsys/ptrace.h、そうですか?
user253751

これはほぼ間違いなく、GCCへの「マルチアーチ」パッチのバグです。ディレクトリ/usr/include/x86_64-linux-gnu システムインクルードディレクトリとして扱われており、によって出力される検索パスリストに含める必要がありますgcc -v。誰かがそのバグをどのようにして達成したかわかりません。私の記憶が正しければ、システムインクルードディレクトリを追加する最も明白な方法は、によって出力されるディレクトリに追加することです-v。(私はGCCのプリプロセッサの約50%を書いたが、それは15年前だったので、何か覚えていなかったかもしれない。)
zwol

@Ramhoundこれは間違いなく以下を再帰的に検索しませ/usr/include。それは世界中のほぼすべてのCライブラリを壊します。
zwol 2015年

回答:


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>

  • / 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プリプロセッサー)がコンパイラーのプロセスの最初のステップであることを知っている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 Pre-Processor)アクションによって、どのように明確にミックスに挿入されるかに注意してください。そして、そのサイトの投稿は、それらのパスがどこから来たのかを説明するためにさらに続きます。再び大胆な強調は私のものです:

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

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


なぜx86_64-linux-gnu /が途中に押し込まれるのですか?
user912083132

@ user912083132:それ$TARGETは私が私の回答とコメントで述べた部分です。これはconfig.guess、GCCがコンパイルされたとき、またはフラグを使用してconfigureスクリプトに渡されたときの出力です--target。本当の問題は、そのパスはどのように組み立てられるのですか?$TARGETヘッダーの初回検索に失敗した後、同じリストをたどってそれぞれに追加しますか?
Warren Young

@ user912083132新しく収集した情報で私の回答を更新しました。もう一度お読みください。回答は、それがCPP(Cプリプロセッサ)から来ていることを説明しています。
JakeGould、2015年

2

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>

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

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.