Семейство языков Си/Objective C/C++ нуждается в препроцессоре. Препроцессор пропускает компилируемый исходник через себя, прежде чем отдать текст на вход компилятору. Пожалуй самая важная часть работы препроцессора заключается в подстановке на место директив #include<имя-файла>
содержимого указанного файла. Обычно указывают относительный путь (ex: stdio.h
, sys/stat.h
). Возникает закономерный вопрос — как препроцессор находит заголовочные файлы?
Классический ответ такой: препроцессор последовательно перебирает пути в INCLUDE_PATH начиная с первого. Относительный путь из директивы include разрешается относительно (sic) папки из INCLUDE_PATH. Если файл не найден, переходим к следующему элементу INCLUDE_PATH. Если INCLUDE_PATH исчерпан, компилятор сообщает об ошибке.
Но Apple как всегда вносит свои коррективы. При сборке в XCode дополнительно используются т.н. header map. Это индекс всех заголовочных файлов в проекте. Если XCode «знает» про foobar.h, то данный файл будет доступен просто по имени (#include<foobar.h>
), вне зависимости от фактического размещения на файловой системе.
Это прекрасное решение — до тех пор, пока оно работает как задумано. К сожалению, механизм header map плохо документирован, что не способствует быстрому разрешению проблем. Постараюсь восполнить этот пробел.