Подтвердить что ты не робот

Gcc/g++: "Нет такого файла или каталога"

g++ дает мне ошибки формы:

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

То же самое происходит при компиляции C-программ с gcc.

Почему это?


Обратите внимание: Этот вопрос задавался много раз раньше, но каждый раз он был специфичен для ситуации с искателями. Цель этого вопроса - задать вопрос о том, что другие могут быть закрыты как дубликаты, раз и навсегда; FAQ.

4b9b3361

Ответ 1

Ваш компилятор просто попытался скомпилировать файл с именем foo.cc. При попадании номера строки line компилятор обнаруживает:

#include "bar"

или

#include <bar>

Затем компилятор пытается найти этот файл. Для этого он использует набор каталогов для поиска, но в этом наборе нет файла bar. Для объяснения различия между версиями оператора include смотрите здесь.

Как сообщить компилятору, где его найти

g++ имеет опцию -I. Он позволяет добавлять пути поиска к командной строке. Представьте, что ваш файл bar находится в папке с именем frobnicate, относительно foo.cc (предположим, что вы компилируете из каталога, где находится foo.cc):

g++ -Ifrobnicate foo.cc

Вы можете добавить дополнительные include-paths; каждый, который вы даете, относится к текущему каталогу. Компилятор Microsoft имеет параметр корреляции /I, который работает аналогичным образом или в Visual Studio, папки могут быть установлены на страницах свойств проекта, в разделе "Свойства конфигурации" → C/С++ → Общие → Дополнительные каталоги включения,

Теперь представьте, что у вас есть несколько версий bar в разных папках, учитывая:


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

Приоритет с #include "bar" является самым левым:

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

Как вы видите, когда компилятор начал просматривать A/, B/ и C/, он остановился при первом или крайнем ударе.

Это относится к обеим формам, include <> и incude "".

Разница между #include <bar> и #include "bar"

Обычно #include <xxx> заставляет его сначала заглядывать в системные папки, #include "xxx" заставляет его сначала просматривать текущие или пользовательские папки.

например:.

Представьте, что в папке проекта есть следующие файлы:

list
main.cc

с main.cc:

#include "list"
....

Для этого ваш компилятор будет #include файл list в вашей папке проекта, потому что в настоящее время он компилирует main.cc и этот файл list находится в текущей папке.

Но с main.cc:

#include <list>
....

а затем g++ main.cc, ваш компилятор сначала рассмотрит системные папки, а поскольку <list> является стандартным заголовком, он будет #include файлом с именем list, который поставляется с вашей платформой С++, как часть стандартная библиотека.

Все это немного упрощено, но должно дать вам основную идею.

Подробная информация о <>/"" -priorities и -I

В соответствии с gcc-documentation приоритет для include <> находится в "нормальной системе Unix" следующим образом:

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

Для программ на С++ он также будет выглядеть в/usr/include/С++/version. В приведенном выше примере цель - это каноническое имя системы, для которой GCC был настроен для компиляции кода; [...].

В документации также указано:

Вы можете добавить в этот список опцию командной строки -Idir. Все каталоги, названные -I, выполняются в порядке слева направо перед каталогами по умолчанию. Единственное исключение - когда dir уже выполняется по умолчанию. В этом случае опция игнорируется, и порядок поиска для системных каталогов остается неизменным.

Чтобы продолжить наш пример #include<list> / #include"list" (тот же код):

g++ -I. main.cc

и

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

и действительно, -I. имеет приоритет в папке . по всей системе, и мы получаем ошибку компилятора.