Partager via


Référence header-units.json C++

Le header-units.json fichier a deux objectifs :

  • Spécifiez les fichiers d’en-tête qui peuvent être traduits en unités d’en-tête lorsqu’ils /translateInclude sont spécifiés.
  • Réduisez les symboles dupliqués pour augmenter le débit de build.

Ce fichier doit se trouver dans le même répertoire que le fichier d’en-tête inclus. Ce fichier est utilisé uniquement lorsqu’il /translateInclude est spécifié avec l’un ou l’autre /scanDependencies /sourceDependencies:directives.

Rationale

Certains fichiers d’en-tête ne peuvent pas être traduits en toute sécurité en unités d’en-tête. Les fichiers d’en-tête qui dépendent de macros qui ne sont pas définies sur la ligne de commande ou qui ne sont pas définis dans les fichiers d’en-tête inclus par l’en-tête ne peuvent pas être traduits en unités d’en-tête.

Si un en-tête définit des macros qui affectent si d’autres en-têtes sont inclus, il ne peut pas être traduit en toute sécurité. Par exemple, donné a.h, b.h et macros.h, qui sont tous dans le même répertoire :

// a.h

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

Le header-units.json répertoire de ce répertoire peut contenir a.h et b.h, mais pas macros.h. L’exemple header-units.json suivant est similaire à ce qui suit :

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

La raison macros.h pour laquelle vous ne pouvez pas être répertorié dans ce header-units.json fichier est que pendant la phase d’analyse, l’unité d’en-tête (.ifc) n’est peut-être pas encore compilée pour macros.h. Dans ce cas, MACRO elle ne sera pas définie quand a.h elle est compilée. Cela signifie b.h qu’il manquera la liste des dépendances pour a.h. Étant donné qu’il n’est pas dans la liste des dépendances, le système de build ne génère pas d’unité d’en-tête pour b.h malgré sa liste dans le header-units.json fichier.

Pour éviter ce problème, lorsqu’il existe une dépendance sur une macro dans un autre fichier d’en-tête, le fichier d’en-tête qui définit la macro est exclu de la liste des fichiers qui peuvent être compilés dans une unité d’en-tête. De cette façon, le fichier d’en-tête qui définit la macro est traité comme une normale #include et sera visible de MACRO sorte qu’il b.h soit inclus et répertorié comme l’une des dépendances.

Prévention des symboles dupliqués

Le header-units.json fichier est également important, car il permet la création automatique de l’unité d’en-tête sans symboles en double. Pour ce faire, créez des unités d’en-tête « atomiques » pour les fichiers répertoriés dans header-units.json. Les unités d’en-tête importées ne contiennent pas de symboles dupliqués des différentes #include directives traitées lors de la traduction du fichier d’en-tête.

Par exemple, considérez deux fichiers d’en-tête qui incluent tous deux un fichier d’en-tête commun. Les deux fichiers d’en-tête sont inclus par le même fichier source :

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

Si le compilateur a généré des unités d’en-tête pour , puis , les unités a.h.ifcd’en-tête compilées , b.h.ifcet c.h.ifc contiennent chacun tous les types à partir de b.h.c.hb.h a.h Source.cppLa compilation, qui importe à la fois a.h et c.hqui nécessite que le compilateur déduplique les b.h types, ce qui impacte les performances de build.

Toutefois, s’il existe un header-units.json b.h répertoire et /translateInclude qu’il est spécifié, les événements suivants se produisent :

  1. Analyse et c.h listes b.h en tant qu’importation a.h d’unité d’en-tête dans les fichiers d’analyse des dépendances générés par le compilateur.
  2. Le système de génération lit les fichiers d’analyse des dépendances et détermine d’abord la génération b.h.ifc .
  3. Ensuite, le système de génération ajoute /headerUnit pour b.h.ifc les lignes de commande pour la a.h compilation et c.h. Il appelle le compilateur pour générer les unités a.h.ifc d’en-tête et c.h.ifc. Comme /translateInclude il est spécifié et /headerUnit for b.h.ifc également spécifié, a.h.ifc et c.h.ifc ne contient b.h pas de types, il n’y aura donc aucune duplication dans les unités d’en-tête produites.

schéma

Il existe un headerunits.json fichier pour les en-têtes STL (Standard Template Library). Le système de génération l’utilise pour déterminer s’il faut créer une unité d’en-tête pour un fichier d’en-tête STL et pour ses dépendances. Si le fichier d’en-tête STL ne figure pas dans la liste, l’instruction est traitée comme une instruction #include normale au lieu d’être importée comme une unité d’en-tête.

Vous pouvez voir le header-units.json fichier sous le répertoire d’installation de Visual Studio. Par exemple : %ProgramFiles%\Microsoft Visual Studio\2022\Enterprise\VC\Tools\MSVC\14.30.30705\include\header-units.json

Le header-units.json fichier commence par la version du schéma, suivi d’un tableau de noms de fichiers pour les en-têtes qui peuvent être intégrés dans des unités d’en-tête.

Le schéma prend également en charge les commentaires, comme indiqué ici :

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

Rechercher des règles

Le compilateur recherche ce fichier dans le même répertoire que le fichier d’en-tête en cours de traitement. Si votre bibliothèque est organisée en sous-répertoires, chaque sous-répertoire a besoin de son propre header-units.json fichier.

Voir aussi

Procédure pas à pas : Importer des bibliothèques STL en tant qu’unités d’en-tête
Procédure pas à pas : Générer et importer des unités d’en-tête dans des projets Visual C++