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 .


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.


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
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.