Compartir a través de


Referencia C++ header-units.json

El archivo header-units.json tiene dos fines:

  • Especifique qué archivos de encabezado se pueden trasladar a unidades de encabezado cuando se especifica /translateInclude.
  • Minimice los símbolos duplicados para aumentar el rendimiento de la compilación.

Este archivo debe de estar en el mismo directorio que el archivo de encabezado incluido. Este archivo solo se usa cuando /translateInclude se especifica con /scanDependencies o /sourceDependencies:directives.

Análisis razonado

Algunos archivos de encabezado no se pueden trasladar con seguridad a unidades de encabezado. Los archivos de encabezado que dependen de las macros que no están definidas en la línea de comandos o que no están definidas en los archivos de encabezado incluidos por el encabezado, no se pueden trasladar a unidades de encabezado.

Si un encabezado define las macros que afectan a si se incluyen otros encabezados, no se puede trasladar con seguridad. Por ejemplo, considerando que a.h, b.h y macros.h, están en el mismo directorio:

// a.h

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

El header-units.json este directorio puede contener a.h y b.h, pero no macros.h. El header-units.json para este ejemplo sería parecido a esto:

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

El motivo macros.h por el que no se puede enumerar en este archivo header-units.json es porque, durante la fase de examen, es posible que la unidad de encabezado (.ifc) todavía no se compile para macros.h. En ese caso, MACRO no se definirá cuando se compile a.h. Esto significa que b.h faltará en la lista de dependencias de a.h. Dado que no está en la lista de dependencias, el sistema de compilación no compilará una unidad de encabezado para b.h a pesar de que se muestre en el header-units.json archivo.

Para evitar este problema, cuando hay una dependencia de una macro en otro archivo de encabezado, el archivo de encabezado que define la macro se excluye de la lista de archivos que se pueden compilar en una unidad de encabezado. De este modo, el archivo de encabezado que define la macro se trata como normal #include y MACRO estará visible para que b.h se incluya y aparezca como una de las dependencias.

Evitar los símbolos duplicados

El archivo header-units.json también es importante porque permite la creación automática de unidades de encabezado sin símbolos duplicados. Para ello, crea unidades de encabezado "atómicas" para los archivos listados en header-units.json. Las unidades de encabezado importadas no contienen los símbolos duplicados de las distintas directivas #include que se han procesado al trasladar el archivo de encabezado.

Por ejemplo, considere dos archivos de encabezado que incluyan un archivo de encabezado común. Los dos archivos de encabezado están incluidos en el mismo archivo de código fuente:

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

Si el compilador compila las unidades de encabezado para a.h, b.h y c.h, entonces las unidades de cabecera compiladas a.h.ifc, b.h.ifc y c.h.ifc contienen cada una todos los tipos de b.h. Compilar Source.cppque importa tanto a.h como c.h, requeriría que el compilador desduplique los tipos b.h, lo que afectaría al rendimiento de la compilación.

Pero si hay un header-units.json elemento en el b.h directorio y /translateInclude se especifica, se produce lo siguiente:

  1. El examen de a.h y c.h enumera b.h como una importación de unidad de encabezado en los archivos de examen de dependencias generados por el compilador.
  2. El sistema de compilación lee los archivos de examen de dependencias y determina primero compilar b.h.ifc.
  3. Entonces, el sistema de compilación agrega /headerUnit para b.h.ifc a las líneas de comandos para compilar a.h y c.h. Llama al compilador para compilar las unidades de encabezado a.h.ifc y c.h.ifc. Dado que se especifica /translateInclude y también /headerUnit for b.h.ifc,a.h.ifc y c.h.ifc no contendrá los tipos b.h, por lo que no habrá ninguna duplicación en las unidades de encabezado generadas.

Esquema

Hay un archivo headerunits.json para los encabezados de la Biblioteca de plantillas estándar (STL). El sistema de compilación lo usa para determinar si se crea una unidad de encabezado para un archivo de encabezado STL y para sus dependencias. Si el archivo de encabezado de STL no está en la lista, se trata como #include normal en lugar de importarlo como una unidad de encabezado.

Puede ver el archivo header-units.json en el directorio de instalación de Visual Studio. Por ejemplo: %ProgramFiles%\Microsoft Visual Studio\2022\Enterprise\VC\Tools\MSVC\14.30.30705\include\header-units.json

El archivo header-units.json comienza con la versión del esquema, seguida de una matriz de nombres de archivo para los encabezados que se pueden integrar en las unidades de encabezado.

El esquema también admite los comentarios, como se muestra aquí:

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

Buscar reglas

El compilador busca este archivo en el mismo directorio que el archivo de encabezado que se está procesando. Si la biblioteca se organiza en subdirectorios, cada subdirectorio necesita su propio archivo header-units.json.

Consulte también

Tutorial: Importación de bibliotecas STL como unidades de encabezado
Tutorial: Compilación e importación de unidades de encabezado en proyectos de Visual C++