web-dev-qa-db-ja.com

gcc / g ++:「そのようなファイルまたはディレクトリはありません」

g++は次の形式のエラーを表示します:

foo.cc:<line>:<column>: fatal error: <bar>: No such file or directory
compilation terminated.

gccを使用してCプログラムをコンパイルする場合も同じです。

何故ですか?


注意:この質問はこれまで何度も質問されてきましたが、そのたびに質問者の状況に固有のものでした。この質問の目的は、他の人が重複して閉じることができるという質問をすること、一度限りです; aFAQ

69
Sebastian Mach

コンパイラは、foo.ccという名前のファイルをコンパイルしようとしました。行番号lineにヒットすると、コンパイラは次を見つけます。

#include "bar"

または

#include <bar>

その後、コンパイラはそのファイルを見つけようとします。このため、ディレクトリセットを使用して調べますが、このセット内にはファイルbarはありません。 includeステートメントのバージョン間の違いの説明については、 here を参照してください。

コンパイラに場所を伝える方法

g++にはオプション-Iがあります。コマンドラインにインクルード検索パスを追加できます。ファイルbarが、foo.ccに関連するfrobnicateという名前のフォルダーにあるとします(foo.ccがあるディレクトリからコンパイルしていると仮定します):

g++ -Ifrobnicate foo.cc

さらにinclude-pathを追加できます。指定するそれぞれは、現在のディレクトリに相対的です。 Microsoftのコンパイラには、/Iと同じように機能する相関オプションがあります。または、Visual Studioでは、プロジェクトのプロパティページの[構成プロパティ]-> [C/C++]-> [一般]-> [追加]ディレクトリを含めます。

次のように、異なるフォルダーにbarの複数のバージョンがあるとします。


// A/bar
#include<string>
std::string which() { return "A/bar"; }

// B/bar
#include<string>
std::string which() { return "B/bar"; }

// C/bar
#include<string>
std::string which() { return "C/bar"; }

// foo.cc
#include "bar"
#include <iostream>

int main () {
    std::cout << which() << std::endl;
}

#include "bar"の優先度は左端です:

$ g++ -IA -IB -IC foo.cc
$ ./a.out
A/bar

ご覧のとおり、コンパイラがA/B/およびC/の検索を開始すると、最初または左端のヒットで停止しました。

これは、include <>incude ""の両方の形式に当てはまります。

#include <bar>#include "bar"の違い

通常、#include <xxx>は最初にシステムフォルダーを調べ、#include "xxx"は最初に現在のフォルダーまたはカスタムフォルダーを調べます。

例えば。:

プロジェクトフォルダーに次のファイルがあるとします。

list
main.cc

main.ccで:

#include "list"
....

このため、コンパイラーはプロジェクトフォルダー内の#includeファイルlistをコンパイルします。これは、現在main.ccをコンパイルしており、そのファイルlistが現在のフォルダーにあるためです。

ただし、main.ccの場合:

#include <list>
....

そしてg++ main.cc、コンパイラは最初にシステムフォルダを調べます。<list>は標準ヘッダーであるため、C++に付属するlistという名前のファイルを#includeします標準ライブラリの一部としてのプラットフォーム。

これはすべて少し簡略化されていますが、基本的な考え方がわかるはずです。

<>/""- prioritiesおよび-Iの詳細

gcc-documentation によると、include <>の優先度は、「通常のUnixシステム」では次のとおりです。

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

C++プログラムの場合、最初に/ usr/include/c ++/versionも検索します。上記のtargetは、GCCがコードをコンパイルするように構成されたシステムの正規名です。 [...]。

ドキュメントには次のようにも記載されています。

-Idirコマンドラインオプションを使用して、このリストに追加できます。 -Iで指定されたすべてのディレクトリは、左から右の順にデフォルトディレクトリの前で検索されます。唯一の例外は、dirがデフォルトですでに検索されている場合です。この場合、オプションは無視され、システムディレクトリの検索順序は変更されません。

#include<list> / #include"list"の例を続行するには(同じコード):

g++ -I. main.cc

そして

#include<list>
int main () { std::list<int> l; }

そして実際、-I.はシステムが含まれるフォルダー.を優先し、コンパイラーエラーが発生します。

94
Sebastian Mach