gcc / g ++: "Tidak ada file atau direktori seperti itu"

88

g++ beri saya kesalahan formulir:

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

Ini sama ketika mengkompilasi program-C dengan gcc.

Mengapa demikian?


Harap diperhatikan: Pertanyaan ini telah ditanyakan berkali-kali sebelumnya, tetapi setiap kali pertanyaan ini khusus untuk situasi penanya. Tujuan pertanyaan ini adalah untuk memiliki pertanyaan yang orang lain dapat ditutup sebagai duplikat , sekali dan untuk semua; sebuah FAQ .

Sebastian Mach
sumber
4
Tambahan yang bagus untuk FAQ. Terimakasih!
sbi

Jawaban:

119

Kompilator Anda baru saja mencoba mengompilasi file bernama foo.cc. Setelah menekan nomor baris line, kompilator menemukan:

#include "bar"

atau

#include <bar>

Kompilator kemudian mencoba menemukan file itu. Untuk ini, ia menggunakan sekumpulan direktori untuk dilihat, tetapi di dalam set ini, tidak ada file bar. Untuk penjelasan tentang perbedaan antara versi pernyataan include, lihat di sini .

Bagaimana cara memberi tahu kompiler di mana menemukannya

g++punya pilihan -I. Ini memungkinkan Anda menambahkan termasuk jalur pencarian ke baris perintah. Bayangkan file Anda barada di folder bernama frobnicate, relatif terhadap foo.cc(anggap Anda sedang mengompilasi dari direktori tempat foo.ccberada):

g++ -Ifrobnicate foo.cc

Anda dapat menambahkan lebih banyak jalur penyertaan; setiap yang Anda berikan adalah relatif terhadap direktori saat ini. Kompiler Microsoft memiliki opsi berkorelasi /Iyang bekerja dengan cara yang sama, atau di Visual Studio, folder dapat diatur di Halaman Properti Proyek, di bawah Properti Konfigurasi-> C / C ++ -> Umum-> Direktori Sertakan Tambahan.

Sekarang bayangkan Anda memiliki beberapa versi bardi folder yang berbeda, mengingat:


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

Prioritas dengan #include "bar"paling kiri:

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

Seperti yang Anda lihat, ketika kompilator mulai mencari A/, B/dan C/berhenti pada klik pertama atau paling kiri.

Ini berlaku untuk kedua bentuk, include <>dan incude "".

Perbedaan antara #include <bar>dan#include "bar"

Biasanya, yang #include <xxx>membuatnya melihat ke folder sistem terlebih dahulu, #include "xxx"membuatnya melihat ke folder saat ini atau khusus terlebih dahulu.

Misalnya:

Bayangkan Anda memiliki file berikut di folder proyek Anda:

list
main.cc

dengan main.cc:

#include "list"
....

Untuk ini, kompilator Anda akan #includefile listdi folder proyek Anda, karena saat ini dikompilasi main.ccdan ada file itu listdi folder saat ini.

Tapi dengan main.cc:

#include <list>
....

dan kemudian g++ main.cc, kompilator Anda akan melihat ke dalam folder sistem terlebih dahulu, dan karena <list>merupakan header standar, ini akan #includemenjadi file bernama listyang disertakan dengan platform C ++ Anda sebagai bagian dari pustaka standar.

Ini semua agak disederhanakan, tetapi akan memberi Anda ide dasarnya.

Detail tentang <>/ ""-prioritas dan-I

Menurut dokumentasi gcc , prioritas untuk include <>adalah, pada "sistem Unix normal", sebagai berikut:

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

Untuk program C ++, ini juga akan melihat / usr / include / c ++ / version terlebih dahulu. Di atas, target adalah nama kanonik sistem yang dikonfigurasi GCC untuk mengompilasi kode; [...].

Dokumentasi juga menyatakan:

Anda dapat menambahkan ke daftar ini dengan opsi baris perintah -Idir. Semua direktori dengan nama -I dicari, dalam urutan kiri-ke-kanan, sebelum direktori default . Satu-satunya pengecualian adalah ketika dir sudah dicari secara default. Dalam kasus ini, opsi diabaikan dan urutan pencarian untuk direktori sistem tetap tidak berubah.

Untuk melanjutkan #include<list> / #include"list"contoh kami (kode yang sama):

g++ -I. main.cc

dan

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

dan memang, -I.memprioritaskan folder di .atas sistem yang disertakan dan kami mendapatkan kesalahan kompiler.

Sebastian Mach
sumber
9
Hanya ingin membuat Anda menyadari bahwa agak aneh Anda menyebut kompilator Anda sebagai "kompilator Anda" karena pertanyaan dan jawabannya memiliki penulis yang sama.
Sepatu
28
@ Jeffrey: Mungkin penulis pertanyaan dimaksudkan agar sesuai dengan format umum di sini. Entahlah, tanya dia.
Sebastian Mach
1
Jawaban ini salah, #include <>terlihat di direktori yang terdaftar dengan -Isebelum direktori sistem default
Jonathan Wakely
5
" Bayangkan bahwa file bar Anda ada di folder bernama frobnicate, relatif terhadap foo.cc " dirs yang diberikan -Irelatif terhadap dir tempat Anda menjalankan gcc, bukan relatif terhadap file yang sedang dikompilasi. Perbedaannya signifikan jika Anda melakukannyag++ -Ifrobnicate blah/foo.cc
Jonathan Wakely
3
Apakah pengaturan PATHvariabel lingkungan Anda (pada sistem Linux) memengaruhi cara kompilator mencari file sama sekali?
Matt Phillips