gcc / g ++: “Nenhum arquivo ou diretório”

87

g++ me dá erros no formulário:

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

É o mesmo ao compilar programas C com gcc.

Por que é que?


Observação: Esta pergunta já foi feita muitas vezes antes, mas cada vez era específica para a situação de quem pergunta. O objetivo desta pergunta é ter uma pergunta que outras pessoas podem ser fechadas como duplicatas , de uma vez por todas; um FAQ .

Sebastian Mach
fonte
4
Boa adição ao FAQ. Te agradece!
sbi

Respostas:

116

Seu compilador acabou de tentar compilar o arquivo chamado foo.cc. Ao atingir o número da linha line, o compilador encontra:

#include "bar"

ou

#include <bar>

O compilador então tenta encontrar esse arquivo. Para isso, ele usa um conjunto de diretórios para pesquisar, mas dentro desse conjunto, não há nenhum arquivo bar. Para obter uma explicação da diferença entre as versões da instrução include, clique aqui .

Como dizer ao compilador onde encontrá-lo

g++tem uma opção -I. Ele permite que você adicione caminhos de pesquisa de inclusão à linha de comando. Imagine que seu arquivo barestá em uma pasta chamada frobnicate, relativo a foo.cc(suponha que você esteja compilando a partir do diretório onde foo.ccestá localizado):

g++ -Ifrobnicate foo.cc

Você pode adicionar mais caminhos de inclusão; cada um dado é relativo ao diretório atual. O compilador da Microsoft possui uma opção de correlação /Ique funciona da mesma maneira, ou no Visual Studio, as pastas podem ser definidas nas páginas de propriedades do projeto, em Propriedades de configuração-> C / C ++ -> Geral-> Diretórios adicionais de inclusão.

Agora imagine que você tenha várias versões de barem pastas diferentes, dadas:


// 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;
}

A prioridade com #include "bar"é a mais à esquerda:

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

Como você vê, quando o compilador começou a olhar através A/, B/e C/, ele parou na primeira ou hit mais à esquerda.

Isso é verdade para ambas as formas include <>e incude "".

Diferença entre #include <bar>e#include "bar"

Normalmente, #include <xxx>faz com que ele examine primeiro as pastas do sistema e primeiro as pastas #include "xxx"atuais ou personalizadas.

Por exemplo:

Imagine que você tenha os seguintes arquivos na pasta do seu projeto:

list
main.cc

com main.cc:

#include "list"
....

Para isso, seu compilador irá colocar #includeo arquivo listna pasta do seu projeto, pois ele atualmente compila main.cce existe esse arquivo listna pasta atual.

Mas com main.cc:

#include <list>
....

e g++ main.cc, em seguida , seu compilador examinará primeiro as pastas do sistema e, por <list>ser um cabeçalho padrão, encontrará #includeo arquivo nomeado listque vem com sua plataforma C ++ como parte da biblioteca padrão.

Tudo isso é um pouco simplificado, mas deve lhe dar uma ideia básica.

Detalhes sobre as prioridades <>/ ""e-I

De acordo com a documentação do gcc , a prioridade para include <>é, em um "sistema Unix normal", como segue:

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

Para programas C ++, ele também irá procurar em / usr / include / c ++ / version, primeiro. Acima, target é o nome canônico do sistema para o qual o GCC foi configurado para compilar o código; [...].

A documentação também afirma:

Você pode adicionar a esta lista com a opção de linha de comando -Idir. Todos os diretórios nomeados por -I são pesquisados, da esquerda para a direita, antes dos diretórios padrão . A única exceção é quando dir já é pesquisado por padrão. Nesse caso, a opção é ignorada e a ordem de pesquisa dos diretórios do sistema permanece inalterada.

Para continuar nosso #include<list> / #include"list"exemplo (mesmo código):

g++ -I. main.cc

e

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

e, de fato, o -I.prioriza a pasta .sobre o sistema inclui e obtemos um erro do compilador.

Sebastian Mach
fonte
9
Só quero que você perceba que é meio estranho que você se refira ao seu compilador como "seu compilador", já que a pergunta e a resposta têm o mesmo autor.
Sapato
27
@Jeffrey: Talvez o autor da pergunta pretendesse se encaixar no formato geral aqui. Não sei, pergunte a ele.
Sebastian Mach
1
Esta resposta está errada, #include <>procure nos diretórios listados com -Iantes dos diretórios padrão do sistema
Jonathan Wakely
5
" Imagine que sua barra de arquivos está em uma pasta chamada frobnicate, em relação a foo.cc ", os diretórios fornecidos com -Isão relativos ao diretório onde você executa o gcc, e não ao arquivo que está sendo compilado. A diferença é significativa se você fizer issog++ -Ifrobnicate blah/foo.cc
Jonathan Wakely,
3
As configurações de sua PATHvariável de ambiente (em sistemas Linux) afetam como o compilador procura por arquivos?
Matt Phillips