4

特に大規模なプロジェクトでコードの特定の部分を再コンパイルする必要がない場合、コンパイラはどのように判断しますか?


たとえば、C++ に 2 つの C++ ファイルと 2 つのヘッダー ファイルがあるとします。ヘッダー ファイルは相互に依存しています。(これらは、お互いのファイルで指定されたクラスを使用します。)

コンパイラは、2 つの C++ ファイルのいずれかを生成するためにクラス情報を取得するために、常に両方のヘッダー ファイル (およびメソッド実装用の C++ ファイル) を解析する必要がありますか?


コマンド プロンプトでコンパイラを実行すると、オブジェクト ファイルを出力した直後にコンパイラが閉じてしまうので、抽象構文木や中間コードをキャッシュすることはできないといつも思っていました。ほとんどの C++ コンパイラは、特定のファイルがオブジェクト ファイルに出力する必要がないためスキップされることを認識していますか?

4

3 に答える 3

3

私が知っているすべてのコンパイラは、指示されたすべてのソース ファイルをコンパイルします。いつも。そして、コンパイルするすべてのソース ファイルに対して新しいバージョンのオブジェクト ファイルを生成します。

必要なものだけをコンパイルすることは、通常、ビルド システム (make またはその他) に任せられます。どのオブジェクトを再生成する必要があるかは、各ソース ファイルに直接的または間接的に何が含まれているかによって異なります。ほとんどのコンパイラには、この情報をオンザフライまたは個別の呼び出しとして何らかの形式で出力するオプションがあり、ビルドシステム (少なくとも使用可能なもの) はこの情報を使用して依存関係を判断します。

于 2013-08-05T13:12:38.957 に答える
2

上で述べたように、コンパイラは、コンパイルを要求されたすべてのファイルをコンパイルします。何をコンパイルする必要があるかを決定するのは、make などのツール次第です。

makeルールを設定します。各ルールにはターゲットと依存関係のリストがあり、その後にそれらの依存関係が満たされない場合に実行するコマンドが続きます。例えば

target.o : target.c
    gcc -c -o target.o target.c

ほとんどのファイル システムでは、各ファイルにタイムスタンプがあります。target.o のタイムスタンプが target.c よりも新しい場合 (ルールの依存関係)、make は以下の gcc コマンドを実行しません。これは、最初にソース ファイルを編集してから、ソース ファイルをオブジェクト ファイルにコンパイルするためです。

ただし、依存ソース ファイルがターゲット ファイルよりも新しい場合は、コンパイル後にソース ファイルが編集されたことがわかり、別のコンパイルが必要になります。makeしたがって、ルールのビルド コマンドを実行します。

ルールが他のルールに依存している場合はさらに複雑になりますが、同じ原則が適用されます。

于 2013-08-05T13:40:37.280 に答える
0

彼らがどのようにそれを実装しているか (実装していないか) はわかりません (実装しない人が多いため... 理由は聞かないでください) が、非常に簡単であると確信しています。中間 (obj) ファイルに、ソース ファイルとコンパイルしているすべての依存ファイルの名前とハッシュを、使用中のコンパイル オプション、コンパイラ (またはその内部バージョン) のハッシュ、およびコンパイル結果 (OK/エラー)。次にユーザーがファイルを再コンパイルしようとすると、コンパイラは中間ファイルが既に存在するかどうか、すべてのハッシュが同じかどうか、コンパイル オプションが同じかどうか、コンパイラが同じかどうかをチェックします...すべてが同じで、事前に保存されたエラー メッセージが表示され、何もせずに終了します。

中間ファイルは少し大きくなります (おそらくそれぞれ数キロバイト)。

于 2013-08-05T13:13:59.927 に答える