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.ifc
d’en-tête compilées , b.h.ifc
et c.h.ifc
contiennent chacun tous les types à partir de b.h
.c.h
b.h
a.h
Source.cpp
La compilation, qui importe à la fois a.h
et c.h
qui 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 :
- Analyse et
c.h
listesb.h
en tant qu’importationa.h
d’unité d’en-tête dans les fichiers d’analyse des dépendances générés par le compilateur. - 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
. - Ensuite, le système de génération ajoute
/headerUnit
pourb.h.ifc
les lignes de commande pour laa.h
compilation etc.h
. Il appelle le compilateur pour générer les unitésa.h.ifc
d’en-tête etc.h.ifc
. Comme/translateInclude
il est spécifié et/headerUnit for b.h.ifc
également spécifié,a.h.ifc
etc.h.ifc
ne contientb.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++