Tracing rule execution in GNU Make

[article]

first capture the normal value of SHELL in a variable called OLD_SHELL (notice below that I use := to get SHELL's value and not its definition) and then I define SHELL to include the real shell value and a $(warning) that will print out the name of the target being built.

OLD_SHELL := $(SHELL)

SHELL = $(warning Building $@)$(OLD_SHELL)

.PHONY: all

all: foo.o bar

bar:

    @touch $@

Running GNU Make now produces really useful information:

make: Building foo.o

cc -c -o foo.o foo.c

Makefile:7: Building bar

The first line is the output of the $(warning) produced when the pattern rule to build foo.o is about to be executed. Since there's no Makefile and line number information we know that a built-in rule was used. The $(warning) shows us that foo.o was about to be built. That's because the $(warning) was able to use the GNU Make automatic variable $@ and hence we know which rule was about to run.

Then you see the actual output of the built-in rule (the cc comma! nd) foll owed by another piece of output from the $(warning). This time there's detailed information: bar is about to be built using the rule in Makefile at line 7.

Since it was possible to use $@ nothing stops us using other automatic variables. For example, we could find out the value of $< (the first prerequisite from which the target is being built) or the list of prerequisites that are newer than the target (which tells us why the target was built and is stored in $?).

OLD_SHELL := $(SHELL)

SHELL = $(warning Building $@$(if $<, (from $<))$(if $?, ($? newer)))$(OLD_SHELL)

.PHONY: all

all: foo.o bar

bar:

    @touch $@

Here SHELL has been redefined to output three pieces of information: the name of the target being built (from $@), the name of the first prerequi site (from $< and wrapped in a $(if) so that nothing is printed if there is no prerequisite) and the names of any newer prerequisites.

Running GNU Make now shows that foo.o was built from foo.c because foo.c was newer.

make: Building foo.o (from foo.c) (foo.c newer)

cc -c -o foo.o foo.c

Makefile:7: Building bar

There's nothing to stop us combining this $(warning) trick with the -x to get output showing which rules ran and what commands were executed:

OLD_SHELL := $(SHELL)

SHELL = $(warning Building $@$(if $<, (from $<))$(if $?, ($? newer)))$(OLD_SHELL) -x

.PHONY: all

all: foo.o bar

bar:

    @touch $@
 

Here's the full output with warnings and echoing of commands :

make: Building foo.o (from foo.c) (foo.c newer)

cc -c -o foo.o foo.c

+ cc -c -o foo.o foo.c

Makefile:7: Building bar

+ touch bar

In October 2005 I talked about the GNU Make Debugger which uses a SHELL definition trick to prompt the user for input each time a rule is run. Take a look at its code if you are interested in other things you can do by redefining SHELL.

Conclusion

With just a small redefinition of SHELL GNU Make can be coaxed into outputting detailed information about the rules that it is executing.

Next month I'll return with a look at what's new in GNU Make 3.81 including the new .SECONDEXPANSION feature, some backward incompatibilities, an explanation of order-only prerequisites, and all the new GNU Make functions.

About the author

John Graham-Cumming's picture John Graham-Cumming

John Graham-Cumming is Co-Founder at Electric Cloud, Inc . Prior to joining Electric Cloud, John was a Venture Consultant with Accel Partners, VP of Internet Technology at Interwoven, Inc. (IWOV), VP of Engineering at Scriptics Corporation (acquired by Interwoven), and Chief Architect at Optimal Networks, Inc. John holds BA and MA degrees in Mathematics and Computation and a Doctorate in Computer Security from Oxford University. John is the creator of the highly acclaimed open source POPFile project. He also holds two patents in network analysis and has others pending.

AgileConnection is one of the growing communities of the TechWell network.

Featuring fresh, insightful stories, TechWell.com is the place to go for what is happening in software development and delivery.  Join the conversation now!

Upcoming Events

Oct 12
Oct 15
Nov 09
Nov 09