Как узнать, откуда включен заголовочный файл?

101

Как узнать, где g ++ нашел включаемый файл? В основном, если я

#include <foo.h>

g ++ просканирует путь поиска, используя любые параметры включения для добавления или изменения пути. Но, в конце концов, есть ли способ определить абсолютный путь к foo.h, который g ++ выбрал для компиляции? Особенно актуально, если во множестве путей поиска есть более одного foo.h.

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

резьба
источник
1
Связано: есть ли способ узнать, из какого родительского включаемого файла (ов) был включен дочерний включаемый файл? То есть, чтобы показать граф включенного из (подсказка: gcc -E не совсем там ... может быть обработан, чтобы получить его.)
Крейзи Глю

Ответы:

79

Это даст make зависимости, в которых перечислены абсолютные пути включаемых файлов:

gcc  -M showtime.c

Если вы не хотите, чтобы система включала (т.е. #include <something.h>), используйте:

gcc  -MM showtime.c
Содвед
источник
18
Следует отметить, что если вы используете вместе с «-o myObj.o», вывод, а не скомпилированный двоичный файл, попадает в «myObj.o». -M имеет неявное значение -E, поэтому компиляция не выполняется. Я обнаружил, что -MD - очень полезный параметр, вместо этого он выполняет компиляцию и помещает вывод в myObj.d. Создание подходящего параметра для добавления в строку компиляции без странных эффектов, таких как * .o, теперь содержит вывод вместо двоичного файла. Спасибо за вашу помощь.
harschware
Все связанные параметры gcc описаны здесь .
Ахан
108
g++ -H ...

также напечатает полный путь к включаемым файлам в формате, который показывает, какой заголовок включает какие

Пулямагнит
источник
7
По моему опыту, это кажется более полезным, чем -M. Мне нравится иерархическое отображение того, что включает в себя.
Брайан Минтон
Хорошо, это полезно для отладки.
1
Это лучший ответ. Вы можете добавить его в процесс сборки, ничего не меняя.
Timmmm 03
4
Это действительно больше отвечает на вопрос, чем принятый ответ. Единственная досадная проблема в том, что я не смог заставить Clang остановить попытки скомпилировать файл в обычном режиме, поэтому в итоге я использовал clang++ -MM -H(что немного полезная комбинация).
rookie1024
@ rookie1024 Используйте, clang++ -H -fsyntax-only ...если вы не хотите создавать файлы вывода ( gccтоже работает ).
Lekensteyn
8

Конечно использовать

g++ -E -dI  ... (whatever the original command arguments were)
Wallyk
источник
2
У этого решения есть несколько преимуществ: 1. Вы можете обнаружить несколько включений одного файла заголовка (-H и -M печатают каждый включенный файл только один раз) 2. Вы можете видеть, где он включен (имя и номер строки оригинала включить инструкцию). 3. Таким образом, вы можете надежно (!)
Определить,
5

Если вы используете -MMили один из связанных параметров ( -Mи т. Д.), Вы получаете только список заголовков, которые включены, без вывода всех остальных выходных данных препроцессора (которые вы, кажется, получаете с предлагаемым g++ -E -dIрешением).

Джонатан Леффлер
источник
g++ -MM t.ccне показывает включения вообще, просто t.o: t.cc. А что-то еще нужно?
wallyk
3
Приятно - для полноты вы можете получить подобное с MSVC, используя /showIncludesопцию. MSVC даже сделает отступ, чтобы показать вам вложение заголовков (я не вижу этого -Mв GCC).
Майкл Берр