G CC и Clang поддерживают опцию -H
(а также опцию -M
и ее родственников).
-H
Печать имени каждого используемого файла заголовка в дополнение к другим обычным действиям. Каждое имя имеет отступ, чтобы показать, насколько глубоко оно находится в стеке #include
. Предварительно скомпилированные заголовочные файлы также печатаются, даже если они признаны недействительными; неверный предварительно скомпилированный заголовочный файл печатается с '...x
', а действительный с '...!
'.
Вывод -H
сообщается о стандартной ошибке, а не о стандартном выводе.
Опция -H
дает больше и другую информацию по сравнению с опцией -M
. Он сообщает об уровнях вложенности (одна или несколько начальных точек) и показывает каждый раз, когда заголовок включен - даже если содержимое игнорируется из-за макросов защиты заголовка:
#ifndef HEADER_H_INCLUDED
#define HEADER_H_INCLUDED
…content of header…
#endif /* HEADER_H_INCLUDED */
Это может быть полезно; форматированные make
строки зависимостей (генерируемые -M
) также могут быть полезны.
Пример вывода (при компиляции одного исходного файла из одной из моих программ - make
сгенерировал компилятор командная строка, конечно):
$ gcc -H -g -O3 -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition -DSYSTEM=MACOS_X -DSTR_SYSTEM='"(macOS Mojave 10.14.6 - Darwin 18.7.0)"' -I/Users/jonathanleffler/inc -DDEBUG -DHASH_STATISTICS -c main.c
. make.h
.. /Users/jonathanleffler/inc/posixver.h
.. config.h
.. /usr/include/assert.h
... /usr/include/sys/cdefs.h
.... /usr/include/sys/_symbol_aliasing.h
.... /usr/include/sys/_posix_availability.h
.. /usr/include/ctype.h
... /usr/include/_ctype.h
.... /usr/include/runetype.h
..... /usr/include/_types.h
...... /usr/include/sys/_types.h
....... /usr/include/machine/_types.h
........ /usr/include/i386/_types.h
....... /usr/include/sys/_pthread/_pthread_types.h
.. /usr/include/errno.h
... /usr/include/sys/errno.h
.. /usr/include/inttypes.h
... /usr/include/Availability.h
.... /opt/gcc/v9.2.0/lib/gcc/x86_64-apple-darwin18.7.0/9.2.0/include-fixed/AvailabilityInternal.h
... /usr/include/sys/_types/_wchar_t.h
... /opt/gcc/v9.2.0/lib/gcc/x86_64-apple-darwin18.7.0/9.2.0/include/stdint.h
.... /opt/gcc/v9.2.0/lib/gcc/x86_64-apple-darwin18.7.0/9.2.0/include-fixed/stdint.h
..... /usr/include/sys/_types/_int8_t.h
..... /usr/include/sys/_types/_int16_t.h
..... /usr/include/sys/_types/_int32_t.h
..... /usr/include/sys/_types/_int64_t.h
..... /usr/include/_types/_uint8_t.h
..... /usr/include/_types/_uint16_t.h
..... /usr/include/_types/_uint32_t.h
..... /usr/include/_types/_uint64_t.h
..... /usr/include/sys/_types/_intptr_t.h
...... /usr/include/machine/types.h
....... /usr/include/i386/types.h
........ /usr/include/sys/_types/_u_int8_t.h
........ /usr/include/sys/_types/_u_int16_t.h
........ /usr/include/sys/_types/_u_int32_t.h
........ /usr/include/sys/_types/_u_int64_t.h
........ /usr/include/sys/_types/_intptr_t.h
........ /usr/include/sys/_types/_uintptr_t.h
..... /usr/include/_types/_intmax_t.h
..... /usr/include/_types/_uintmax_t.h
.. /opt/gcc/v9.2.0/lib/gcc/x86_64-apple-darwin18.7.0/9.2.0/include-fixed/limits.h
... /opt/gcc/v9.2.0/lib/gcc/x86_64-apple-darwin18.7.0/9.2.0/include-fixed/syslimits.h
.... /opt/gcc/v9.2.0/lib/gcc/x86_64-apple-darwin18.7.0/9.2.0/include-fixed/limits.h
..... /usr/include/limits.h
...... /usr/include/machine/limits.h
....... /usr/include/i386/limits.h
........ /usr/include/i386/_limits.h
...... /usr/include/sys/syslimits.h
.. /opt/gcc/v9.2.0/lib/gcc/x86_64-apple-darwin18.7.0/9.2.0/include/stdbool.h
.. /opt/gcc/v9.2.0/lib/gcc/x86_64-apple-darwin18.7.0/9.2.0/include-fixed/stdio.h
... /opt/gcc/v9.2.0/lib/gcc/x86_64-apple-darwin18.7.0/9.2.0/include/stdarg.h
... /usr/include/_stdio.h
.... /usr/include/sys/_types/_va_list.h
.... /usr/include/sys/_types/_size_t.h
.... /usr/include/sys/_types/_null.h
.... /usr/include/sys/stdio.h
... /usr/include/sys/_types/_off_t.h
... /usr/include/sys/_types/_ssize_t.h
... /usr/include/secure/_stdio.h
.... /usr/include/secure/_common.h
.. /usr/include/stdlib.h
... /usr/include/sys/wait.h
.... /usr/include/sys/_types/_pid_t.h
.... /usr/include/sys/_types/_id_t.h
.... /usr/include/sys/signal.h
..... /usr/include/sys/appleapiopts.h
..... /usr/include/machine/signal.h
...... /usr/include/i386/signal.h
..... /usr/include/machine/_mcontext.h
...... /usr/include/i386/_mcontext.h
....... /usr/include/mach/machine/_structs.h
........ /usr/include/mach/i386/_structs.h
..... /usr/include/sys/_pthread/_pthread_attr_t.h
..... /usr/include/sys/_types/_sigaltstack.h
..... /usr/include/sys/_types/_ucontext.h
...... /usr/include/machine/_mcontext.h
..... /usr/include/sys/_types/_sigset_t.h
..... /usr/include/sys/_types/_uid_t.h
.... /usr/include/sys/resource.h
..... /usr/include/sys/_types/_timeval.h
... /usr/include/sys/_types/_wchar_t.h
... /usr/include/malloc/_malloc.h
.. /usr/include/string.h
... /usr/include/secure/_string.h
.. /usr/include/sys/stat.h
... /usr/include/sys/_types/_timespec.h
... /usr/include/sys/_types/_blkcnt_t.h
... /usr/include/sys/_types/_blksize_t.h
... /usr/include/sys/_types/_dev_t.h
... /usr/include/sys/_types/_ino_t.h
... /usr/include/sys/_types/_mode_t.h
... /usr/include/sys/_types/_nlink_t.h
... /usr/include/sys/_types/_gid_t.h
... /usr/include/sys/_types/_time_t.h
... /usr/include/sys/_types/_s_ifmt.h
.. /usr/include/unistd.h
... /usr/include/sys/unistd.h
.... /usr/include/sys/_types/_posix_vdisable.h
.... /usr/include/sys/_types/_seek_set.h
... /usr/include/sys/_types/_useconds_t.h
.. /Users/jonathanleffler/inc/debug.h
... /Users/jonathanleffler/inc/kludge.h
.. /Users/jonathanleffler/inc/emalloc.h
.. list.h
.. /Users/jonathanleffler/inc/sastrings.h
.. /Users/jonathanleffler/inc/stderr.h
... /opt/gcc/v9.2.0/lib/gcc/x86_64-apple-darwin18.7.0/9.2.0/include/stdarg.h
. /Users/jonathanleffler/inc/getopt.h
Multiple include guards may be useful for:
/opt/gcc/v9.2.0/lib/gcc/x86_64-apple-darwin18.7.0/9.2.0/include-fixed/syslimits.h
/usr/include/assert.h
/usr/include/errno.h
/usr/include/machine/limits.h
/usr/include/secure/_stdio.h
/usr/include/secure/_string.h
/usr/include/sys/_posix_availability.h
/usr/include/sys/_symbol_aliasing.h
/usr/include/sys/_types/_seek_set.h
$
, которая перечисляет 110 заголовков; повторяются только пять:
2 /opt/gcc/v9.2.0/lib/gcc/x86_64-apple-darwin18.7.0/9.2.0/include-fixed/limits.h
2 /opt/gcc/v9.2.0/lib/gcc/x86_64-apple-darwin18.7.0/9.2.0/include/stdarg.h
2 /usr/include/machine/_mcontext.h
2 /usr/include/sys/_types/_intptr_t.h
2 /usr/include/sys/_types/_wchar_t.h
В других проектах, над которыми я работаю, повторений много. Если взять один исходный файл, более или менее произвольно (я знаю, что это большой файл; я не думаю, что он худший), то есть список заголовков, включенных 4 или более раз - многие включаются 2 и 3 раза. Общее количество строк заголовка из -H
для этого файла составляет 592. Специфичные для проекта c имена каталогов и файлов были изменены, чтобы защитить невинных - и имена файлов были замаскированы с realpath(2)
, чтобы иметь дело с особенностями c использование имен стилей ../subdir/header.h
в исходном коде и во включенных заголовках, которые -H
расширяются до имен, таких как:
../incl/../subdir1/../subdir1/../subdir2/../subdir2/header27.h
Количество:
4 /usr/include/errno.h
4 /usr/include/time.h
4 /opt/project/incl/header1.h
4 /opt/project/incl/header2.h
4 /opt/project/subdir/header3.h
4 /opt/project/subdir/header4.h
4 /opt/project/subdir/header5.h
5 /opt/project/incl/header6.h
5 /opt/project/subdir/header7.h
6 /opt/project/subdir/header8.h
6 /opt/project/subdir/header9.h
6 /work5/gcc/v9.2.0/lib/gcc/x86_64-pc-linux-gnu/9.2.0/include-fixed/limits.h
7 /opt/project/subdir/header10.h
14 /usr/include/bits/wordsize.h
14 /opt/project/subdir/header11.h
22 /work5/gcc/v9.2.0/lib/gcc/x86_64-pc-linux-gnu/9.2.0/include/stddef.h