web-dev-qa-db-ja.com

/ usr / includeにヘッダーファイルの複数のコピーがあるのはなぜですか?

私は/ usr/includeフォルダーを閲覧してレイアウトに慣れ親しんでおり、ヘッダーファイルのコピーが複数あることに気付きました(少なくとも名前で、実際にそれらを比較して、それらが正確であるかどうかを確認しませんでした)コピー)/ usr/includeのいくつかのサブディレクトリにあります。これは特に、標準CおよびC++ヘッダーファイルとPOSIX/LSB標準ヘッダーファイルの場合です。

いくつかの例が含まれます(注./は/ usr/includeを指します):

./asm-generic/unistd.h
./linux/unistd.h
./unistd.h
./x86_64-linux-gnu/sys/unistd.h
./x86_64-linux-gnu/bits/unistd.h
./x86_64-linux-gnu/asm/unistd.h

./stdlib.h
./x86_64-linux-gnu/bits/stdlib.h
./c++/7/stdlib.h
./c++/7/tr1/stdlib.h

./c++/7/cmath
./c++/7/ext/cmath
./c++/7/tr1/cmath

./asm-generic/termios.h
./linux/termios.h
./x86_64-linux-gnu/sys/termios.h
./x86_64-linux-gnu/bits/termios.h
./x86_64-linux-gnu/asm/termios.h
./termios.h

./linux/time.h
./time.h
./x86_64-linux-gnu/sys/time.h
./x86_64-linux-gnu/bits/time.h

どうしてこれなの?そして、なぜいくつかのC標準ヘッダーがC++の場所に表示されるのですか?

インストールされているコンパイラは1つだけです(GCC 7)。

6
Adam Sperry

いいえ、正確なコピーではありません。

調べてみると、トップレベルのファイル/usr/includeには通常、多くの#ifdefsまたはその他の条件があり、アーキテクチャに依存しない部分のみを定義し、 #include階層内のより深いアーキテクチャ固有のディレクトリからのその他のもの。アーキテクチャ固有の一部のパーツは、アーキテクチャに依存しない一部のパーツに依存している可能性があるため、複数のレイヤーが互いに重なり合っている場合があります。

同様に、/usr/include/c++の下のファイルには、C++でのみ意味のある追加の宣言、および対応するCインクルードファイルの#includesが適切な場所にあります。

ゲームの名前は保守性のための重複排除:目的は、glibc開発者が、アプリケーションとglibc間のABIにのみ影響し、アーキテクチャ固有の部分がない新しい何かを追加する必要がある場合に、追加理想的には、インクルードファイルのツリー内の1つの場所でのみ発生する必要があり、glibcを使用するすべてのハードウェアアーキテクチャで有効になります。または、たとえば、新しいシステムコールがLinuxカーネルに追加された場合、* BSDやGNU Hurdシステムコールの定義など)に干渉することなく追加できます。またはglibcをさらに別のハードウェア/カーネルアーキテクチャに移植している場合は、アーキテクチャに依存しないものを絶対に必要以上に妨害することなく、必要なカーネルABI定義をプラグインできる場所が見つかります。

はい、かなり複雑です。

/usr/includeレイアウト全体がISO CおよびPOSIX標準の要件とGCCおよびglibcプロジェクトの両方で行われた選択の合計であるため、簡単な参照はありません。

アーキテクチャトリプレット(ケースではx86_64-linux-gnu、GCCでサポートされているアーキテクチャではgcc -dumpmachineで取得可能)を書き留めて、コンパイラのデフォルトを調べることをお勧めします#include <...>ファイル検索パス。

あなたは検索パスを見ることができます:

  • cpp -v /dev/null -o /dev/nullプレーンC
  • cpp -x c++ -v /dev/null -o /dev/null(C++の場合)

ここにはGCC 7を備えたシステムはありませんが、GCC 6の場合、インクルードパスのリストはCの場合は次のようになります。

...
#include <...> search starts here:
 /usr/lib/gcc/x86_64-linux-gnu/6/include
 /usr/local/include
 /usr/lib/gcc/x86_64-linux-gnu/6/include-fixed
 /usr/include/x86_64-linux-gnu
 /usr/include
End of search list.
...

... C++の場合は次のようになります。

...
#include <...> search starts here:
 /usr/include/c++/6
 /usr/include/x86_64-linux-gnu/c++/6
 /usr/include/c++/6/backward
 /usr/lib/gcc/x86_64-linux-gnu/6/include
 /usr/local/include
 /usr/lib/gcc/x86_64-linux-gnu/6/include-fixed
 /usr/include/x86_64-linux-gnu
 /usr/include
End of search list.
...

/usr/local/include/<architecture triplet>ディレクトリが存在する場合、/usr/local/includeの直前のリストに追加されます。

したがって、独自のプロジェクトの場合、アーキテクチャ固有のバージョンのインクルードファイルが必要な場合は、それらを/usr/[local/]include/<architecture triplet>/の下に置き、通常のアーキテクチャに依存しないインクルードファイルを/usr/[local/]include/に置くことができます。 。パス名にコンパイラのメジャーバージョン番号が含まれているインクルードディレクトリには、十分な理由なしに触れません。

glibcを変更する予定があり、glibc開発者向けドキュメントで必要なものが見つからない場合は、glibc開発メーリングリストでアドバイスを求めることをお勧めします。 glibcは、GCC以外のコンパイラーを使用するアーキテクチャーでも使用できるため、非常に複雑であり、アーキテクチャーのトリプレット規則が標準ではない場合があります。

6
telcoM