gcc / g ++: "No existe tal archivo o directorio"

87

g++ me da errores de la forma:

foo.cc:<line>:<column>: fatal error: <bar>: No such file or directory
compilation terminated.

Es lo mismo al compilar programas C con gcc.

¿Porqué es eso?


Tenga en cuenta: esta pregunta se ha hecho muchas veces antes, pero cada vez fue específica para la situación de los solicitantes. El propósito de esta pregunta es tener una pregunta que otras puedan cerrarse como duplicados , de una vez por todas; una pregunta frecuente .

Sebastián Mach
fuente
4
Buena adición a las preguntas frecuentes. ¡Gracias!
sbi

Respuestas:

116

Su compilador acaba de intentar compilar el archivo llamado foo.cc. Al presionar el número de línea line, el compilador encuentra:

#include "bar"

o

#include <bar>

Luego, el compilador intenta encontrar ese archivo. Para ello, utiliza un conjunto de directorios para buscar, pero dentro de este conjunto, no hay ningún archivo bar. Para obtener una explicación de la diferencia entre las versiones de la declaración de inclusión, consulte aquí .

Cómo decirle al compilador dónde encontrarlo

g++tiene una opción -I. Le permite agregar rutas de búsqueda de inclusión a la línea de comandos. Imagine que su archivo barestá en una carpeta con el nombre frobnicate, relativo a foo.cc(suponga que está compilando desde el directorio donde foo.ccse encuentra):

g++ -Ifrobnicate foo.cc

Puede agregar más rutas de inclusión; cada uno que da es relativo al directorio actual. El compilador de Microsoft tiene una opción de correlación /Ique funciona de la misma manera, o en Visual Studio, las carpetas se pueden configurar en las Páginas de propiedades del Proyecto, en Propiedades de configuración-> C / C ++ -> General-> Directorios de inclusión adicionales.

Ahora imagine que tiene varias versiones de baren diferentes carpetas, dado:


// 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 prioridad con #include "bar"es la más a la izquierda:

$ g++ -IA -IB -IC foo.cc
$ ./a.out
A/bar

Como se ve, cuando el compilador empezado a buscar a través A/, B/y C/, se detuvo en el primer o el golpe más a la izquierda.

Esto es cierto para ambas formas include <>y incude "".

Diferencia entre #include <bar>y#include "bar"

Por lo general, lo #include <xxx>hace buscar primero en las carpetas del sistema, luego lo #include "xxx"hace buscar primero en las carpetas actuales o personalizadas.

P.ej:

Imagina que tienes los siguientes archivos en la carpeta de tu proyecto:

list
main.cc

con main.cc:

#include "list"
....

Para esto, su compilador guardará #includeel archivo listen la carpeta de su proyecto, porque actualmente se compila main.ccy ese archivo está listen la carpeta actual.

Pero con main.cc:

#include <list>
....

y luego g++ main.cc, su compilador buscará primero en las carpetas del sistema, y ​​debido a que <list>es un encabezado estándar, será #includeel archivo nombrado listque viene con su plataforma C ++ como parte de la biblioteca estándar.

Todo esto está un poco simplificado, pero debería darte una idea básica.

Detalles sobre <>/ ""-priorities y-I

Según la documentación de gcc , la prioridad para include <>es, en un "sistema Unix normal", como sigue:

 /usr/local/include
 libdir/gcc/target/version/include
 /usr/target/include
 /usr/include

Para los programas C ++, también buscará primero en / usr / include / c ++ / version. En lo anterior, target es el nombre canónico del sistema para el que GCC fue configurado para compilar código; [...].

La documentación también dice:

Puede agregar a esta lista con la opción de línea de comando -Idir. Todos los directorios nombrados por -I se buscan, en orden de izquierda a derecha, antes de los directorios predeterminados . La única excepción es cuando dir ya se busca de forma predeterminada. En este caso, la opción se ignora y el orden de búsqueda de los directorios del sistema permanece sin cambios.

Para continuar con nuestro #include<list> / #include"list"ejemplo (mismo código):

g++ -I. main.cc

y

#include<list>
int main () { std::list<int> l; }

y de hecho, -I.prioriza la carpeta .sobre el sistema que incluye y obtenemos un error del compilador.

Sebastián Mach
fuente
9
Solo quiero hacerle notar que es un poco extraño que se refiera a su compilador como "su compilador", ya que la pregunta y la respuesta tienen el mismo autor.
Zapato
27
@Jeffrey: Quizás el autor de la pregunta pretendía ajustarse al formato general aquí. No sé, pregúntale.
Sebastian Mach
1
Esta respuesta es incorrecta, se #include <>ve en los directorios enumerados -Iantes de los directorios predeterminados del sistema
Jonathan Wakely
5
" Imagine que su barra de archivos está en una carpeta llamada frobnicate, relativa a foo.cc " los directorios dados con -Ison relativos al directorio donde ejecuta gcc, no al archivo que se está compilando. La diferencia es significativa si lo haceg++ -Ifrobnicate blah/foo.cc
Jonathan Wakely
3
¿La configuración de su PATHvariable de entorno (en sistemas Linux) afecta la forma en que el compilador busca archivos?
Matt Phillips