C++ header-units.json 参考
header-units.json
文件有两种用途:
- 规定在指定了
/translateInclude
时哪些头文件可以转换为头单元。 - 最大程度地减少重复的符号以提高生成吞吐量。
此文件必须与包含的头文件位于同一目录中。 仅当 /translateInclude
与 /scanDependencies
或 /sourceDependencies:directives
一起指定时才会使用此文件。
理由
某些头文件无法安全地转换为头单元。 符合以下条件的头文件无法转换为标题单元:依赖于未在命令行中定义的宏,或未在头包含的头文件中定义。
如果头定义的宏会影响是否包含其他头,则无法安全地对其进行转换。 例如,给定 a.h
、b.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
文件中列出的原因是在扫描阶段,可能尚未为 macros.h
编译头单元 (.ifc
)。 在这种情况下,在编译 MACRO
时不会定义 a.h
。 这意味着 a.h
的依赖项列表中将缺少 b.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
类型进行重复数据删除,这会影响生成的性能。
但是如果 b.h
目录中有 header-units.json
,并且指定了 /translateInclude
,则会发生以下情况:
- 扫描
a.h
和c.h
会将b.h
作为头单元导入列出在编译器生成的依赖扫描文件中。 - 生成系统读取依赖项扫描文件,并确定先生成
b.h.ifc
。 - 然后生成系统将在命令行中为
b.h.ifc
添加/headerUnit
以编译a.h
和c.h
。 它调用编译器来生成头单元a.h.ifc
和c.h.ifc
。 因为指定了/translateInclude
,也指定了/headerUnit for b.h.ifc
,所以a.h.ifc
和c.h.ifc
不会包含b.h
类型,所以生成的头单元不会有任何重复项。
架构
标准模板库 (STL) 头有一个 headerunits.json
文件。 生成系统使用此文件来确定是否为 STL 头文件及其依赖项创建头单元。 如果 STL 头文件不在列表中,则将其视为普通 #include
,而不是将其作为标头单元导入。
你可以在 Visual Studio 的安装目录下看到 header-units.json
文件。 例如:%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
文件。