Справочник по header-units.json C++
Файл header-units.json
служит двумя целями:
- Укажите, какие файлы заголовков можно преобразовать в единицы заголовков при
/translateInclude
указании. - Свести к минимуму повторяющиеся символы, чтобы увеличить пропускную способность сборки.
Этот файл должен находиться в том же каталоге, что и включенный файл заголовка. Этот файл используется только в том случае, если /translateInclude
он указан вместе с /scanDependencies
ним или /sourceDependencies:directives
.
Правильно
Некоторые файлы заголовков не могут быть безопасно переведены в единицы заголовков. Файлы заголовков, зависящие от макросов, которые не определены в командной строке, или которые не определены в файлах заголовков, включенных в заголовок, нельзя преобразовать в единицы заголовков.
Если заголовок определяет макросы, влияющие на включение других заголовков, его невозможно безопасно преобразовать. Например, задано a.h
b.h
и macros.h
, которые находятся в одном каталоге:
// a.h
#include "macros.h" // #defines MACRO=1
#ifdef MACRO
#include "b.h"
#endif
В этом каталоге header-units.json
может содержаться a.h
и b.h
, но не macros.h
. Пример header-units.json
этого примера аналогичен следующему:
{
"Version": "1.0",
"BuildAsHeaderUnits": [
// macros.h should not be listed
"a.h",
"b.h"
]
}
macros.h
Причина не может быть указана в этом header-units.json
файле в том, что во время этапа сканирования блок заголовка (.ifc
) может быть скомпилирован еще не для macros.h
. В этом случае MACRO
не будет определяться при a.h
компиляции. Это означает, что b.h
в списке зависимостей a.h
отсутствует. Так как он отсутствует в списке зависимостей, система сборки не будет создавать блок заголовка, b.h
несмотря на то, что он указан в header-units.json
файле.
Чтобы избежать этой проблемы, при наличии зависимости от макроса в другом файле заголовка файл заголовка, определяющий макрос, исключается из списка файлов, которые можно скомпилировать в единицу заголовка. Таким образом, файл заголовка, определяющий макрос, обрабатывается как обычный #include
и MACRO
будет виден таким образом, чтобы b.h
он был включен и указан как один из зависимостей.
Предотвращение повторяющихся символов
Файл header-units.json
также важен, так как он позволяет автоматически создавать блок заголовков без повторяющихся символов. Это делается путем создания "атомарных" блоков заголовков для файлов, перечисленных в header-units.json
. Импортированные блоки заголовков не содержат повторяющиеся символы из различных #include
директив, которые были обработаны при переводе файла заголовка.
Например, рассмотрим два файла заголовка, которые включают общий файл заголовка. Оба файла заголовка включаются в один и тот же исходный файл:
// a.h
#include "b.h"
// c.h
#include "b.h"
// Source.cpp
import "a.h";
import "c.h";
Если компилятор создал блоки заголовков для a.h
, b.h
а c.h
затем скомпилированные единицы a.h.ifc
заголовков, b.h.ifc
и c.h.ifc
каждый из них содержит все типы из b.h
. Компиляция Source.cpp
, которая импортирует оба a.h
и c.h
, потребует от компилятора дедупликации b.h
типов, что повлияет на производительность сборки.
Но если в каталоге header-units.json
b.h
есть и /translateInclude
указан, то происходит следующее:
- Сканирование и
c.h
спискиb.h
в виде импорта единицы заголовкаa.h
в файлах проверки зависимостей, созданных компилятором. - Система сборки считывает файлы проверки зависимостей и определяет сначала сборку
b.h.ifc
. - Затем система сборки добавляется
/headerUnit
вb.h.ifc
командные строки для компиляцииa.h
иc.h
. Он вызывает компилятор для сборки единицa.h.ifc
заголовка иc.h.ifc
. Так как/translateInclude
он указан, а/headerUnit for b.h.ifc
также указанa.h.ifc
иc.h.ifc
не будет содержатьb.h
типы, поэтому в единицах созданных заголовков не будет дублирования.
Схема
headerunits.json
Существует файл заголовков стандартной библиотеки шаблонов (STL). Система сборки использует ее для определения того, следует ли создавать блок заголовка для файла заголовка STL и для зависимостей. Если файл заголовка STL не находится в списке, он рассматривается как обычный #include
вместо импорта его в виде единицы заголовка.
Файл можно просмотреть header-units.json
в каталоге установки для Visual Studio. Например: %ProgramFiles%\Microsoft Visual Studio\2022\Enterprise\VC\Tools\MSVC\14.30.30705\include\header-units.json
Файл header-units.json
начинается с версии схемы, за которой следует массив имен файлов для заголовков, которые могут быть встроены в единицы заголовков.
Схема также поддерживает комментарии, как показано здесь:
{
"Version": "1.0",
"BuildAsHeaderUnits": [
// "__msvc_all_public_headers.hpp", // for testing, not production
"__msvc_system_error_abi.hpp",
"__msvc_tzdb.hpp",
"__msvc_xlocinfo_types.hpp",
"algorithm",
"any",
"array",
"atomic",
"barrier",
"bit",
"bitset",
// "cassert", // design is permanently incompatible with header units
...
}
Поиск среди правил
Компилятор ищет этот файл в том же каталоге, что и обработанный файл заголовка. Если библиотека организована в подкаталогах, каждый подкаталог должен иметь собственный header-units.json
файл.
См. также
Пошаговое руководство. Импорт библиотек STL в качестве блоков заголовков
Создание и импорт блоков заголовков в проектах Visual C++