gcc / g ++: "Không có tệp hoặc thư mục nào như vậy"


87

g++ cho tôi lỗi của biểu mẫu:

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

Khi biên dịch chương trình C với gcc.

Tại sao vậy?


Xin lưu ý: Câu hỏi này đã được hỏi nhiều lần trước đây, nhưng mỗi lần nó là cụ thể cho tình huống của người hỏi. Mục đích của câu hỏi này là có một câu hỏi mà những người khác có thể được coi là bản sao của , một lần và mãi mãi; một câu hỏi thường gặp .


4
Bổ sung tốt cho Câu hỏi thường gặp. Cảm ơn bạn!
sbi

Câu trả lời:


117

Trình biên dịch của bạn vừa cố gắng biên dịch tệp có tên foo.cc. Khi nhấn số dòng line, trình biên dịch tìm thấy:

#include "bar"

hoặc là

#include <bar>

Sau đó, trình biên dịch sẽ cố gắng tìm tệp đó. Đối với điều này, nó sử dụng một tập hợp các thư mục để xem xét, nhưng trong tập hợp này, không có tệp bar. Để có lời giải thích về sự khác biệt giữa các phiên bản của câu lệnh include, hãy xem tại đây .

Cách thông báo cho trình biên dịch biết nơi tìm nó

g++có một tùy chọn -I. Nó cho phép bạn thêm bao gồm các đường dẫn tìm kiếm vào dòng lệnh. Hãy tưởng tượng rằng tệp của bạn barnằm trong một thư mục có tên frobnicate, liên quan đến foo.cc(giả sử bạn đang biên dịch từ thư mục foo.ccđược đặt):

g++ -Ifrobnicate foo.cc

Bạn có thể thêm nhiều đường dẫn bao gồm hơn; mỗi bạn cung cấp là tương đối với thư mục hiện tại. Trình biên dịch của Microsoft có tùy chọn tương quan /Ihoạt động theo cách tương tự hoặc trong Visual Studio, các thư mục có thể được đặt trong Trang thuộc tính của Dự án, trong Thuộc tính cấu hình-> C / C ++ -> Chung-> Thư mục Bao gồm Bổ sung.

Bây giờ, hãy tưởng tượng bạn có nhiều phiên bản bartrong các thư mục khác nhau, đã cho:


// 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;
}

Mức độ ưu tiên ở ngoài #include "bar"cùng bên trái:

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

Như bạn thấy, khi trình biên dịch bắt đầu nhìn qua A/, B/C/, nó dừng lại ở các hit tận cùng bên trái đầu tiên hoặc.

Điều này đúng với cả hai dạng, include <>incude "".

Sự khác biệt giữa #include <bar>#include "bar"

Thông thường, #include <xxx>nó làm cho nó nhìn vào các thư mục hệ thống trước, #include "xxx"làm cho nó nhìn vào các thư mục hiện tại hoặc tùy chỉnh trước.

Ví dụ:

Hãy tưởng tượng bạn có các tệp sau trong thư mục dự án của mình:

list
main.cc

với main.cc:

#include "list"
....

Đối với điều này, trình biên dịch của bạn sẽ #includetệp listtrong thư mục dự án của bạn, vì nó hiện đang biên dịch main.ccvà có tệp đó listtrong thư mục hiện tại.

Nhưng với main.cc:

#include <list>
....

và sau đó g++ main.cc, trình biên dịch của bạn sẽ xem xét các thư mục hệ thống trước tiên và vì <list>là tiêu đề tiêu chuẩn, nó sẽ #includeđặt tên tệp listđi kèm với nền tảng C ++ của bạn như một phần của thư viện tiêu chuẩn.

Tất cả điều này được đơn giản hóa một chút, nhưng sẽ cung cấp cho bạn ý tưởng cơ bản.

Chi tiết về <>/ ""-priorities và-I

Theo tài liệu gcc , mức độ ưu tiên đối với include <>, trên "hệ thống Unix thông thường", như sau:

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

Đối với các chương trình C ++, trước tiên, nó cũng sẽ tìm trong / usr / include / c ++ / version. Ở trên, target là tên chuẩn của hệ thống mà GCC đã được định cấu hình để biên dịch mã cho; [...].

Tài liệu cũng nêu rõ:

Bạn có thể thêm vào danh sách này với tùy chọn dòng lệnh -Idir. Tất cả các thư mục được đặt tên bởi -I được tìm kiếm, theo thứ tự từ trái sang phải, trước các thư mục mặc định . Ngoại lệ duy nhất là khi dir đã được tìm kiếm theo mặc định. Trong trường hợp này, tùy chọn bị bỏ qua và thứ tự tìm kiếm các thư mục hệ thống không thay đổi.

Để tiếp tục #include<list> / #include"list"ví dụ của chúng tôi (cùng một mã):

g++ -I. main.cc

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

và thực sự, -I.thư mục ưu tiên .hơn hệ thống bao gồm và chúng tôi gặp lỗi trình biên dịch.


9
Chỉ muốn làm cho bạn nhận thấy rằng thật kỳ lạ khi bạn gọi trình biên dịch của mình là "trình biên dịch của bạn" vì câu hỏi và câu trả lời có cùng một tác giả.
Giày vào

27
@Jeffrey: Có thể tác giả của câu hỏi định để phù hợp với định dạng chung ở đây. Dunno, hỏi anh ta.
Sebastian Mach

1
Câu trả lời này là sai, #include <>vẻ trong dirs liệt kê với -Itrước dirs hệ thống mặc định
Jonathan Wakely

5
" Hãy tưởng tượng rằng thanh tệp của bạn nằm trong một thư mục có tên frobnicate, liên quan đến foo.cc " -Icác dir được cung cấp có liên quan đến dir nơi bạn chạy gcc, không liên quan đến tệp đang được biên dịch. Sự khác biệt là đáng kể nếu bạn làmg++ -Ifrobnicate blah/foo.cc
Jonathan Wakely

3
Các cài đặt của PATHbiến môi trường của bạn (trên hệ thống Linux) có ảnh hưởng đến cách trình biên dịch tìm kiếm tệp không?
Matt Phillips
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.