Partilhar via


Referência C++ de header-units.json

O arquivo header-units.json tem duas finalidades.

  • Especifique quais arquivos de cabeçalho podem ser convertidos em unidades de cabeçalho quando /translateInclude é especificado.
  • Minimize símbolos duplicados para aumentar a taxa de transferência de compilação.

Esse arquivo deve estar no mesmo diretório que o arquivo de cabeçalho incluído. Esse arquivo só é usado quando /translateInclude é especificado junto com /scanDependencies ou /sourceDependencies:directives.

Fundamento

Alguns arquivos de cabeçalho não podem ser convertidos com segurança em unidades de cabeçalho. Arquivos de cabeçalho que dependem de macros que não estão definidas na linha de comando ou que não estão definidas nos arquivos de cabeçalho incluídos pelo cabeçalho, não podem ser convertidos em unidades de cabeçalho.

Se um cabeçalho definir macros que afetam se outros cabeçalhos estão incluídos, ele não poderá ser convertido com segurança. Por exemplo, dado a.h, b.h e macros.h, que estão todos no mesmo diretório:

// a.h

#include "macros.h" // #defines MACRO=1
#ifdef MACRO
#include "b.h"
#endif

O header-units.json neste diretório pode conter a.h e b.h, mas não macros.h. O header-units.json para este exemplo seria semelhante a:

{
    "Version": "1.0",
    "BuildAsHeaderUnits": [
        // macros.h should not be listed
        "a.h",
        "b.h"         
     ] 
}

O motivo pelo qual macros.h não pode ser listado neste arquivo header-units.json é que, durante a fase de verificação, a unidade de cabeçalho (.ifc) pode não ser compilada ainda para macros.h. Nesse caso, MACRO não será definido quando a.h for compilado. Isso significa que b.h não estará na lista de dependências para a.h. Como ele não está na lista de dependências, o sistema de compilação não criará uma unidade de cabeçalho para b.h apesar de estar listada header-units.json no arquivo.

Para evitar esse problema, quando há uma dependência de uma macro em outro arquivo de cabeçalho, o arquivo de cabeçalho que define a macro é excluído da lista de arquivos que podem ser compilados em uma unidade de cabeçalho. Dessa forma, o arquivo de cabeçalho que define a macro é tratado como normal #include e ficará visível para que b.h seja incluído e MACRO listado como uma das dependências.

Impedindo símbolos duplicados

O arquivo header-units.json também é importante porque permite a criação automática de unidade de cabeçalho sem símbolos duplicados. Ele faz isso criando unidades de cabeçalho "atômicas" para os arquivos listados em header-units.json. As unidades de cabeçalho importadas não contêm símbolos duplicados das várias diretivas #include que foram processadas ao traduzir o arquivo de cabeçalho.

Por exemplo, considere dois arquivos de cabeçalho que incluem um arquivo de cabeçalho comum. Ambos os arquivos de cabeçalho são incluídos pelo mesmo arquivo de origem:

// a.h
#include "b.h"
 
// c.h
#include "b.h"
 
// Source.cpp
import "a.h";
import "c.h";

Se o compilador construísse unidades de cabeçalho para a.h, b.h e c.h, então as unidades de cabeçalho compiladas a.h.ifc, b.h.ifc e c.h.ifc conteriam todos os tipos de b.h. Compilar Source.cpp, que importa a.h e c.h, exigiria que o compilador desduplicasse os tipos b.h, o que afetaria o desempenho da compilação.

Mas se houver um header-units.json no b.h diretório e /translateInclude for especificado, ocorrerá o seguinte:

  1. A digitalização de a.h e c.h lista b.h como uma importação de unidade de cabeçalho nos arquivos de digitalização de dependência gerados pelo compilador.
  2. O sistema de compilação lê os arquivos de verificação de dependência e determina a compilação b.h.ifc primeiro.
  3. Em seguida, o sistema de compilação adiciona /headerUnit para b.h.ifc às linhas de comando para compilar a.h e c.h. Ele chama o compilador para criar as unidades a.h.ifc de cabeçalho e c.h.ifc. Como /translateInclude e /headerUnit for b.h.ifc são especificados, a.h.ifc e c.h.ifc não conterão tipos b.h, portanto, não haverá duplicação nas unidades de cabeçalho produzidas.

Esquema

Há um arquivo headerunits.json para os cabeçalhos stl (Biblioteca de Modelos Padrão). O sistema de build o usa para determinar se é necessário criar uma unidade de cabeçalho para um arquivo de cabeçalho STL e suas dependências. Se o arquivo de cabeçalho STL não estiver na lista, ele será tratado como um #include normal, em vez de importá-lo como uma unidade de cabeçalho.

Você pode ver o arquivo header-units.json no diretório de instalação do Visual Studio. Por exemplo: %ProgramFiles%\Microsoft Visual Studio\2022\Enterprise\VC\Tools\MSVC\14.30.30705\include\header-units.json

O arquivo header-units.json começa com a versão do esquema, seguida por uma matriz de nomes de arquivo para cabeçalhos que podem ser incorporados em unidades de cabeçalho.

O esquema também dá suporte a comentários, conforme mostrado aqui:

{
    "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
        ...
}

Pesquisar regras

O compilador procura esse arquivo no mesmo diretório que o arquivo de cabeçalho que está sendo processado. Se a biblioteca for organizada em subdiretórios, cada subdiretório precisará de seu próprio arquivo header-units.json.

Confira também

Passo a passo: Importar bibliotecas STL como unidades de cabeçalho
Guia Passo a passo: compilar e importar unidades de cabeçalho em seus projetos do Visual C++