The capture of automatic variables is done by the new_rule macro called by do which uses the GMSL map function to call another macro (dump_var) for each of @ % < ? ^ + *. new_rule also ensures that the corresponding .force file has been created.
Lastly, do writes out the complex $(if ...) statement that contains both the unexpanded and expanded versions of the commands for the current rule. And then it actually runs the commands (that's the $C) at the end.
There are a small number of limitations to this technique. Firstly if the commands in a rule contain any side effects (e.g. they call $(shell ...) then the system may misbehave if there was an assumption that the $(shell ...) was only called once.
Secondly, it's vital that signature is included before any of the .sig files.
And lastly, if the Makefile is edited and the commands in a rule change the signature system will not notice. If you do that then it's vital to regenerate the corresponding target so that the .sig is updated.
Not a lot of code, for a lot of benefit. Let me know if you use it in a large project!
Lastly, reader Semih Cemiloglu wrote to say that a while back I'd promised to write an article on tracing which rules in a Makefile fire and in what order. Although some of that is covered in recent articles on the GNU Make Debugger, I'll return in April with the missing piece! Thanks for the reminder Semih.