我知道我可以make
随时中断进程,而不必再次重新编译整个源代码树。据我所知,make
只有在尚未编译的情况下才编译目标,或者在上次编译后修改了源代码。
但如果我中断make
,肯定会有一个或多个(取决于并发级别)半就绪的二进制文件。下次我跑步时它们会做什么make
?或者当我按Ctrl+C以避免部分编译的二进制文件时它是否完成当前目标?
答案1
简单来说,您可以将其视为make
具有(可能很大)数量的步骤,其中每个步骤都采用多个文件作为输入并创建一个文件作为输出。
步骤可能是“编译file.c
到”file.o
或“使用ld
链接main.o
到”。如果您用中断,则当前执行的步骤将终止,这将(或应该)删除它正在处理的输出文件。通常不会留下任何“半就绪的二进制文件”。file.o
program
make
CtrlC
当您重新启动时make
,它将查看所有输入和输出文件的时间戳并重新运行以下步骤:
- 输入文件的时间戳比输出文件更新
- 输出文件不存在
这通常意味着,如果一个步骤需要很长时间才能运行(这在现代计算机上很少见,但大型程序的步骤在设计ld
时很容易花费很多分钟),那么停止并重新启动将从头开始该步骤。make
make
平均值的实际情况Makefile
比上述描述要复杂得多,但基本原理是相同的。
答案2
Ctrl+C导致 aSIGINT
被发送到正在运行的进程。该信号可以被进程捕获。在 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
描述了正确执行的依赖关系和命令,所以所有需要(重新)制作的都是。