I know that I can interrupt a
make process anytime without having to recompile the entire source tree again. As I know,
make only compiles a target if it's not compiled yet, or the source code is modified after the last compilation.
But if I interrupt
make, there will surely be one or more (depending on the concurrency level) half-ready binaries. What does it do with them the next time I run
make? Or does it finish the current target when I press Ctrl+C to avoid partly compiled binaries?
I know that I can interrupt a
In simple terms, you can think of
make as having a (possibly large) number of steps, where each step takes a number of files as input and creates one file as output.
A step might be "compile
file.o" or "use
ld to link
program". If you interrupt
make with CtrlC, then the currently executing step will be terminated which will (or should) remove the output file it was working on. There are usually not any "half-ready binaries" left behind.
When you restart
make, it will look at the timestamps of all the input and output files and rerun the steps where:
- an input file has a newer timestamp than the output file
- the output file does not exist
This generally means that if a step takes a long time to run (it's rare on modern computers, but the
ld step for large programs could easily take many minutes when
make was designed), then stopping and restarting
make will start that step over from the beginning.
The reality of your average
Makefile is considerably more complicated than the above description, but the fundamentals are the same.
Ctrl+C causes a
SIGINT to be sent to the process running. This signal can be caught by the process. In the make source code you can find a trap for this signal in
/* 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() is the cleanup function of
make, see it's definition here:
/* 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. */
And later in the function you see, they will be effectively deleted:
status = unlink (f->name);
Generally don't be affraid of interrupting a compilation with
make. If it's not an uncatchable signal (
SIGKILL, SIGSEGV, SIGSTOP) it will do a cleanup of intermediate files.
When something stops
make (be it ctrl-C, shutdown, or even a command that fails), the work already done stays. When restated,
make does as always: it figures out what still needs to be done (because a file changed or
make never got to have it processed doesn't matter) and goes on with the job.
The above description clearly presumes the relevant
Makefiles describe the dependencies and commands to execute correctly, so all what needs to be (re)made is.