We have a long and complicated Makefile in our build system. Is there a good way to trace exactly which targets get executed for a given make invocation?
You can get some information about what targets are being built and why by redefining the SHELL variable in GNU make:
__ORIGINAL_SHELL:=$(SHELL)
SHELL=$(warning Building $@$(if $<, (from $<))$(if $?, ($? newer)))$(TIME) $(__ORIGINAL_SHELL)
For example, in trace-targets.mk
:
__ORIGINAL_SHELL:=$(SHELL)
SHELL=$(warning Building $@$(if $<, (from $<))$(if $?, ($? newer)))$(TIME) $(__ORIGINAL_SHELL)
all: aa.stamp ba.stamp
%.stamp:
echo stamp > $(@)
stamp-clean:
rm -vf *.stamp
clean: stamp-clean
.PHONY: %.phony
%.phony:
echo $(@)
aa.stamp: ab.stamp
ab.stamp: ac.stamp
ba.stamp: bb.stamp
bb.stamp: bc.phony
Running trace-targets.mk
after clean:
$ make -f trace-targets.mk
trace-targets.mk:9: Building ac.stamp
echo stamp > ac.stamp
trace-targets.mk:9: Building ab.stamp (from ac.stamp) (ac.stamp newer)
echo stamp > ab.stamp
trace-targets.mk:9: Building aa.stamp (from ab.stamp) (ab.stamp newer)
echo stamp > aa.stamp
trace-targets.mk:18: Building bc.phony
echo bc.phony
bc.phony
trace-targets.mk:9: Building bb.stamp (from bc.phony) (bc.phony newer)
echo stamp > bb.stamp
trace-targets.mk:9: Building ba.stamp (from bb.stamp) (bb.stamp newer)
echo stamp > ba.stamp
Then running trace-targets.mk
again without cleaning:
$ make -f trace-targets.mk
trace-targets.mk:18: Building bc.phony
echo bc.phony
bc.phony
trace-targets.mk:9: Building bb.stamp (from bc.phony) (bc.phony newer)
echo stamp > bb.stamp
trace-targets.mk:9: Building ba.stamp (from bb.stamp) (bb.stamp newer)
echo stamp > ba.stamp
Practically, what I do in my makefiles is I add this snippet:
ifneq ($(filter all targets,$(VERBOSE)),)
__ORIGINAL_SHELL:=$(SHELL)
SHELL=$(warning Building $@$(if $<, (from $<))$(if $?, ($? newer)))$(TIME) $(__ORIGINAL_SHELL)
endif
Then I run my makefiles as follow to see the tracing:
make VERBOSE=all
# or
make VERBOSE=targets
The reason for the all/targets is because I also have other verbose stuff like this:
ifneq ($(filter all vars,$(VERBOSE)),)
dump_var=$(info var $(1)=$($(1)))
dump_vars=$(foreach var,$(1),$(call dump_var,$(var)))
else
dump_var=
dump_vars=
endif
# used like
$(call dump_vars,SHELL VERBOSE)
And sometimes I want to selectively enable/disable debugging aspects.
If you have many makefiles it may make sense to put this in a common file and include it from others.
Credit by John Graham-Cumming who described this method in Tracing rule execution in GNU Make.