gccを使用してファイルを作成するプロジェクトがあります。プロジェクトには、1つの大きなサブプロジェクト(SDK)と、そのSDKといくつかの共有フレームワークを使用する比較的小さなサブプロジェクトが多数含まれています。
プリコンパイル済みヘッダーを使用しますが、これは再コンパイルを高速化するためにのみ役立ちます。
ビルド時の最適化に役立つ既知の手法やツールはありますか?または、このトピックまたは関連トピックに関する記事/リソースを知っていますか?
gccを使用してファイルを作成するプロジェクトがあります。プロジェクトには、1つの大きなサブプロジェクト(SDK)と、そのSDKといくつかの共有フレームワークを使用する比較的小さなサブプロジェクトが多数含まれています。
プリコンパイル済みヘッダーを使用しますが、これは再コンパイルを高速化するためにのみ役立ちます。
ビルド時の最適化に役立つ既知の手法やツールはありますか?または、このトピックまたは関連トピックに関する記事/リソースを知っていますか?
この問題には2つの側面から取り組むことができます。コードをリファクタリングしてコンパイラーが見ている複雑さを軽減するか、コンパイラーの実行を高速化します。
コードに触れることなく、コードにコンパイル能力を追加できます。ccacheを使用して、既にコンパイルしたファイルを再コンパイルしないようにし、distccを使用して、ビルド時間をより多くのマシンに分散します。make -jを使用します。ここで、Nは、ローカルでコンパイルする場合はコアの数+1、分散ビルドの場合はより大きな数です。そのフラグは、複数のコンパイラを並行して実行します。
コードのリファクタリング。インクルード(単純)よりも前方宣言を優先します。依存関係を回避するために、できる限り分離します(PIMPLイディオムを使用します)。
テンプレートのインスタンス化にはコストがかかり、テンプレートを使用するすべてのコンパイルユニットで再コンパイルされます。テンプレートを前方宣言するようにリファクタリングしてから、1つのコンパイルユニットでのみインスタンス化できる場合。
私が考えることができる最高のmake
ものは-j
オプションです。これはmake
、できるだけ多くのジョブを並行して実行するように指示します。
make -j
同時ジョブの数をnに制限する場合は、次を使用できます。
make -j
n
make
必要のないジョブを実行しないように、依存関係が正しいことを確認してください。
考慮すべきもう 1 つのことはgcc
、-O
スイッチで行う最適化です。さまざまなレベルの最適化を指定できます。最適化が高いほど、コンパイルとリンクの時間が長くなります。-O3
私が作業しているプロジェクトは、 とのリンクに 2 分、 とのリンクに 30 分かかります-O1
。必要以上に最適化していないことを確認する必要があります。開発ビルドでは最適化なしでビルドし、展開ビルドでは最適化してビルドできます。
デバッグ情報 ( gcc -g
) を使用してコンパイルすると、実行可能ファイルのサイズが大きくなり、ビルド時間に影響する可能性があります。不要な場合は、削除して影響があるかどうかを確認してください。
リンクの種類 (静的か動的か) によって違いが生じるはずです。私が理解している限り、静的リンクには時間がかかります (ただし、ここでは間違っている可能性があります)。これがビルドに影響するかどうかを確認する必要があります。
プロジェクトの説明から、ディレクトリごとに 1 つの Makefile があり、再帰的な make を多用していると思います。その場合、「Recursive Make Considered Harful」のテクニックが非常に役立ちます。
複数のコンピュータを利用できる場合、gcc はdistccによって適切に配布されます。
さらに、 ccacheを使用することもできます。
これはすべて、makefile をほとんど変更することなく機能します。
SCons などの別のビルド システムに切り替えることを検討することもできます (これは明らかにすべての人にとって機能するわけではありません)。SCons は make よりもはるかにスマートです。ヘッダーの依存関係が自動的にスキャンされるため、再構築の依存関係のセットが常に最小になります。SConstruct ファイルに行Decider('MD5-timestamp')
を追加することにより、SCons は最初にファイルのタイム スタンプを調べ、以前に作成されたタイム スタンプよりも新しい場合は、ファイルの MD5 を使用して、実際に何かが変更されたことを確認します。これは、ソース ファイルだけでなく、オブジェクト ファイルでも機能します。これは、たとえばコメントを変更した場合、再リンクする必要がないことを意味します。
また、ヘッダー ファイルの自動スキャンにより、scons --clean と入力する必要がなくなりました。それは常に正しいことをします。
また、ソース コード ファイルを可能な限り小さく、自己完結型に保つことをお勧めします。つまり、1 つの巨大なオブジェクト ファイルよりも多くの小さなオブジェクト ファイルを優先します。
これは、不要な再コンパイルを避けるのにも役立ちます。さらに、ソース コード ディレクトリまたはモジュールごとにオブジェクト ファイルを含む 1 つのスタティック ライブラリを作成できるため、コンパイラは以前にコンパイルされたコードを可能な限り再利用できます。
前の応答のいずれにもまだ言及されていない他の何かは、シンボル リンケージを可能な限り「プライベート」にすることです。つまり、コードが外部から見える必要がない場合は、コードの静的リンケージ (関数、変数) を優先します。
さらに、 ELF ターゲット用の C++ コードをコンパイルするのにはるかに効率的なGNU ゴールド リンカーの使用を検討することもできます。
基本的に、ビルド プロセスを注意深くプロファイリングし、最も時間がかかる場所を確認することをお勧めします。これにより、ビルド プロセスまたはプロジェクトのソース コード構造を最適化する方法に関するヒントが得られます。
開発者のマシンが LAN に接続されている場合は、distccなどの分散コンパイラ ソリューションを実装してみてください。
ビルド中のすべての時間が依存関係の分析や単一のシリアル タスクの実行に費やされている場合、これは役に立たない可能性があります。多くのソース ファイルをオブジェクト ファイルにコンパイルする生のクランチについては、Nathan が (1 台のマシンで) 提案したように、並列ビルドが明らかに役立ちます。複数のマシンにまたがって並列化すると、それがさらに進む可能性があります。
http://ccache.samba.org/は大幅に高速化します。
私は中規模のプロジェクトに取り組んでいますが、それがコンパイル時間を短縮するために行う唯一のことです。
複数のマシンにアクセスできる場合は、distcc分散コンパイラを使用してビルド時間を短縮できます。これは、distcc に関連する IBM developerWorks の記事とその使用方法です: http://www.ibm.com/developerworks/linux/library/l-distcc.html
ビルド時間を短縮するもう 1 つの方法は、プリコンパイル済みヘッダーを使用することです。これが gccの出発点です。
また、マシンに複数の CPU/コアがある場合は、make でビルドするときに -j を使用することを忘れないでください (コア/CPU の数の 2 倍で十分です)。