Skip to content

Commit f8a4e1c

Browse files
authored
Merge pull request MicrosoftDocs#4081 from MicrosoftDocs/main
2/4 AM Publish
2 parents 2a31c72 + a1b8adf commit f8a4e1c

9 files changed

+346
-230
lines changed
11.7 KB
Loading
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
---
2+
description: "Reference for header-units.json file"
3+
title: "C++ header unit.json reference"
4+
ms.date: 02/03/2022
5+
author: "tylermsft"
6+
ms.author: "twhitney"
7+
f1_keywords: ["header-units.json"]
8+
helpviewer_keywords: ["header-units.json", "header unit"]
9+
---
10+
11+
# C++ header-units.json reference
12+
13+
The `header-units.json` file serves two purposes:
14+
- Specify which header files can be translated into header units when [`/translateInclude`](translateinclude.md) is specified.
15+
- Minimize duplicated symbols to increase build throughput.
16+
17+
This file must be in the same directory as the included header file. This file is only used when [`/translateInclude`](translateinclude.md) is specified along with either `/scanDependencies` or [`/sourceDependencies:directives`](sourcedependencies-directives.md).
18+
19+
## Rationale
20+
21+
Some header files can't be safely translated to header units. Header files that depend on macros that aren't defined on the command line, or that aren't defined in the header files included by the header, can't be translated to header units.
22+
23+
If a header defines macros that affect whether other headers are included, it can't be safely translated. For example, given `a.h`, `b.h` and `macros.h`, which are all in the same directory:
24+
25+
```cpp
26+
// a.h
27+
28+
#include "macros.h" // #defines MACRO=1
29+
#ifdef MACRO
30+
#include "b.h"
31+
#endif
32+
```
33+
34+
The `header-units.json` in this directory can contain `a.h` and `b.h`, but not `macros.h`. The `header-units.json` for this example would be similar to this:
35+
36+
```json
37+
{
38+
"Version": "1.0",
39+
"BuildAsHeaderUnits": [
40+
// macros.h should not be listed
41+
"a.h",
42+
"b.h"
43+
]
44+
}
45+
```
46+
47+
The reason `macros.h` can't be listed in this `header-units.json` file is that during the scan phase, the header unit (`.ifc`) might not be compiled yet for `macros.h`. In that case, `MACRO` won't be defined when `a.h` is compiled. That means `b.h` will be missing from the list of dependencies for `a.h`. Because it isn't in the list of dependencies, the build system won't build a header unit for `b.h` despite it being listed in the `header-units.json` file.
48+
49+
To avoid this problem when there's a dependency on a macro in another header file, the header file that defines the macro is excluded from the list of files that can be compiled into a header unit. This way the header file that defines the macro is treated as an `#include` and `MACRO` will be visible so that `b.h` is included and listed as one of the dependencies.
50+
51+
### Preventing duplicated symbols
52+
53+
The `header-units.json` file is also important because it allows for automatic header unit creation without duplicated symbols. It does this by creating "atomic" header units for the files listed in `header-units.json`. The imported header units don't contain duplicated symbols from the various `#include` directives that were processed while translating the header file.
54+
55+
For example, consider two header files that both include a common header file. Both header files are included by the same source file:
56+
57+
```cpp
58+
// a.h
59+
#include "b.h"
60+
61+
// c.h
62+
#include "b.h"
63+
64+
// Source.cpp
65+
import "a.h";
66+
import "c.h";
67+
```
68+
69+
If the compiler built header units for `a.h`, `b.h` and `c.h`, then the compiled header units `a.h.ifc`, `b.h.ifc`, and `c.h.ifc` would each contain all of the types from `b.h`. Compiling `Source.cpp`, which imports both `a.h` and `c.h`, would require the compiler to deduplicate the `b.h` types, which would impact build performance.
70+
71+
But if there's a `header-units.json` in the `b.h` directory, and `/translateInclude` is specified, the following happens:
72+
73+
1. The scan of `a.h` and `c.h` lists `b.h` as a header unit import in the dependency scan files generated by the compiler.
74+
1. The build system reads the dependency scan files and determines to build `b.h.ifc` first.
75+
1. Then the build system adds `/headerUnit` for `b.h.ifc` to the command lines for compiling `a.h` and `c.h`. It calls the compiler to build the header units `a.h.ifc` and `c.h.ifc`. Because `/translateInclude` is specified, and `/headerUnit for b.h.ifc` is also specified, `a.h.ifc` and `c.h.ifc` won't contain `b.h` types, so there won't be any duplication in the produced header units.
76+
77+
## Schema
78+
79+
There's a `headerunits.json` file for the Standard Template Library (STL) headers. The build system uses it to determine whether to create a header unit for an STL header file, and for its dependencies. If the STL header file isn't on the list, it's treated as a normal `#include` instead of importing it as a header unit.
80+
81+
You can see the `header-units.json` file under the installation directory for Visual Studio. For example: `%ProgramFiles%\Microsoft Visual Studio\2022\Enterprise\VC\Tools\MSVC\14.30.30705\include\header-units.json`
82+
83+
The `header-units.json` file starts with the schema version, followed by an array of filenames for headers that can be built into header units.
84+
85+
The schema also supports comments, as shown here:
86+
87+
```json
88+
{
89+
"Version": "1.0",
90+
"BuildAsHeaderUnits": [
91+
// "__msvc_all_public_headers.hpp", // for testing, not production
92+
"__msvc_system_error_abi.hpp",
93+
"__msvc_tzdb.hpp",
94+
"__msvc_xlocinfo_types.hpp",
95+
"algorithm",
96+
"any",
97+
"array",
98+
"atomic",
99+
"barrier",
100+
"bit",
101+
"bitset",
102+
// "cassert", // design is permanently incompatible with header units
103+
...
104+
}
105+
```
106+
107+
## Search rules
108+
109+
The compiler looks for this file in the same directory as the header file being processed. If your library is organized into subdirectories, each subdirectory needs its own `header-units.json` file.
110+
111+
## See also
112+
113+
[Walkthrough: Import STL libraries as header units](..\walkthrough-import-stl-header-units.md#approach1)\
114+
[Walkthrough: Build and import header units in your Visual C++ projects](..\walkthrough-header-units.md)

docs/build/reference/headerunit.md

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
---
22
title: "/headerUnit (Use header unit IFC)"
33
description: "Use the /headerUnit compiler option to associate a header file with the header unit to import in its place."
4-
ms.date: 04/13/2021
4+
ms.date: 02/01/2022
55
f1_keywords: ["/headerUnit"]
66
helpviewer_keywords: ["/headerUnit", "Use header unit IFC"]
77
author: "tylermsft"
88
ms.author: "twhitney"
99
---
1010
# `/headerUnit` (Use header unit IFC)
1111

12-
Used to import a header unit. Tells the compiler where to find the *`.ifc`* file (the binary representation of the header unit) for the specified header.
12+
Imports a header unit. Tells the compiler where to find the *`.ifc`* file (the binary representation of the header unit) for the specified header.
1313

1414
## Syntax
1515

@@ -27,45 +27,46 @@ The name of a file that contains compiled header unit information. To import mor
2727

2828
## Remarks
2929

30-
The **`/headerUnit`** compiler option requires the [`/std:c++20`](std-specify-language-standard-version.md) or later compiler option (such as **`/std:c++latest`**).
30+
The **`/headerUnit`** compiler option requires [`/std:c++20`](std-specify-language-standard-version.md) or later.
3131

32-
The **`/headerUnit`** compiler option is available starting in Visual Studio 2019 version 16.10.
32+
The **`/headerUnit`** compiler option is available in Visual Studio 2019 version 16.10 or later.
3333

34-
When the compiler comes across `import "file";` or `import <file>;`, this compiler option helps the compiler find the compiled header unit (*`.ifc`*) for the specified header file. The path to this file can be expressed in three ways:
34+
When the compiler comes across `import "file";` or `import <file>;` this compiler option helps the compiler find the compiled header unit (*`.ifc`*) for the specified header file. The path to this file can be expressed in these ways:
3535

36-
**`/headerUnit`** looks up the compiled header unit in the current directory, or at the location specified in *`ifc-filename`*.
36+
- **`/headerUnit`** looks up the compiled header unit in the current directory, or at the location specified by *`ifc-filename`*.
3737

38-
**`/headerUnit:quote`** looks up the compiled header unit file using the same rules as `#include "file"`.
38+
- **`/headerUnit:quote`** looks up the compiled header unit file using the same rules as `#include "file"`.
3939

40-
**`/headerUnit:angle`** looks up the compiled header unit file using the same rules as `#include <file>`.
40+
- **`/headerUnit:angle`** looks up the compiled header unit file using the same rules as `#include <file>`.
4141

42-
The compiler can't map a single *`header-name`* to multiple *`.ifc`* files. While mapping multiple *`header-name`* arguments to a single *`.ifc`* is possible, we don't recommend it. The contents of the *`.ifc`* get imported as if it was only the header specified by *`header-name`*.
42+
The compiler can't map a single *`header-name`* to multiple *`.ifc`* files. Mapping multiple *`header-name`* arguments to a single *`.ifc`* is possible, but it isn't recommended. The contents of the *`.ifc`* are imported as if it was only the header specified by *`header-name`*.
4343

44-
The compiler implicitly enables the new preprocessor when this option is used. That is, [`/Zc:preprocessor`](zc-preprocessor.md) is added to the command line by the compiler if any form of `/headerUnit` is specified on the command line. To opt out of the implicit `/Zc:preprocessor`, specify: `/Zc:preprocessor-`
44+
The compiler implicitly enables the new preprocessor when this option is used. If any form of `/headerUnit` is specified on the command line, then [`/Zc:preprocessor`](zc-preprocessor.md) is added to the command line by the compiler. To opt out of the implicit `/Zc:preprocessor`, specify: `/Zc:preprocessor-`
4545

4646
If you disable the new preprocessor, but a file you compile imports a header unit, the compiler will report an error.
4747

4848
### Examples
4949

50-
Given a project that references two header files and their header units, listed in this table:
50+
Given a project that references two header files and their header units as listed in this table:
5151

5252
| Header file | IFC file |
5353
|--|--|
5454
| *`C:\utils\util.h`* | *`C:\util.h.ifc`* |
5555
| *`C:\app\app.h`* | *`C:\app\app.h.ifc`* |
5656

57-
The compiler options to reference the header units for these particular header files would look similar to this:
57+
The compiler options to reference the header units for these particular header files would look like this:
5858

5959
```CMD
6060
cl ... /std:c++latest /headerUnit C:\utils\util.h=C:\util.h.ifc /headerUnit:quote app.h=app.h.ifc
6161
```
6262

6363
### To set this compiler option in the Visual Studio development environment
6464

65-
You normally shouldn't set this in the Visual Studio development environment. It is set by the build system.
65+
You normally shouldn't set this in the Visual Studio development environment. It's set by the build system.
6666

6767
## See also
6868

6969
[`/exportHeader` (Create header units)](module-exportheader.md)\
7070
[`/headerName` (Create a header unit from the specified header)](headername.md)\
71-
[`/reference` (Use named module IFC)](module-reference.md)
71+
[`/reference` (Use named module IFC)](module-reference.md)\
72+
[`/translateInclude` (Translate include directives into import directives)](translateinclude.md)

docs/build/reference/sourcedependencies-directives.md

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,25 @@
11
---
22
title: "/sourceDependencies:directives (List module and header unit dependencies)"
33
description: "Reference guide to the /sourceDependencies:directives compiler option in Microsoft C++."
4-
ms.date: 04/13/2020
4+
ms.date: 02/02/2022
55
author: "tylermsft"
66
ms.author: "twhitney"
77
f1_keywords: ["/sourceDependencies:directives"]
88
helpviewer_keywords: ["/sourceDependencies:directives compiler option", "/sourceDependencies:directives"]
99
---
1010
# `/sourceDependencies:directives` (List module and header unit dependencies)
1111

12-
This command-line option generates a JSON file that lists module and header-unit dependencies.
12+
This command-line option scans source files and their `#include` statements to generate a JSON file that lists module export and imports. This information can be used by a build system to determine the build order of modules and header units.
1313

14-
It identifies which modules and header units need to be compiled before the project that uses them is compiled. For instance, it will list `import <library>;` or `import "library";` as a header unit dependency, and `import name;` as a module dependency.
14+
This option differs from [`/sourceDependencies`](sourcedependencies.md) in the following ways:
1515

16-
This command-line option is similar to [`/sourceDependencies`](sourcedependencies.md), but differs in the following ways:
17-
18-
- The compiler doesn't produce compiled output. Instead, the files are scanned for module directives. No compiled code, modules, or header units are produced.
16+
- The compiler doesn't produce compiled output. No compiled code, modules, or header units are produced. Instead, the files are scanned for module directives.
17+
- The JSON format is different from what `/sourceDependencies` produces. The `/sourceDependencies` option is intended to be used with other build tools, such as CMake.
1918
- The output JSON file doesn't list imported modules and imported header units (*`.ifc`* files) because this option does a scan of the project files, not a compilation. So there are no built modules or header units to list.
2019
- Only directly imported modules or header units are listed. It doesn't list the dependencies of the imported modules or header units themselves.
21-
- Header file dependencies are not listed. That is, `#include <file>` or `#include "file"` dependencies are not listed.
20+
- Header file dependencies aren't listed. That is, `#include <file>` or `#include "file"` dependencies aren't listed.
2221
- `/sourceDependencies:directives` is meant to be used before *`.ifc`* files are built.
22+
- `/sourceDependencies` causes the compiler to report all of the files, such as `#includes`, `.pch` files, `.ifc` files, and so on, that were used for a particular translation unit, whereas `/sourceDependencies:directives [file1]` scans the specified source file and reports all `import` and `export` statements. `/sourceDependencies` can be used with `/sourceDependencies:directives`.
2323

2424
## Syntax
2525

@@ -40,14 +40,16 @@ If the argument is a directory, the compiler generates source dependency files i
4040

4141
## Remarks
4242

43-
**`/sourceDependencies:directives`** is available starting in Visual Studio 2019 version 16.10. It's not enabled by default.
43+
**`/sourceDependencies:directives`** is available starting in Visual Studio 2019 version 16.10.
4444

45-
When you specify the **`/MP`** compiler option, we recommend you use **`/sourceDependencies`** with a directory argument. If you provide a single filename argument, two instances of the compiler may attempt to open the output file simultaneously and cause an error. For more information on **`/MP`**, see [`/MP` (Build with multiple processes)](mp-build-with-multiple-processes.md).
45+
When you specify the [`/MP` (Build with multiple processes)](mp-build-with-multiple-processes.md) compiler option, specify the output file location for **`/sourceDependencies:directives`** with a directory argument. The compiler will produce `[directory]\[source file name with extension].module.json` for each source file.
4646

4747
When a non-fatal compiler error occurs, the dependency information still gets written to the output file.
4848

4949
All file paths appear as absolute paths in the output.
5050

51+
This switch can be used with [`/translateInclude`](translateinclude.md).
52+
5153
### Examples
5254

5355
Given the following sample code:
@@ -66,9 +68,11 @@ import "t.h";
6668
int main() {}
6769
```
6870

69-
> `cl /std:c++latest /sourceDependencies:directives output.json main.cpp`
71+
This following command line:
72+
73+
`cl /std:c++latest /translateInclude /sourceDependencies:directives output.json main.cpp`
7074

71-
This command line produces a JSON file *`output.json`* with content like:
75+
produces a JSON file *`output.json`* similar to:
7276

7377
```JSON
7478
{
@@ -88,17 +92,19 @@ This command line produces a JSON file *`output.json`* with content like:
8892
}
8993
```
9094

91-
We've used `...` to abbreviate the reported paths. The report will contain the absolute paths. The paths reported depend on where the compiler finds the dependencies. If the results are unexpected, you may want to check your project's include path settings.
95+
For brevity, the previous example uses `...` to abbreviate the reported paths. The report contains the absolute paths. The paths reported depend on where the compiler finds the dependencies. If the results are unexpected, you might want to check your project's include path settings.
9296

9397
`ProvidedModule` lists exported module or module partition names.
9498

95-
No *`.ifc`* files are listed in the output because they weren't built. Unlike `/sourceDependencies`, the compiler doesn't produce compiled output when `/sourceDependencies:directives` is specified, so no compiled modules or header units are produced to import.
99+
No *`.ifc`* files are listed in the output because they weren't built. Unlike `/sourceDependencies`, the compiler doesn't produce compiled output when `/sourceDependencies:directives` is specified, so no compiled modules or header units are produced.
96100

97101
## To set this compiler option in Visual Studio
98102

99-
You normally shouldn't set this yourself in the Visual Studio development environment. It is set by the build system.
103+
You normally shouldn't set this yourself in the Visual Studio development environment. It's set by the build system.
100104

101105
## See also
102106

107+
[`/translateInclude`](translateinclude.md)\
108+
[C++ header-units.json reference](header-unit-json-reference.md)\
103109
[MSVC compiler options](compiler-options.md)\
104110
[MSVC compiler command-line syntax](compiler-command-line-syntax.md)

0 commit comments

Comments
 (0)