> ## Documentation Index
> Fetch the complete documentation index at: https://devdocs.xbox.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Visual C++ コンパイラとリンカーのスイッチに関する推奨事項

> Visual C++ コンパイラとリンカーのスイッチに関する推奨事項

このトピックでは、XBOX 開発における Microsoft Game Development Kit (GDK) で推奨される、さまざまな Visual C++ コンパイラとリンカーのスイッチについて説明します。

> clang/LLVM for Windows では、"MSVC ライク" な clang-cl フロントエンドを通じて同じスイッチがサポートされています。clang ツールセット固有のいくつかのスイッチについては、以下で説明します。

## C++ 言語標準 (`/std`)

Visual C++ の既定は C++14 準拠モードです。C++17 準拠モードを有効にするには、`/std:c++17` を使用します。XBOX 向け Microsoft Game Development Kit (GDK) の API には C++11 以降が必要であり、タイトル開発では C++14 以降の使用が完全にサポートされています。

> [!NOTE]
>
> `/std:c++latest` は、Visual Studio 2017 および Visual Studio 2019 で C++20 ドラフト準拠を有効にします。`/std:c++latest` の動作は Visual C++ のサービス更新によって引き続き変更されるため、ある程度注意して使用する必要があります。

> VS 2019 (16.11) と VS 2022 は `/std:c++20` スイッチをサポートしています。[こちらのブログ投稿](https://devblogs.microsoft.com/cppblog/msvc-cpp20-and-the-std-cpp20-switch/)を参照してください。

> VS 2019 (16.8) 以降、Visual C++ コンパイラは `/std:c11` と `/std::c17` をサポートしています。ただし、GameRuntime やその他の多くの GDK ヘッダーには C++11 以降が必要です。

詳細については、以下を参照してください。

* [/std (言語標準バージョンの指定)](https://learn.microsoft.com/cpp/build/reference/std-specify-language-standard-version) (Microsoft Docs)
* [Standards version switches in the compiler](https://devblogs.microsoft.com/cppblog/standards-version-switches-in-the-compiler/) (C++ チーム ブログ)
* [C11 and C17 Standard Support Arriving in MSVC](https://devblogs.microsoft.com/cppblog/c11-and-c17-standard-support-arriving-in-msvc/) (C++ チーム ブログ)

## 一般的な最適化には `/O1 /Oi` を、"ホット" なモジュールには `/O2` を使用する

XBOX One および XBOX Series X/S のアウトオブオーダー実行 CPU では、通常、コードの絶対的な最速バージョンよりも、コード セグメントを命令キャッシュに収めることの方が重要であるため、*サイズの最適化*が推奨されます。*速度の最適化*の使用は、特定のモジュールまたは関数のみに限定してください。組み込み関数の生成は浮動小数点のパフォーマンスを向上させるため、ゲームではコードが増えても価値があります。また、`#pragma optimize("t", on)` / `#pragma optimize("", on )` で囲むことで、特定の関数または関数のセットに対して*速度の最適化*を有効にすることもできます。*速度の最適化* (`/O2` または `/Ox`) では、積極的なループ展開によってプログラム サイズが大幅に増加する可能性があることに注意してください。

> [!NOTE]
>
> 単一命令複数データ (SIMD) の自動ベクター化の最適化は、`/O2` または `/Ox` の場合にのみ有効になります。プロファイル ガイド付き最適化 (PGO) を使用すると、*速度の最適化*と*サイズの最適化*をどこに適用するかについて、より適切な選択を行うことができます。
>
> 歴史的な理由により、`/Ox` は `O2` とほぼ同じですが、`/GF` (重複する文字列の削除) と `/Gy` (関数レベルのリンクを有効にする) の両方が欠けていることに注意することが重要です。そのため、一般的には `/Ox` よりも `/O2` を使用することをお勧めします。`/Ox` を使用する場合は、リンカーの最適化を有効にするために重要な `/Gy` を少なくとも明示的に有効にしてください。

## `/fp:fast` コンパイラ スイッチ

Visual Studio 2005 で導入された `/fp` フラグは、コンパイラで使用されるさまざまな浮動小数点モデル (fast、precise、strict、except) を制御します。fast 浮動小数点モデルでは、コア "C" ルールの一部ではない多くの最適化が使用されます。precise 浮動小数点モデルではこれらの追加の最適化が無効になり、これが既定です。ゲームには `/fp:fast` を使用することをお勧めします。

詳細については、以下を参照してください。

* [/fp (浮動小数点の動作の指定)](https://learn.microsoft.com/cpp/build/reference/fp-specify-floating-point-behavior) (Microsoft Docs)
* [Do You Prefer Fast or Precise? ](https://devblogs.microsoft.com/cppblog/do-you-prefer-fast-or-precise/) (C++ チーム ブログ)

VS 2022 で新しく追加された、浮動小数点に関連する以下の追加フラグも参照してください。

* [/fpcvt](https://devblogs.microsoft.com/cppblog/microsoft-visual-studio-2022-and-floating-point-to-integer-conversions/)
* [/fpcontract](https://devblogs.microsoft.com/cppblog/the-fpcontract-flag-and-changes-to-fp-modes-in-vs2022/)

## `/arch` コンパイラ スイッチ

x64 ネイティブ プラットフォームの暗黙の既定値は `/arch:SSE2` です。XBOX One 本体 (AMD Jaguar CPU) では、`/arch:AVX` を使用する必要があります。XBOX Series X/S (AMD Hercules CPU) では、`/arch:AVX2` の使用をお勧めします。

`/arch:AVX` または `/arch:AVX2` を使用する主な利点は、コンパイラが SSE 命令の VEX プレフィックス バージョンを生成することです。これは、ソース オペランドの 1 つが結果で上書きされる標準の 2 オペランド エンコードではなく、非破壊的な 3 オペランド エンコードを使用します。これは、SSE 命令を使用する x64 ネイティブ コードのスカラー浮動小数点と、SSE 組み込み関数の明示的な使用の両方に影響します。これにより、レジスタのスケジューリングの負荷が軽減され、一部の `movaps` 命令を排除できます。

詳細については、以下を参照してください。

* [/arch (x64)](https://learn.microsoft.com/cpp/build/reference/arch-x64) (Microsoft Docs)
* [AVX2 floating point improvements in Visual Studio 2019 version 16.5](https://devblogs.microsoft.com/cppblog/avx2-floating-point-improvements-in-visual-studio-2019-version-16-5/) (C++ チーム ブログ)

Visual Studio 2019 (16.3) 以降を使用する XBOX Series X|S では、`vzeroupper` 命令の使用に関して AMD Hercules CPU が推奨する動作に合わせて最適化するために、`/d2vzeroupper` も使用する必要があります。プログラム全体の最適化 (`/LTCG`) では、必要な同等のリンカー スイッチは `/d2:-vzeroupper` です。これは VS 2022 コンパイラの既定の動作です。

Visual Studio 2022 を使用する XBOX One では、`vzeroupper` 命令の使用に関して AMD Jaguar CPU が推奨する動作に合わせて最適化するために、`/d2vzeroupper-` も使用する必要があります。プログラム全体の最適化 (`/LTCG`) では、必要な同等のリンカー スイッチは `/d2:-vzeroupper-` です。これは VS 2019 コンパイラの既定の動作です。

> clang/LLVM では、XBOX One (AMD Jaguar CPU) には `-march=btver2` を、XBOX Series X/S (AMD Hercules CPU) には `-march=znver2` を使用します。

> PC 開発では、SSE と SSE2 はアーキテクチャ定義の一部であるため、すべての x64 ネイティブ CPU でサポートされていることを前提にできます。また、SSE3 は Windows 10 または Windows 11 でサポートされているすべての最新の Intel CPU でサポートされているため、安全に必須とすることもできます。PC で AVX や AVX2 など、SSE2 を超えるものを使用する場合は、必ず実行時に CPU のサポートを確認してください。

## `/favor` コンパイラ スイッチ

`/favor` スイッチは、AMD64 プロセッサと Intel 64 プロセッサのどちらを優先するかについて、x64 コンパイラの最適化の選択を制御します。XBOX 開発では、`/favor:AMD64` を使用します。

## 例外処理モデル (`/EHsc`)

x64 ネイティブ コードでは、例外処理は関数のエピローグやプロローグにコード上の直接的な影響を与えません。Windows x86 では、モジュールに追加のコードが挿入されるスタック ベースの方式が使用されていましたが、x64 ネイティブ コード生成では、例外処理中にスタックを適切にアンワインドできるようにテーブル ベースの方式が使用されます。x64 ネイティブで使用されるテーブル ベースの方式には、スタック バッファー オーバーラン攻撃の影響を受けないため、より安全であるという利点もあります。この設計には、いくつかの意味があります。

* 例外処理は、生成されるコードの命令数に影響しません。Windows x86 で使用されるようなスタック ベースの方式では 5 から 10 パーセントのコード ペナルティが発生する可能性がありますが、x64 ネイティブの例外処理では、実行可能ファイルに関連付けられたテーブル ベースのデータのみが生成され、命令は増えません。x64 ネイティブで例外処理を明示的に無効にしても (これはお勧めしません)、C++ 処理用の少量の補助データが削減されるだけで、スタック アンワインド データの生成は無効になりません。

* try/catch ブロックの使用コストは低くなります。スタック ベースの方式の try/catch ブロックでは、追跡用の追加コードがいくらか追加されます。x64 では、アンワインド テーブルにいくつかのエントリが追加されるだけです。

* 例外処理 (つまり、実際の例外のスロー) には、追加のテーブル参照が必要です。トレードオフとして、スタック ベースの方式では例外をより迅速にスローできますが、すべてのコード パスでペナルティが発生します。テーブル ベースの方式は "スロー" に時間がかかりますが、他のコード パスには影響しません。例外は通常のフロー制御に使用すべきではなく、実際には例外的な状況でのみトリガーされるべきものであるため、この処理の追加のパフォーマンス コストは、アプリケーション全体のパフォーマンスと比較すると無視できる程度です。

XBOX 向け Microsoft Game Development Kit (GDK) の API は、エラー結果を返すために例外処理ではなくエラー コードまたは `HRESULT` を使用するため、タイトルのコード ベース内で C++ 例外処理をどの程度採用するかは完全に開発者の判断に委ねられます。例外はフロー制御に使用すべきではないため、一般的に最適な用途は "フェイルファスト" のシナリオであり、これによりデバッグとコーディングを簡素化できます。標準 C++ ライブラリの多くは、適切なエラー処理のために例外処理が有効になっていることを前提としています。

例外処理を明示的に無効にすることはお勧めしません。クラッシュ後の分析に悪影響を及ぼし、コード生成も改善されないためです。`/EHa` はオプティマイザーを阻害する可能性があるため、使用はお勧めしません。

> [!NOTE]
>
> 演算子 `new` は、割り当てが失敗すると常に C++ 例外をスローします。スローしないバージョンの `new` を使用する場合は、`new (std::nothrow)` を使用する必要があります。詳細については、[std::nothrow](https://en.cppreference.com/w/cpp/memory/new/nothrow) (cppreference.com) を参照してください。

C++ には、例外処理を明示的に使用する場合と使用しない場合の両方でうまく機能する "例外セーフ" なコードを記述するための多数のメカニズムが用意されています。たとえば、`std::unique_ptr`、`std::shared_ptr`、`std::lock_guard` などです。[Microsoft::WRL::ComPtr](https://learn.microsoft.com/cpp/cppcx/wrl/comptr-class) のような COM スマート ポインターを使用して COM の参照カウントを自動的に処理することは "例外セーフ" であり、エラーが発生しにくくなります。一般的には、リソース取得時の初期化 ([RAII](https://en.wikipedia.org/wiki/Resource_acquisition_is_initialization)) のコーディング パターンを使用することをお勧めします。

> [!NOTE]
>
> 既定では、VS 2019 でビルドされた x64 ネイティブ コードは、改良された例外ハンドラーの実装 (` __CxxFrameHandler4`、`__GSHandlerCheck_EH4`) を使用します。そのため、VS 2019 でビルドされた静的ライブラリは、VS 2017 の C/C++ ランタイムと互換性がありません。VS 2017 でビルドされた静的ライブラリは VS 2019 と互換性があります。

詳細については、以下を参照してください。

* [/EH (例外処理モデル)](https://learn.microsoft.com/cpp/build/reference/eh-exception-handling-model) (Microsoft Docs)
* [x64 の例外処理](https://learn.microsoft.com/cpp/build/exception-handling-x64) (Microsoft Docs)
* [Making C++ Exception Handling Smaller On x64](https://devblogs.microsoft.com/cppblog/making-cpp-exception-handling-smaller-x64/) (C++ チーム ブログ)

## ランタイム ライブラリ (`/MD`、`/MDd`)

推奨される選択肢は、Visual C/C++ ランタイムの*マルチスレッド DLL* バージョンを使用することです。これにより、コードの肥大化が最小限に抑えられ、DLL 間の相互作用に関する潜在的な問題が回避され、サービスが簡素化されます。これは、すべての Microsoft プラットフォームで推奨されるオプションです。

XBOX 向け Microsoft Game Development Kit (GDK) では、これは `ucrt.lib` または `ucrtd.lib` にリンクすることを意味します。

> [!NOTE]
>
> 技術的には、`libucrt.lib` または `libucrtd.lib` を使用して、`/MT`、`/MTd` による静的 CRT リンクを使用することもできます。GDK には静的 CRT と互換性のある拡張ライブラリが含まれていないため、このシナリオのサポートは限定的です。

## 呼び出し規約 (`/Gd`、`/Gv`)

x64 のネイティブ コード生成では、最初の 4 つのパラメーターをレジスタで渡すことができる、シンプルで標準的な `__fastcall` 呼び出し規約が使用されます。

* 最初のパラメーターが整数またはポインター相当の場合は、RCX で渡されます。`float` または `double` の場合は、XMM0L で渡されます。それ以外の場合は、スタックで渡されます。
* 2 番目のパラメーターが整数またはポインター相当の場合は、RDX で渡されます。`float` または `double` の場合は、XMM1L で渡されます。それ以外の場合は、スタックで渡されます。
* 3 番目のパラメーターが整数またはポインター相当の場合は、R8 で渡されます。`float` または `double` の場合は、XMM2L で渡されます。それ以外の場合は、スタックで渡されます。
* 4 番目のパラメーターが整数またはポインター相当の場合は、R9 で渡されます。`float` または `double` の場合は、XMM3L で渡されます。それ以外の場合は、スタックで渡されます。
* その他のパラメーターはすべてスタックで渡されます。
* 64 ビットに収まる戻り値は RAX で返されます。`float`、`double`、`__m128`、`__m128i`、`__m128d` の値を返すには XMM0 が使用されます。それ以外の場合は、呼び出し元が 0 番目の引数としてメモリへのポインターを RCX で渡し、RAX は同じポインターで返される必要があります。

これらの点から、関数シグネチャが短いほどパフォーマンスが向上し、オブジェクトへのポインター (または参照) を渡す方が値渡しよりも高速であることがわかります。呼び出し規約では、8 バイトを超えるオブジェクトは自動的に参照渡しされます。

`__fastcall` 方式では、SIMD 値がレジスタで渡されることはありません。

> [!NOTE]
>
> x64 ネイティブ コードでは、`__cdecl`、`__stdcall`、`__thiscall` はすべて `__fastcall` のエイリアスです。

詳細については、[x64 呼び出し規約](https://learn.microsoft.com/cpp/build/x64-calling-convention) (Microsoft Docs) を参照してください。

### ベクター呼び出し

Visual Studio は、x64 ネイティブ コード生成向けに、`__vectorcall` と呼ばれるオプションの呼び出し規約をサポートしています。

* 最初のパラメーターが整数またはポインター相当の場合は、RCX で渡されます。`float`、`double`、`__m128`、`__m128i`、または `__m128d` の場合、パラメーターは XMM0 で渡されます。`__m256`、`__m256i`、または `__m256d` の場合は、YMM0 で渡されます。それ以外の場合、最初のパラメーターはスタックで渡されます。
* 2 番目のパラメーターが整数またはポインター相当の場合は、RDX で渡されます。`float`、`double`、`__m128`、`__m128i`、`__m128d`、`__m256`、`__m256i`、または `__m256d` の場合、パラメーターは XMM1/YMM1 で渡されます。それ以外の場合、2 番目のパラメーターはスタックで渡されます。
* 3 番目のパラメーターが整数またはポインター相当の場合は、R8 で渡されます。`float`、`double`、`__m128`、`__m128i`、`__m128d`、`__m256`、`__m256i`、または `__m256d` の場合、パラメーターは XMM2/YMM2 で渡されます。それ以外の場合、3 番目のパラメーターはスタックで渡されます。
* 4 番目のパラメーターが整数またはポインター相当の場合は、R9 で渡されます。`float`、`double`、`__m128`、`__m128i`、`__m128d`、`__m256`、`__m256i`、または `__m256d` の場合、パラメーターは XMM3/YMM3 で渡されます。それ以外の場合、4 番目のパラメーターはスタックで渡されます。
* 5 番目のパラメーターが `float`、`double`、`__m128`、`__m128i`、`__m128d`、`__m256`、`__m256i`、または `__m256d` の場合、パラメーターは XMM4/YMM4 で渡されます。それ以外の場合、5 番目のパラメーターはスタックで渡されます。
* 6 番目のパラメーターが `float`、`double`、`__m128`、`__m128i`、`__m128d`、`__m256`、`__m256i`、または `__m256d` の場合、パラメーターは XMM5/YMM5 で渡されます。それ以外の場合、6 番目のパラメーターはスタックで渡されます。
* その他のパラメーターはすべてスタックで渡されます。
* 64 ビットに収まる戻り値は RAX で返されます。`float`、`double`、`__m128`、`__m128i`、`__m128d` の値を返すには XMM0 が使用されます。`__m256`、`__m256i`、または `__m256d` の値を返すには YMM0 が使用されます。それ以外の場合は、呼び出し元が 0 番目の引数としてメモリへのポインターを RCX で渡し、RAX は同じポインターで返される必要があります。

`__vectorcall` 規約は、同種ベクター集約 (HVA) 型も処理できます。HVA 型は、同じ種類のベクター型または浮動小数点型の 1 つ以上のメンバー (最大 4 つ) で構成されます (つまり、`struct * { __m128 v[4]; }` は HVA です)。

値渡しのパラメーターとしては、他のパラメーターを割り当てた後に XMM0/YMM0 から XMM5/YMM5 に十分な空き領域がある場合、HVA はレジスタで渡されます。戻り値としては、HVA は XMM0/YMM0 から XMM3/YMM3 を介して返されます。

> [!NOTE]
>
> `__vectorcall` は、`vararg` 関数や C++ コンストラクターをサポートしていません。

詳細については、以下を参照してください。

* [\_\_vectorcall](https://learn.microsoft.com/cpp/cpp/vectorcall) (Microsoft Docs)
* [Introducing 'Vector Calling Convention'](https://devblogs.microsoft.com/cppblog/introducing-vector-calling-convention/) (C++ チーム ブログ)

## プログラム全体の最適化 (`/GL`、`/Gw`、`/LTCG`)

従来のコンパイラ最適化手法では関数やモジュールを最適化できますが、*プログラム全体の最適化* (*リンク時のコード生成 (LTCG)* とも呼ばれます) では、モジュール間で最適化が実行されます。これには、副作用をより正確に把握したうえでのレジスタ割り当てとスケジューリングの改善、プロシージャ間の定数/範囲の伝達、部分的なインライン展開、可能な場合のオブジェクトに対する関数呼び出しの仮想化解除などが含まれます。

> [!NOTE]
>
> LTCG は、開発のイテレーションでコードのパフォーマンス上の利点を得るために、インクリメンタル モードで使用することもできます。詳細については、[Speeding up the Incremental Developer Build Scenario](https://devblogs.microsoft.com/cppblog/speeding-up-the-incremental-developer-build-scenario/) (C++ チーム ブログ) を参照してください。

> ビルド済みの静的 C++ ライブラリを出荷するミドルウェア ベンダーの場合、WPO を有効にすると、ライブラリが特定のリリースのコンパイラ ツールセットに結び付けられます。このシナリオでは、WPO なしでライブラリを出荷する必要があります。このアドバイスは、DLL やソースからビルドされたコードには適用されません。

詳細については、[/GL (プログラム全体の最適化)](https://learn.microsoft.com/cpp/build/reference/gl-whole-program-optimization) (Microsoft Docs) を参照してください。

> Visual Studio 2022 (17.5) では、`/Gw` に関連する新しい準拠スイッチ `/Zc:checkGwOdr` が追加されました。[こちらのブログ投稿](https://devblogs.microsoft.com/cppblog/standards-conformance-improvements-to-gw-in-visual-studio-version-17-5-preview-2/)を参照してください。

### プロファイル ガイド付き最適化

プロファイル ガイド付き最適化 (PGO) は、LTCG プロセスをさらに一歩進めたもので、アプリケーションの以前の実行で収集されたパフォーマンス トレースによってプログラム全体の最適化が制御されます。これにより、既存の最適化の品質が向上するとともに、ワーキング セットと分岐予測を改善するための関数レイアウト、ブロック レイアウト、コード分離の最適化も行われます。

詳細については、[プロファイル ガイド付き最適化](https://learn.microsoft.com/cpp/build/profile-guided-optimizations) (Microsoft Docs) を参照してください。

## `/OPT:REF,ICF` リンカー スイッチ

これらは、最終的な実行可能ファイルにリンクされる際に、さまざまなオブジェクト モジュール内の冗長なコンテンツを排除します。通常、これらはデバッグ ビルドでは無効にしますが、リリース ビルドでは指定する必要があります。

> [!NOTE]
>
> 最良の結果を得るには、必ず `/Gy` (関数レベルのリンクを有効にする) オプションを指定してコンパイルしてください。

## `/GS` コンパイラ スイッチ

すべてのコードについて、リリース構成でバッファー チェックを使用することをお勧めします。特定のバッファーがセキュリティ上の脅威から安全であるにもかかわらず、チェックによってパフォーマンスに影響があるように見える場合は、`/GS` をグローバルに無効にするのではなく、関数に `__declspec(safebuffers)` を使用してください。よりリスクの高いコードには、`#pragma strict_gs_check(on)` を使用します。

詳細については、[/GS (バッファー セキュリティ チェック)](https://learn.microsoft.com/cpp/build/reference/gs-buffer-security-check) (Microsoft Docs) を参照してください。

## `/homeparams` コンパイラ スイッチ

最適化されたビルドでこのスイッチを使用すると、アプリケーションのリリース ビルドをデバッグする能力が大幅に向上します。製品ビルドで使用すると、クラッシュ ダンプの分析とデバッグのプロセスを簡素化できます。これにより、スタックに追加のパラメーターを格納するための少量のオーバーヘッドが追加されます。ほとんどの場合、パフォーマンスに目立った影響はありません。

詳細については、[/homeparams (スタックへのレジスタ パラメーターのコピー)](https://learn.microsoft.com/cpp/build/reference/homeparams-copy-register-parameters-to-stack) (Microsoft Docs) を参照してください。

## `/Zc:inline` コンパイラ スイッチ

これは、インライン関数の宣言に関するより厳格な C++11 ルールを適用します。このルールでは、すべてのインライン関数の本体が、その宣言および使用箇所と同じコンパイル単位に存在する必要があります。このフラグを使用すると、ビルド時間が短縮され、.obj ファイルのサイズを大幅に削減できます。インライン関数が C++11 に準拠していない場合は、リンク時に LNK2019 エラーが発生します。このスイッチは MSBuild でビルドする場合は既定でオンになっていますが、コマンド ライン、CMake などを使用してビルドする場合は明示的に追加する必要があります。

詳細については、[/Zc:inline (参照されていない COMDAT の削除)](https://learn.microsoft.com/cpp/build/reference/zc-inline-remove-unreferenced-comdat) (Microsoft Docs) を参照してください。

## `/Zc:throwingNew` コンパイラ スイッチ

C++ 標準と標準 C++ ライブラリのテンプレートでは、演算子 `new` は割り当てが失敗したときに `nullptr` を返すのではなく例外をスローする必要があります。`new` で `std::nothrow` を使用すると、`nullptr` を返す動作を強制できます。Visual C++ コンパイラは長い間、`new` の各呼び出しの後に `null` のチェックを生成してきましたが、これは例外処理が存在する場合は不要です。このスイッチを使用すると、余分なチェックが排除されます。

詳細については、以下を参照してください。

* [/Zc:throwingNew (演算子 new がスローすると仮定する)](https://learn.microsoft.com/cpp/build/reference/zc-throwingnew-assume-operator-new-throws) (Microsoft Docs)
* [New in VS 2015: /Zc:throwingNew](https://devblogs.microsoft.com/cppblog/new-in-vs-2015-zcthrowingnew/) (C++ チーム ブログ)

## `/Zc:__cplusplus` コンパイラ スイッチ

歴史的な理由により、Visual C++ の `__cplusplus` マクロは非常に長い間 "199711" を返してきました。Visual Studio 2017 (15.7 更新プログラム) 以降、この新しいスイッチを使用すると、Visual C++ コンパイラは正しい標準値を返します。将来のバージョンのコンパイラでは既定でこの動作になるため、残っている準拠の問題を解決するために、早めにこのスイッチをオンにしておく価値があります。

詳細については、以下を参照してください。

* [/Zc:\_\_cplusplus (更新された \_\_cplusplus マクロを有効にする)](https://learn.microsoft.com/cpp/build/reference/zc-cplusplus) (Microsoft Docs)
* [MSVC now correctly reports \_\_cplusplus](https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplus/) (C++ チーム ブログ)

## `/volatile:iso` コンパイラ スイッチ

キーワード `volatile` には、その動作に関連する Microsoft 固有の拡張動作が多数あり、それらは Visual C++ の世代間でさえ移植性がありません。このスイッチをオンにして、コード内で `volatile` を誤用していないことを確認することを検討してください。

詳細については、[/volatile (volatile キーワードの解釈)](https://learn.microsoft.com/cpp/build/reference/volatile-volatile-keyword-interpretation) (Microsoft Docs) を参照してください。

## `/permissive-` コンパイラ スイッチ

Visual Studio 2017 では、古い `/Za` スイッチを置き換える新しい標準準拠スイッチが導入されました。このスイッチを使用すると、他のコンパイラに移植する際に問題が発生する可能性がある Microsoft 固有の拡張動作を使用したときに、コンパイラがエラーと警告を出力します。`/permissive-` を使用すると、コンパイル時間も改善される可能性があります。

詳細については、以下を参照してください。

* [/permissive- (標準準拠)](https://learn.microsoft.com/cpp/build/reference/permissive-standards-conformance) (Microsoft Docs)
* [Give Visual C++ a Switch to Standard Conformance](https://devblogs.microsoft.com/cppblog/permissive-switch/) (C++ チーム ブログ)

> [!NOTE]
>
> Visual Studio 2017 (15.3 更新プログラム) 以降、`/permissive-` を使用すると 2 フェーズの名前参照も有効になります。一部の C++ テンプレート コードは適切な標準の適用ではコンパイルされないため、`/permissive-` を完全に無効にする代わりに、`/Zc:twoPhase-` を使用してその部分だけを選択的に無効にできます。
>
> 詳細については、以下を参照してください。
>
> * [/Zc:twoPhase- (2 フェーズの名前参照を無効にする)](https://learn.microsoft.com/cpp/build/reference/zc-twophase) (Microsoft Docs)
> * [Two-phase name lookup support comes to MSVC](https://devblogs.microsoft.com/cppblog/two-phase-name-lookup-support-comes-to-msvc/) (C++ チーム ブログ)

準拠の適用に関連するその他のスイッチには、[/Zc:lambda](https://learn.microsoft.com/cpp/build/reference/zc-lambda) と [/Zc:templateScope](https://learn.microsoft.com/cpp/build/reference/zc-templatescope) があります。

## `/Zc:preprocessor` コンパイラ スイッチ

Visual Studio 2019 (16.6) には、C99 準拠のプリプロセッサを有効にする新しいスイッチが含まれています。このスイッチは既定ではオフですが、コードの移植性が懸念される場合は、有効にすることを検討してください。[Announcing full support for a C/C++ conformant preprocessor in MSVC](https://devblogs.microsoft.com/cppblog/announcing-full-support-for-a-c-c-conformant-preprocessor-in-msvc/) を参照してください。

## `/ZH:SHA_256` コンパイラ スイッチ

デバッグ シンボルでは、従来 MD5 ハッシュが使用されてきました。サプライ チェーンのセキュリティを向上させるために、代わりに SHA-256 を使用することをお勧めします。Visual Studio 2022 の既定値は `/ZH:SHA_256` であることに注意してください。

> このスイッチは、v16 以降の clang/LLVM でサポートされています。

## `/NXCOMPAT` および `/SAFESEH` リンカー スイッチ

これら 2 つのスイッチは、x64 ネイティブ ターゲットを使用する場合は暗黙的に指定されます。XBOX タイトルにはデータ実行防止 (NX) 保護が必要なため、`/NXCOMPAT:NO` は使用できません。

## `/DYNAMICBASE` リンカー スイッチ

このスイッチは、アドレス空間レイアウトのランダム化 (ASLR) の使用を有効にし、既定でオンになっています。これは XBOX タイトルに必須であるため、`/DYNAMICBASE:NO` は使用できないことに注意してください。

## `/Debug:FASTLINK` リンカー スイッチ

*Visual Studio 2019 (16.8) 以降では、リンカーのパフォーマンスが大幅に向上したため、`/Debug:FASTLINK` の使用は推奨されなくなりました。*

~~ローカル ビルドでは、このリンカー スイッチを有効にすると、ビルドのイテレーション時間を大幅に短縮できます。~~

> [!NOTE]
>
> `/Debug:FASTLINK` を使用すると、プロジェクトのプライマリ `pdb` には、ビルド全体に散在する `pdb` ファイルへのリンクのみが含まれることに注意してください。`/Debug:FASTLINK` ビルドのシンボルを共有または保存する場合は、`mspdbcmf.exe` コマンド ライン ツールを使用して完全な `pdb` ファイルを生成できます。
>
> 詳細については、以下を参照してください。
>
> * [/DEBUG (デバッグ情報の生成)](https://learn.microsoft.com/cpp/build/reference/debug-generate-debug-info) (Microsoft Docs)
> * [Faster C++ build cycle in VS 2017 with /Debug:fastlink](https://devblogs.microsoft.com/cppblog/faster-c-build-cycle-in-vs-15-with-debugfastlink/) (C++ チーム ブログ)

## ライブラリ

*Gaming.Xbox.XboxOne.x64* および *Gaming.Xbox.Scarlett.x64* プラットフォームでは、`xgameplatform.lib` にリンクすることが重要です。これは、本体でサポートされているすべての Win32 API を含む "アンブレラ" ライブラリです。`kernel32.lib`、`onecore.lib`、`onecoreuap.lib`、または `WindowsApps.lib` とはリンク**しないでください**。アンブレラ ライブラリを混在させることは推奨されず、プロセスの起動エラーにつながる可能性があります。

"アンブレラ" ライブラリの詳細については、[Microsoft Docs](https://learn.microsoft.com/windows/win32/apiindex/windows-umbrella-libraries) を参照してください。

### `/NODEFAULTLIB:library` リンカー スイッチ

`#pragma comment(lib,)` を介してサポートされていないライブラリがリンク時に使用されないようにするために、一般的なライブラリ名の特定のリストを指定して `/NODEFAULTLIB` リンカー スイッチを使用することをお勧めします。

```
/NODEFAULTLIB:advapi32.lib /NODEFAULTLIB:comctl32.lib /NODEFAULTLIB:comsupp.lib
/NODEFAULTLIB:dbghelp.lib /NODEFAULTLIB:gdi32.lib /NODEFAULTLIB:gdiplus.lib
/NODEFAULTLIB:guardcfw.lib /NODEFAULTLIB:kernel32.lib /NODEFAULTLIB:mmc.lib
/NODEFAULTLIB:msimg32.lib /NODEFAULTLIB:msvcole.lib /NODEFAULTLIB:msvcoled.lib
/NODEFAULTLIB:mswsock.lib /NODEFAULTLIB:ntstrsafe.lib /NODEFAULTLIB:ole2.lib
/NODEFAULTLIB:ole2autd.lib /NODEFAULTLIB:ole2auto.lib /NODEFAULTLIB:ole2d.lib
/NODEFAULTLIB:ole2ui.lib /NODEFAULTLIB:ole2uid.lib /NODEFAULTLIB:ole32.lib
/NODEFAULTLIB:oleacc.lib /NODEFAULTLIB:oleaut32.lib /NODEFAULTLIB:oledlg.lib
/NODEFAULTLIB:oledlgd.lib /NODEFAULTLIB:oldnames.lib /NODEFAULTLIB:runtimeobject.lib
/NODEFAULTLIB:shell32.lib /NODEFAULTLIB:shlwapi.lib /NODEFAULTLIB:strsafe.lib
/NODEFAULTLIB:urlmon.lib /NODEFAULTLIB:user32.lib /NODEFAULTLIB:userenv.lib
/NODEFAULTLIB:wlmole.lib /NODEFAULTLIB:wlmoled.lib
/NODEFAULTLIB:onecore.lib
```

> [!NOTE]
>
> ライブラリがリンク入力として明示的に指定されている場合は、`/NODEFAULTLIB` ライブラリとして指定されていても使用されます。このスイッチは、暗黙的な参照のみを無視します。

### Visual C++ ランタイム ライブラリ

**Visual Studio 開発者コマンド プロンプト**では、これらのパスを見つけるために必要な環境変数が定義されています。

*Gaming.Xbox.\*.x64* で Visual C++ ランタイムのインポート ライブラリを見つけるための適切な `/LIBPATH` は `%VCToolsInstallDir%lib\onecore\x64` です。

#### ダイナミック リンク ライブラリ (DLL)

*Gaming.Xbox.\*.x64* の Game OS には、Visual C++ ランタイムの DLL ライブラリは含まれていません。ゲームを起動するために、これらはタイトル レイアウトに含まれます。

* リリースの場合は、`%VCToolsRedistDir%onecore\x64\Microsoft.VC14?.CRT` の内容が必要です。同じレイアウトにデバッグとリリースの両方のバイナリが混在している場合は、すべてのレイアウトにこれらを含める必要があります。

* デバッグの場合は、`%VCToolsRedistDir%onecore\debug_nonredist\x64\Microsoft.VC14?.DebugCRT` の内容が必要です。

* デバッグの場合は、Windows SDK の `%WindowsSdkVerBinPath%x64\ucrt` にあるデバッグ バージョンの `ucrtbased.dll` *も*必要です。リリース バージョンの `ucrtbase.dll` は Game OS に含まれています。

> [!NOTE]
>
> OpenMP を使用する場合は、`Microsoft.VC14?.OpenMP` または `Microsoft.VC14?.DebugOpenMP` (あるいはその両方) の内容も必要です

## 関連項目

[CMakeExample](https://github.com/microsoft/Xbox-GDK-Samples/tree/main/Samples/Tools/) サンプル


## Related topics

- [Microsoft Game Development Kit (GDK) で Clang を使用する](/ja-jp/tools/tools-pc/visualstudio/gr-vs-clang.md)
- [Visual Studio (目次)](/ja-jp/tools/tools-pc/visualstudio/gr-visualstudio-toc.md)
- [コンソール向け Microsoft Game Development Kit (GDK) で Clang を使用する](/ja-jp/tools/tools-console/visualstudio/vs-clang.md)
- [Visual Studio でのプロファイルガイド付き最適化](/ja-jp/tools/tools-console/pgo/pgo_full.md)
- [RETAIL サンドボックスでのテストに関する推奨事項](/ja-jp/publishing/game-publishing/publishing-processes/managed-creators/publishing-processes-recommendations-for-testing-in-retail.md)
