g++
daje mi błędy w formularzu:
foo.cc:<line>:<column>: fatal error: <bar>: No such file or directory
compilation terminated.
To samo dzieje się podczas kompilowania programów w C z gcc
.
Dlaczego?
Uwaga: to pytanie zadawano już wiele razy, ale za każdym razem było to specyficzne dla sytuacji pytających. Celem tego pytania jest pytanie, które inni mogą zostać zamknięci jako duplikaty raz na zawsze; FAQ .
Odpowiedzi:
Twój kompilator właśnie próbował skompilować plik o nazwie
foo.cc
. Po naciśnięciu numeru wierszaline
kompilator znajduje:#include "bar"
lub
#include <bar>
Kompilator następnie próbuje znaleźć ten plik. W tym celu wykorzystuje zestaw katalogów do przeglądania, ale w tym zestawie nie ma pliku
bar
. Aby uzyskać wyjaśnienie różnicy między wersjami instrukcji include, zajrzyj tutaj .Jak powiedzieć kompilatorowi, gdzie go znaleźć
g++
ma opcję-I
. Umożliwia dodanie ścieżek wyszukiwania dołączania do wiersza poleceń. Wyobraź sobie, że twój plikbar
znajduje się w folderze o nazwiefrobnicate
względemfoo.cc
(załóżmy, że kompilujesz z katalogu, w którymfoo.cc
się znajduje):g++ -Ifrobnicate foo.cc
Możesz dodać więcej ścieżek włączania; każdy, który podajesz, odnosi się do bieżącego katalogu. Kompilator Microsoftu ma opcję korelacji,
/I
która działa w ten sam sposób, lub w Visual Studio foldery można ustawić na stronach właściwości projektu, w sekcji Właściwości konfiguracji-> C / C ++ -> Ogólne-> Dodatkowe katalogi dołączane.Teraz wyobraź sobie, że masz wiele wersji
bar
w różnych folderach, biorąc pod uwagę:// 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; }
Priorytet z
#include "bar"
jest skrajnie lewy:Jak widać, gdy kompilator zaczął rozglądać się za pośrednictwem
A/
,B/
orazC/
, że zatrzymał się na pierwszym lub skrajnej lewej przeboju.Dotyczy to obu form
include <>
iincude ""
.Różnica między
#include <bar>
i#include "bar"
Zwykle
#include <xxx>
najpierw sprawdza foldery systemowe, a najpierw#include "xxx"
bieżące lub niestandardowe foldery.Na przykład:
Wyobraź sobie, że masz następujące pliki w folderze projektu:
list main.cc
z
main.cc
:#include "list" ....
W tym celu kompilator umieści
#include
pliklist
w folderze projektu, ponieważ obecnie się kompilujemain.cc
i ten plik znajduje sięlist
w bieżącym folderze.Ale z
main.cc
:#include <list> ....
a następnie
g++ main.cc
Twój kompilator najpierw zajrzy do folderów systemowych, a ponieważ<list>
jest to standardowy nagłówek, będzie#include
to plik o nazwielist
dostarczonej z platformą C ++ jako część biblioteki standardowej.To wszystko jest nieco uproszczone, ale powinno dać ci podstawowe pojęcie.
Szczegóły dotyczące
<>
/""
-priorities i-I
Zgodnie z dokumentacją gcc , priorytet dla
include <>
"normalnego systemu uniksowego" jest następujący:/usr/local/include libdir/gcc/target/version/include /usr/target/include /usr/include
Dokumentacja podaje również:
Aby kontynuować nasz
#include<list> / #include"list"
przykład (ten sam kod):g++ -I. main.cc
i
#include<list> int main () { std::list<int> l; }
i rzeczywiście, nadaje
-I.
priorytet folderowi.
nad zawartością systemu i otrzymujemy błąd kompilatora.źródło
#include <>
wygląda w katalogach wymienionych-I
przed domyślnymi katalogami systemowymi-I
są względne w stosunku do katalogu, w którym uruchamiasz gcc, a nie względem kompilowanego pliku. Różnica jest znacząca, jeśli to zrobiszg++ -Ifrobnicate blah/foo.cc
PATH
zmiennej środowiskowej (w systemach Linux) wpływają na sposób wyszukiwania plików przez kompilator?