三大コンパイラ: MSVC・Clang・GCC¶
一言で言うと¶
C++には主要な処理系が3つあり、ゲーム開発では複数と付き合うのが普通です(Windows=MSVC、コンソール機=Clangベースが多い、Linuxサーバー=GCC/Clang)。標準準拠の共通部分と、処理系ごとの差分(フラグ・拡張・ABI)を分けて把握します。
3つのプロフィール¶
| MSVC | Clang | GCC | |
|---|---|---|---|
| 開発元 | Microsoft | LLVMプロジェクト | GNU |
| 主戦場 | Windows / Visual Studio | Mac(Apple Clang)、Android、多くのコンソール機、ツール基盤 | Linux、組み込み |
| コンパイラ実行体 | cl.exe | clang++ | g++ |
| C++20対応 | 良好(近年は最速級で対応) | 良好 | 良好 |
| エラーメッセージ | 改善中 | 最良と評判(初学者に優しい) | 良 |
| 特徴 | VSデバッガとの統合、Windows SDK連携 | ツール化(clang-format/clang-tidyの基盤)、モジュール構造 | 歴史と実績、最適化の強さ |
- Clangのツール性が現代の要: フォーマッタ(clang-format)、静的解析(clang-tidy)、言語サーバー(clangd = VSCodeの補完)はすべてClangの解析器の再利用。MSVCで開発していてもClangツール群は使う
- コンソール機のコンパイラはNDA下だが、Clangベースが多いのは公知(だからクロスプラットフォームコードはClangでも警告ゼロにしておくと移植が楽)
フラグの対応表(日常で使うもの)¶
| 目的 | GCC / Clang | MSVC |
|---|---|---|
| 規格指定 | -std=c++20 |
/std:c++20 |
| 最適化 | -O0 / -O2 / -O3 / -Os |
/Od / /O2 / /O1 |
| 警告 | -Wall -Wextra(全部ではない点に注意) |
/W4(/Wallは過剰) |
| 警告をエラーに | -Werror |
/WX |
| デバッグ情報 | -g |
/Zi(PDB生成) |
| define | -DNAME=1 |
/DNAME=1 |
| 例外オフ | -fno-exceptions |
/EHs-c-(既定で例外モデル指定/EHsc) |
| RTTIオフ | -fno-rtti |
/GR- |
| サニタイザ | -fsanitize=address 等 |
/fsanitize=address(近年対応) |
処理系差が現れる場所(ハマりどころ)¶
- ABI非互換: MSVCとGCC(MinGW)のバイナリは混ざらない(→ ABI)。ClangはWindowsでMSVC互換ABIモード(clang-cl)を持つ
- 警告の検出範囲が違う: GCCで警告ゼロでもMSVCで出る(逆も)。複数コンパイラでビルドするだけでバグが見つかるのはこのため(CIで両方回す価値)
- 拡張機能:
#pragma onceは3社対応(事実上標準)だが、__forceinline(MSVC)/__attribute__(GCC/Clang)、可変長配列(GCC拡張。標準C++にはない)などは移植の罠 - 標準ライブラリも別物: MSVC STL / libstdc++(GCC) / libc++(Clang)。実装依存の挙動(unordered_mapの成長戦略、SSOの閾値等)が異なる(→ 実装定義)
- 最適化の癖・浮動小数点の厳密さ(
/fp:fastvs-ffast-math)——クロスプラットフォームでリプレイ・ロックステップ同期が壊れる原因になりうる(決定性が要るなら固定小数点や厳密モードの検討)
C#/Unityとの対応¶
- C#のコンパイラは実質1つ(Roslyn)で、この「複数処理系」問題自体が存在しない。IL2CPPは吐いたC++を各プラットフォームのC++コンパイラ(まさにこの3つ+コンソール機)でビルドしている——Unityビルドの裏でこのページが動いている
- 「Standalone/il2cppでだけ挙動が違う」報告の一部は、C++コンパイラ差・最適化差に由来する
実務指針¶
- 1次コンパイラ(毎日使う)+CIで2次コンパイラを回す構成が理想(警告・移植性の早期発見)
- 警告フラグはプロジェクト開始時に最大級で固定(後から上げると数千件出て詰む → 警告レベル)
- コンパイラのバージョン更新はブランチで隔離してテスト(最適化差・新警告・ABI変化)
理解度チェック¶
- 3コンパイラの主戦場をそれぞれ言えますか。
- 「複数コンパイラでビルドするとバグが見つかる」のはなぜですか。
- MinGW(GCC)でビルドした.libをVSプロジェクトで使えない理由は?
演習¶
samples/ の任意のサンプルを -Wall -Wextra 付きでビルドし、警告が出るか確認してください。godbolt.orgで同じコードをGCC/Clang/MSVCでコンパイルし、生成コードとエラーメッセージの違いを見比べるのも推奨です。
前: ビルドとは何か | カテゴリ目次 | 次: ビルドツール: CMake