header-units.json ファイルには、次の 2 つの目的があります。
/translateIncludeを指定した場合にヘッダー 単位に変換できるヘッダー ファイルを指定します。- 重複するシンボルを最小限に抑えて、ビルドのスループットを向上させます。
このファイルは、含まれているヘッダー ファイルと同じディレクトリに存在する必要があります。 このファイルは、/scanDependenciesまたは/sourceDependencies:directivesと共に/translateIncludeが指定されている場合にのみ使用されます。
理由
一部のヘッダー ファイルは、ヘッダー ユニットに安全に変換できません。 コマンド ラインで定義されていないマクロに依存するヘッダー ファイル、またはヘッダーに含まれるヘッダー ファイルで定義されていないヘッダー ファイルは、ヘッダー ユニットに変換できません。
ヘッダーが他のヘッダーを含めるかどうかに影響するマクロを定義している場合、安全に変換することはできません。 たとえば、 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"
]
}
このheader-units.json ファイルmacros.h一覧表示できない理由は、スキャン フェーズ中にヘッダー ユニット (.ifc) がmacros.h用にまだコンパイルされていない可能性があるためです。 その場合、a.hのコンパイル時にMACROは定義されません。 つまり、 b.h は a.hの依存関係の一覧に表示されません。 依存関係の一覧には含まれていないため、ビルド システムは、header-units.json ファイルに一覧表示されているにもかかわらず、b.hのヘッダー ユニットをビルドしません。
この問題を回避するために、別のヘッダー ファイル内のマクロに依存関係がある場合、そのマクロを定義するヘッダー ファイルは、ヘッダー ユニットにコンパイルできるファイルの一覧から除外されます。 このように、マクロを定義するヘッダー ファイルは通常の #include として扱われ、 MACRO が表示され、依存関係の 1 つとして b.h が含まれて一覧表示されます。
重複するシンボルの防止
また、 header-units.json ファイルは、重複するシンボルを使用せずにヘッダー ユニットを自動的に作成できるため、重要です。 これを行うには、 header-units.jsonに記載されているファイルの "アトミック" ヘッダー ユニットを作成します。 インポートされたヘッダー ユニットには、ヘッダー ファイルの変換中に処理されたさまざまな #include ディレクティブの重複したシンボルは含まれません。
たとえば、両方に共通のヘッダー ファイルを含む 2 つのヘッダー ファイルがあるとします。 両方のヘッダー ファイルは、同じソース ファイルに含まれています。
// 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のすべての型が含まれます。 a.hとc.hの両方をインポートするSource.cppをコンパイルするには、コンパイラがb.h型を重複除去する必要があり、ビルドのパフォーマンスに影響します。
ただし、b.h ディレクトリにheader-units.jsonがあり、/translateIncludeが指定されている場合は、次のようになります。
a.hとc.hのスキャンでは、コンパイラによって生成された依存関係スキャン ファイルにヘッダー ユニットのインポートとしてb.hが一覧表示されます。- ビルド システムは依存関係スキャン ファイルを読み取り、最初にビルド
b.h.ifc決定します。 - その後、ビルド システムは、
a.hとc.hをコンパイルするためのコマンド ラインにb.h.ifcの/headerUnitを追加します。 コンパイラを呼び出して、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 ファイルとして扱われます。
header-units.json ファイルは、Visual Studio のインストール ディレクトリの下に表示されます。 例: %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 ファイルが必要です。
関連項目
チュートリアル: STL ライブラリをヘッダ ーユニットとしてインポートする
チュートリアル: Visual C++ プロジェクトでヘッダー ユニットをビルドしてインポートする