インクリメンタル コンパイルとは何かを理解しています。コンパイラは、編集したコードのすべてではなく、そのコードのみをコンパイルします。しかし、コードを .h ファイルと .c/.cc ファイル、および C++ の makefile に分割すると、インクリメンタル コンパイルにどのように役立つのでしょうか?
1 に答える
ヘッダー ファイルは、コンパイルのインクリメンタル性に対して実際には非生産的です。ヘッダーを変更すると、そのヘッダーを含むすべてのソース ファイルが (別のヘッダーを介して間接的にも) 再コンパイルされます。しかし、ヘッダーを使用すると、言語で必要とされるように、複数の翻訳単位間ですべての定義を同一に保つことがはるかに簡単になるため、それらの使用は実質的に必要です。この逆生産性が、「必要なものだけを含める」ことが考慮すべき経験則である理由です。
インクリメンタル コンパイルに役立つのは、単純に翻訳単位ごとの定義が少ないことです。プログラム全体を 1 つのソース ファイルに記述した場合、プログラムの小さな部分にわずかな変更を加えただけでも、プログラム全体を再コンパイルする必要があります。
代わりに、すべての関数を個別のソース ファイルに記述した場合、それらの関数のいずれかを変更すると、その小さなソース ファイルのみを再コンパイルする必要が生じ、以前にコンパイルされた変更されていないオブジェクト ファイルと一緒にリンクされます。通常、単一の関数をコンパイルする方が、プログラム全体をコンパイルするよりも高速です。ただし、変更がたとえば関数の引数に対するものである場合、関数を呼び出すすべてのもの (つまり、その依存先) も再コンパイルする必要があります (したがって、これは、変更がヘッダー ファイルにあり、すべての依存先が変更されている場合です)。ヘッダーが含まれている必要があります)。
複数のソース ファイルを持つことのもう 1 つの利点は、それらを個別にコンパイルできるため、並行してコンパイルできることです。これは、今日のマルチコア プロセッサを考えると素晴らしいことです。コンピューター システムが無数に並んでいるデータ センターは言うまでもありません。ただし、欠点もあります。ゼロからの非インクリメンタル コンパイルは、多くのインライン関数 (特にすべてのテンプレートを含む) があり、それらを使用する個別のソース ファイルごとに再コンパイルする必要がある場合、一般にコストが高くなります。
make や ninja などのビルド システムは、他の機能の中でも特に、以前にコンパイルされたソース ファイルを追跡し、変更後に再コンパイルが必要なソース ファイルを決定する作業を行うツールです。通常、この決定は、コンパイルされたオブジェクト ファイルと比較したソース ファイル (および含まれるすべてのファイル) の変更時間に基づいて行われます。
これはすべて、必要な再コンパイルをフィルタリングするビルド ツールを必要とし、その中にインクリメンタル ロジックを持たない「ダム」非インクリメンタル コンパイラ (ほとんどのコンパイラ) の使用に当てはまります。真のインクリメンタル コンパイラの場合、ビルド システムや場合によっては翻訳単位の分割さえも必要ない場合があります。