make はどのようにコンパイルを続行しますか?

make はどのようにコンパイルを続行しますか?

ソースツリー全体を再度コンパイルしなくても、いつでもプロセスを中断できることはわかっていますmake。 は、makeターゲットがまだコンパイルされていない場合、または最後のコンパイル後にソースコードが変更された場合にのみ、ターゲットをコンパイルします。
しかし、 を中断するとmake、1 つ以上の (同時実行レベルに応じて) 半分準備が整ったバイナリが確実に存在します。 次に を実行したときに、それらはどうなりますか? または、部分的にコンパイルされたバイナリを回避するために、 +makeを押すと現在のターゲットを終了しますか?CtrlC

答え1

make簡単に言えば、 (おそらくは多数の)ステップがあり、各ステップで複数のファイルを入力として受け取り、1 つのファイルを出力として作成すると考えることができます。

ステップは、「file.cにコンパイルfile.o」または「にldリンクして にmain.o使用」である可能性があります。を使用して中断すると、現在実行中のステップが終了し、作業中の出力ファイルが削除されます (または削除されるはずです)。通常、「半分準備ができたバイナリ」は残されません。file.oprogrammakeCtrlC

を再起動するとmake、すべての入力ファイルと出力ファイルのタイムスタンプが確認され、次の手順が再実行されます。

  • 入力ファイルのタイムスタンプが出力ファイルよりも新しい
  • 出力ファイルが存在しません

これは通常、ステップの実行に長い時間がかかる場合 (最近のコンピュータではまれですが、大規模なプログラムのステップは設計ld時に数分かかることがありました)、停止して再起動すると、そのステップが最初からやり直されることを意味します。makemake

平均値の現実はMakefile上記の説明よりもかなり複雑ですが、基本は同じです。

答え2

Ctrl+ は実行中のプロセスにCシグナルSIGINTを送信します。このシグナルはプロセスによってキャッチされます。make ソース コードでは、このシグナルのトラップを次の場所で見つけることができますcommands.c

  /* If we got a signal that means the user
     wanted to kill make, remove pending targets.  */

  if (sig == SIGTERM || sig == SIGINT

  ... remove childrens ...

  /* Delete any non-precious intermediate files that were made.  */

  remove_intermediates (1);

remove_intermediates()は のクリーンアップ関数ですmake。その定義はここを参照してください。

/* Remove all nonprecious intermediate files.
   If SIG is nonzero, this was caused by a fatal signal,
   meaning that a different message will be printed, and
   the message will go to stderr rather than stdout.  */

そして、関数の後半では、それらは事実上削除されます。

status = unlink (f->name);

結論: 一般的に、 でコンパイルを中断することを恐れないでくださいmake。キャッチできないシグナル ( ) でない場合は、SIGKILL, SIGSEGV, SIGSTOP中間ファイルのクリーンアップが行われます。

答え3

何かが停止するとmake(Ctrl + C、シャットダウン、または失敗したコマンドなど)、すでに完了した作業はそのまま残ります。言い換えると、make通常どおりに動作します。つまり、まだ実行する必要がある作業を判断し (ファイルが変更されたり、make処理されなかったりしても問題ないため)、ジョブを続行します。

上記の説明では、関連するMakefileが依存関係とコマンドを正しく実行するように記述していることが明確に想定されているため、(再)作成する必要があるのはすべて です。

関連情報