Поделиться через


Справочник по header-units.json C++

Файл header-units.json служит двумя целями:

  • Укажите, какие файлы заголовков можно преобразовать в единицы заголовков при /translateInclude указании.
  • Свести к минимуму повторяющиеся символы, чтобы увеличить пропускную способность сборки.

Этот файл должен находиться в том же каталоге, что и включенный файл заголовка. Этот файл используется только в том случае, если /translateInclude он указан вместе с /scanDependencies ним или /sourceDependencies:directives.

Правильно

Некоторые файлы заголовков не могут быть безопасно переведены в единицы заголовков. Файлы заголовков, зависящие от макросов, которые не определены в командной строке, или которые не определены в файлах заголовков, включенных в заголовок, нельзя преобразовать в единицы заголовков.

Если заголовок определяет макросы, влияющие на включение других заголовков, его невозможно безопасно преобразовать. Например, задано a.hb.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 указан, то происходит следующее:

  1. Сканирование и c.h списки b.h в виде импорта единицы заголовка a.h в файлах проверки зависимостей, созданных компилятором.
  2. Система сборки считывает файлы проверки зависимостей и определяет сначала сборку b.h.ifc .
  3. Затем система сборки добавляется /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++