web-dev-qa-db-ja.com

#すべての.cppファイルを1つのコンパイル単位に含めますか?

最近、通常のデバッグ構成とリリース構成でVisual Studio C++プロジェクトを操作する必要がありましたが、これまでに見たことのない「すべてを解放」と「すべてをデバッグ」もしました。

プロジェクトの作成者は、他のすべての.cppファイルを#includeする単一のALL.cppを持っていることがわかりました。 *すべての構成は、この1つのALL.cppファイルをビルドするだけです。もちろん、これは通常の構成から除外されており、通常の構成ではALL.cppがビルドされません。

これが一般的な慣習だったのかと思いました。どんなメリットがありますか? (私の最初の反応は、悪臭がしたということでした。)

これに遭遇する可能性が高い落とし穴はどのようなものですか?私が考えることができる1つは、.cppsに匿名の名前空間がある場合、それらはそのcppに「プライベート」ではなく、他のcppsにも表示されるようになったということです。

すべてのプロジェクトがDLLを構築するので、匿名の名前空間にデータがあることは良い考えではありませんよね?しかし、機能は大丈夫でしょうか?

乾杯。

68
Steve Folly

これは、一部の(およびgoogle対応)から「Unityビルド」と呼ばれています。それはめちゃくちゃ高速にリンクし、同様にかなり速くコンパイルします。これは、中央サーバーからのリリースビルドのように、反復する必要がないビルドに最適ですが、必ずしもインクリメンタルビルドに適しているわけではありません。

そしてそれは維持すべきPITAです。

編集:詳細はこちらをご覧ください: http://buffered.io/posts/the-magic-of-unity-builds/

高速にするのは、コンパイラーがすべての.cppファイルに対して行うのではなく、一度にすべてを読み取り、コンパイルしてリンクするだけでよいということです。

ブルース・ドーソンは彼のブログでこれについてより良い記事を書いています: http://randomascii.wordpress.com/2014/03/22/make-vc-compiles-fast-through-parallel-compilation/ =

56
MSN

Unityは、3つの主な理由でビルド速度が向上しています。最初の理由は、すべての共有ヘッダーファイルを一度だけ解析する必要があることです。多くのC++プロジェクトには、ほとんどまたはすべてのCPPファイルに含まれる多くのヘッダーファイルがあり、これらの冗長な解析は、特に多くの短いソースファイルがある場合、コンパイルの主なコストです。プリコンパイル済みヘッダーファイルはこのコストに役立ちますが、通常、プリコンパイルされていないヘッダーファイルがたくさんあります。

ユニティビルドがビルド速度を向上させる次の主な理由は、コンパイラーの起動回数が少ないためです。コンパイラーの起動には、いくらかの初期費用がかかります。

最後に、冗長なヘッダー解析の削減は、インライン関数の冗長なコード生成の削減を意味するため、オブジェクトファイルの合計サイズが小さくなり、リンクが高速になります。

Unityビルドは、より良いコード生成を提供することもできます。

Unityのビルドは[〜#〜] not [〜#〜]ディスクI/Oの削減により高速です。私はxperfを使用して多くのビルドのプロファイルを作成しており、私が何を話しているのかを知っています。十分なメモリがある場合、OSディスクキャッシュは冗長I/Oを回避します-ヘッダーの後続の読み取りはOSディスクキャッシュから行われます。十分なメモリがない場合、ユニティビルドでは、コンパイラのメモリフットプリントが使用可能なメモリを超えてページアウトされるため、ビルド時間がさらに悪化する可能性があります。

ディスクI/Oは高価です。これが、すべてのオペレーティングシステムが冗長なディスクI/Oを回避するために積極的にデータをキャッシュする理由です。

50
Bruce Dawson

ALL.cppは、コンパイラーがプログラムのサイズを最適化する機能を改善するために、プロジェクト全体を単一のコンパイル単位内に配置しようとしているのでしょうか。

通常、一部の最適化は、重複するコードの削除やインライン展開など、別個のコンパイル単位内でのみ実行されます。

とは言っても、最近のコンパイラー(Microsoft、Intelですが、GCCを含むとは思わない)が複数のコンパイルユニットにわたってこの最適化を実行できることを覚えているようです。そのため、この「トリック」は不要だと思います。

とはいえ、実際に違いがあるかどうかを確認するのは興味深いことです。

6
Arafangion

私はブルースに同意します。私の経験から、大量のヘッダーインクルードと多数の.cppsを含む.dllプロジェクトの1つにUnityビルドを実装しようとしました。 VS2010の全体的なコンパイル時間を減らすために(既にインクリメンタルビルドオプションを使い果たしました)、コンパイル時間を減らすのではなく、メモリが足りなくなり、ビルドはコンパイルを完了することさえできませんでした。

ただし、追加するには; Visual Studioでマルチプロセッサコンパイルオプションを有効にすると、コンパイル時間を大幅に短縮できることがわかりました。そのようなオプションが他のプラットフォームコンパイラで利用できるかどうかはわかりません。

2
spforay

MacOSとWindowsのマルチプラットフォームプロジェクトがあります。多数の大きなテンプレートと多くのヘッダーを含めます。プリコンパイルされたヘッダーを使用してVisual Studio 2017 msvcでビルド時間を半分にしました。 MacOSの場合、ビルド時間を短縮するために数日間試行しましたが、プリコンパイル済みヘッダーはビルド時間を85%に短縮するだけでした。単一の.cpp-Fileを使用することが画期的なことでした。このALL.cppをスクリプトで作成するだけです。 ALL.cppには、プロジェクトのすべての.cpp-Filesのインクルードのリストが含まれています。 XCode 9.0を使用すると、ビルド時間が30%に短縮されます。唯一の欠点は、.cpp-Files内のすべてのプライベートなコンパイルされていないコンパイルユニットの名前空間に名前を付ける必要があったことです。そうしないと、ローカル名が衝突します。

0
Stephanie

Bruce Dawsonの excellent answer に加えて、次のリンクは、Unityビルドの長所と短所についてより多くの洞察をもたらします- https://github.com/onqtam/ucm#unity-builds =

0
onqtam