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

87

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 .

Sebastian Mach
la source
4
Bel ajout à la FAQ. Merci!
sbi

Réponses:

117

Votre compilateur a juste essayé de compiler le fichier nommé foo.cc. En frappant 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 à 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 se bartrouve dans un dossier nommé frobnicate, par rapport à foo.cc(supposons que vous compiliez à partir du répertoire où foo.ccse 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 /Iqui 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 bardans 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é à chercher A/, B/etC/ , il est arrêté à la première ou à gauche frappé.

Cela est vrai des deux formes, include <>et incude "".

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 #includele fichier listdans votre dossier de projet, car il compile actuellement main.ccet il y a ce fichier listdans 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 #includele 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

Pour les programmes C ++, il cherchera également dans / usr / include / c ++ / version, d'abord. Dans ce qui précède, target est le nom canonique du système pour lequel 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 des répertoires système reste inchangé.

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.

Sebastian Mach
la source
9
Je veux juste vous faire remarquer que c'est un peu bizarre que vous vous référiez à votre compilateur comme "votre compilateur" puisque la question et la réponse ont le même auteur.
Chaussure du
27
@Jeffrey: Peut-être que l'auteur de la question avait l'intention de s'adapter au format général ici. Je ne sais pas, demandez-lui.
Sebastian Mach
1
Cette réponse est fausse, #include <>regarde dans les répertoires répertoriés avec -Iavant les répertoires système par défaut
Jonathan Wakely
5
" Imaginez que votre barre de fichiers se trouve dans un dossier nommé frobnicate, relatif à foo.cc " les répertoires donnés avec -Isont 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
Jonathan Wakely
3
Les paramètres de votre PATHvariable d'environnement (sur les systèmes Linux) affectent-ils la manière dont le compilateur recherche les fichiers?
Matt Phillips