web-dev-qa-db-fra.com

gcc / g ++: "Aucun fichier ou répertoire de ce type"

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.

69
Sebastian Mach

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 .

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 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 "".

Différence entre #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.

Détails sur <>/""- 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.

94
Sebastian Mach