gcc/g++: "No such file or directory"

118

g++给我报错的形式为:

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

使用gcc编译C程序也是一样。

为什么会这样呢?


请注意:这个问题已经被问过很多次,但每次都是针对提问者的具体情况。这个问题的目的是创建一个可以关闭其他重复问题的问题,一劳永逸;成为一个常见问题解答

3个回答

154

您的编译器尝试编译名为foo.cc的文件。在到达第line行时,编译器发现:

#include "bar"

或者

#include <bar>

编译器会尝试找到该文件,它使用一组目录进行查找,但在这个集合中没有bar文件。关于include语句版本之间的区别,请点击这里了解更多。
如何告诉编译器去哪里找呢?g++有一个选项-I,它允许你将包含搜索路径添加到命令行中。假设你的bar文件在名为frobnicate的文件夹中,相对于foo.cc(假设你正在从foo.cc所在的目录进行编译)。
g++ -Ifrobnicate foo.cc

你可以添加更多的包含路径;每个路径都是相对于当前目录的。微软的编译器有一个相关选项/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 <>#include "" 两种形式都是正确的。 #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

这只是简化了的内容,但应该能给你基本的理解。

<>/""优先级和-I的详细信息

根据gcc文档,在“普通Unix系统”上,include <>的优先级如下:

 /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 优先考虑文件夹 . 而不是系统包含文件,因此我们会得到编译器错误。


12
希望您注意一下,有点奇怪的是,您把编译器称为“您的编译器”,因为问题和答案的作者是同一个人。 - Shoe
36
@Jeffrey: 或许提问者想符合这里的一般格式。不知道,可以问问他。 - Sebastian Mach
1
这个答案是错误的,“#include <>”会在列有“-I”的目录中查找,然后再查找默认系统目录。 - Jonathan Wakely
6
假设您的文件栏位于名为frobnicate的文件夹中,相对于foo.cc。使用“-I”指定的目录是相对于运行gcc的目录而不是正在编译的文件。如果您执行“g++ -Ifrobnicate blah/foo.cc”,则这种差异是显著的。 - Jonathan Wakely
3
在Linux系统上,你的PATH环境变量设置是否会影响编译器文件搜索? - Matt Phillips
显示剩余2条评论

0
此外,似乎编译器存在一个错误,如果您在头文件名中包含字符“struct”或“Struct”,编译器将抛出相同的“没有这个文件或目录”的错误。

你的回答目前不够清晰。请 [编辑] 添加更多细节,帮助其他人了解这个问题的回答方式。你可以在 帮助中心找到关于如何编写好的答案的更多信息。 - Community
如果您有新的问题,请通过单击提问按钮来提出。如果它有助于提供上下文,请包含此问题的链接。- 来自审核 - Yang Yushi

-5

这对我有效,sudo apt-get install libx11-dev


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接