Как компиляторы знают, где найти #include?

мне интересно, как компиляторы на Mac OS X, Windows и Linux знают, где найти файлы заголовков C.

в частности, мне интересно, как он знает, где найти #include с <> скобках.

#include "/Users/Brock/Desktop/Myfile.h"    // absolute reference
#include <stdio.h>                         // system relative reference?

Я предполагаю, что в системе есть текстовый файл, с которым он консультируется. Откуда он знает, где искать заголовки? Можно ли изменить этот файл, если да, то где этот файл находится в операционной системе?

6 ответов


когда компилятор построен, он знает о нескольких стандартных местоположениях для поиска файла заголовка. Некоторые из них не зависят от того, где установлен компилятор (например, /usr /include,/usr/local / include и т. д.) и некоторые из них основаны на том, где установлен компилятор (который для gcc управляется параметром --prefix при запуске configure).

местоположения, такие как /usr/include, хорошо известны, и "знание" этого местоположения встроено в gcc. Такие места, как /usr / local / include не считается полностью стандартным и может быть установлен, когда gcc построен с параметром --with-local-prefix configure.

тем не менее, вы можете добавить новые каталоги для поиска файлов include с помощью опции командной строки compiler-I. При попытке включить файл он будет выглядеть в каталогах, указанных с флагом-I перед каталогами, о которых я говорил в первом абзаце.


ОС не знает, где искать эти файлы-это делает компилятор (точнее, препроцессор). Он имеет набор путей поиска, где он знает, чтобы искать заголовки, так же, как ваша командная оболочка имеет набор мест, где она будет искать программы для выполнения при вводе имени. документация GCC объясняет как это делает компилятор и как эти пути поиска могут быть изменены.


расположение файла зависит от системы. Действительно, файл может быть предкомпилированного, или он может даже не существовать-компилятор может иметь его как "встроенный". На моем MacBook, я вижу, что есть такой файл в /usr/include/c++/4.2.1/iostream, но вы не должны полагаться на него, и это определенно плохая идея для редактирования.


в Visual Studio это либо в настройках проекта, если вы используете IDE, либо в %INCLUDE% переменная окружения при использовании командной строки.


Если вы используете g++, вы можете сделать что-то вроде этого, чтобы узнать, какие пути включения были найдены:

touch empty.cpp
g++ -v empty.cpp

Я не знаю, есть ли эквивалент для Xcode. Может быть, это будет работать, так как Xcode основан на GCC?


вы должны избегать #include-ING файлов, используя абсолютные пути. Компилятор ищет включаемые файлы в различных каталогах и включает файлы, начиная с каждого каталога. Например:

#include <boost/tokenizer.hpp>

работает, потому что корневой каталог boost содержит папку под названием "boost", и эта папка либо в вашем пути включения по умолчанию, либо вы сделали что-то вроде этого.

g++ -I$BOOST_ROOT {blah,  blah}

это стандарт C и C++, что разделитель UNIX '/' будет работать одинаково для всех системы, независимо от того, что хост-система фактически использует для обозначения каталогов. Как упоминалось выше, иногда #include вообще не включает реальный файл.