g++
me donne des erreurs de la forme:
foo.cc:<line>:<column>: fatal error: <bar>: No such file or directory
compilation terminated.
Il en est de même lors de la compilation de programmes C avec gcc
.
Pourquoi donc?
Remarque: Cette question a été posée à plusieurs reprises auparavant, mais chaque fois, elle était spécifique à la situation des demandeurs. Le but de cette question est d'avoir une question que d'autres peuvent être fermées comme des doublons de, une fois pour toutes; a FAQ.
Votre compilateur vient d'essayer de compiler le fichier nommé foo.cc
. En tapant le numéro de ligne line
, 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, mais dans cet ensemble, il n’ya pas de fichier bar
. Pour une explication de la différence entre les versions de l'instruction include, regardez ici .
g++
a une option -I
. Il vous permet d'ajouter des chemins de recherche d'inclusion à la ligne de commande. Imaginez que votre fichier bar
se trouve dans un dossier nommé frobnicate
, par rapport à foo.cc
(supposons que vous compilez à partir du répertoire où se trouve foo.cc
):
g++ -Ifrobnicate foo.cc
Vous pouvez ajouter plus de chemins d'inclusion. chaque que vous donnez est relatif au répertoire en cours. 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-> Autres. Inclure les répertoires.
Maintenant, imaginez 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:
$ g++ -IA -IB -IC foo.cc
$ ./a.out
A/bar
Comme vous le voyez, lorsque le compilateur a commencé à regarder à travers A/
, B/
et C/
, il s’est arrêté au premier hit ou au doigt le plus à gauche.
Cela est vrai pour les deux formes, include <>
et incude ""
.
#include <bar>
et #include "bar"
Habituellement, le #include <xxx>
le fait d'abord rechercher dans les dossiers système, le #include "xxx"
le cherche d'abord dans les dossiers actuels ou personnalisés.
Par exemple.:
Imaginez que vous ayez les fichiers suivants dans votre dossier de projet:
list
main.cc
avec main.cc
:
#include "list"
....
Pour cela, votre compilateur va #include
le fichier list
dans votre dossier de projet, car il compile actuellement main.cc
et il y a ce fichier list
dans le dossier actuel.
Mais avec main.cc
:
#include <list>
....
puis g++ main.cc
, votre compilateur examinera d’abord les dossiers système et, comme <list>
est un en-tête standard, il _ #include
le fichier nommé list
fourni avec votre C++. plate-forme faisant partie de la bibliothèque standard.
Ceci est un peu simplifié, mais devrait vous donner l’idée de base.
<>
/""
- priorités et -I
Selon gcc-documentation , la priorité de include <>
est, sur un "système Unix normal", comme suit:
/usr/local/include
libdir/gcc/target/version/include
/usr/target/include
/usr/include
Pour les programmes C++, il cherchera également d’abord dans/usr/include/c ++/version. Ci-dessus, cible est le nom canonique du système que GCC a été configuré pour compiler le code; [...].
La documentation indique également:
Vous pouvez ajouter à cette liste avec l'option de ligne de commande -Idir. Tous les répertoires nommés par -I sont recherchés, dans l'ordre de gauche à droite, avant les répertoires par défaut . La seule exception est lorsque dir est déjà recherché par défaut. Dans ce cas, l'option est ignorée et l'ordre de recherche pour les répertoires système reste inchangé.
Pour continuer notre exemple #include<list> / #include"list"
(même code):
g++ -I. main.cc
et
#include<list>
int main () { std::list<int> l; }
et en effet, le -I.
donne la priorité au dossier .
par rapport au système et nous obtenons une erreur de compilation.