g++
me donne des erreurs de forme:
foo.cc:<line>:<column>: fatal error: <bar>: No such file or directory
compilation terminated.
C'est la même chose lors de la compilation de programmes C avec gcc
.
Pourquoi donc?
Remarque: cette question a été posée plusieurs fois auparavant, mais à chaque fois, elle était spécifique à la situation des demandeurs. Le but de cette question est d'avoir une question dont d'autres peuvent être fermées comme des doublons , une fois pour toutes; une FAQ .
Réponses:
Votre compilateur a juste essayé de compiler le fichier nommé
foo.cc
. En frappant le numéro de ligneline
, le compilateur trouve:#include "bar"
ou
#include <bar>
Le compilateur essaie ensuite de trouver ce fichier. Pour cela, il utilise un ensemble de répertoires à examiner, mais dans cet ensemble, il n'y a pas de fichier
bar
. Pour une explication de la différence entre les versions de l'instruction include, regardez ici .Comment dire au compilateur où le trouver
g++
a une option-I
. Il vous permet d'ajouter des chemins de recherche d'inclusion à la ligne de commande. Imaginez que votre fichier sebar
trouve dans un dossier nomméfrobnicate
, par rapport àfoo.cc
(supposons que vous compiliez à partir du répertoire oùfoo.cc
se trouve):g++ -Ifrobnicate foo.cc
Vous pouvez ajouter plus de chemins d'inclusion; chaque que vous donnez est relatif au répertoire courant. Le compilateur de Microsoft a une option de corrélation
/I
qui fonctionne de la même manière, ou dans Visual Studio, les dossiers peuvent être définis dans les pages de propriétés du projet, sous Propriétés de configuration-> C / C ++ -> Général-> Répertoires d'inclusion supplémentaires.Imaginez maintenant que vous avez plusieurs versions de
bar
dans différents dossiers, étant donné:// 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; }
La priorité avec
#include "bar"
est la plus à gauche:Comme vous le voyez, lorsque le compilateur a commencé à chercher
A/
,B/
etC/
, il est arrêté à la première ou à gauche frappé.Cela est vrai des deux formes,
include <>
etincude ""
.Différence entre
#include <bar>
et#include "bar"
Habituellement,
#include <xxx>
il regarde d'abord dans les dossiers système, le#include "xxx"
fait d'abord regarder dans les dossiers actuels ou personnalisés.Par exemple:
Imaginez que vous avez les fichiers suivants dans votre dossier de projet:
list main.cc
avec
main.cc
:#include "list" ....
Pour cela, votre compilateur mettra
#include
le fichierlist
dans votre dossier de projet, car il compile actuellementmain.cc
et il y a ce fichierlist
dans le dossier actuel.Mais avec
main.cc
:#include <list> ....
et puis
g++ main.cc
, votre compilateur examinera d'abord les dossiers système, et comme il<list>
s'agit d'un en-tête standard, il sera#include
le fichier nommélist
fourni avec votre plate-forme C ++ dans le cadre de la bibliothèque standard.Tout cela est un peu simplifié, mais devrait vous donner une idée de base.
Détails sur
<>
/""
-priorités et-I
Selon la documentation gcc , la priorité pour
include <>
est, sur un "système Unix normal", comme suit:/usr/local/include libdir/gcc/target/version/include /usr/target/include /usr/include
La documentation indique également:
Pour continuer notre
#include<list> / #include"list"
exemple (même code):g++ -I. main.cc
et
#include<list> int main () { std::list<int> l; }
et en effet, la
-I.
priorité du dossier.
sur le système inclut et nous obtenons une erreur de compilation.la source
#include <>
regarde dans les répertoires répertoriés avec-I
avant les répertoires système par défaut-I
sont relatifs au répertoire dans lequel vous exécutez gcc, et non au fichier en cours de compilation. La différence est significative si vous le faitesg++ -Ifrobnicate blah/foo.cc
PATH
variable d'environnement (sur les systèmes Linux) affectent-ils la manière dont le compilateur recherche les fichiers?