I am trying to implement the logic to display the progress of the build in a makefile.
I can successfully print it for the target “simple” in the makefile cascaded herewith. However when it comes to another target “for” in the makefile, something goes wrong and I am not able to figure out what it is.
Any help would be really appreciated.
## BUILD is initially undefined
ifndef BUILD
# T estimates how many targets we are building by replacing BUILD with a special string
T := $(shell $(MAKE) progress --no-print-directory \
-nrRf $(firstword $(MAKEFILE_LIST)) \
BUILD="COUNTTHIS" | grep -c "COUNTTHIS")
## N is the target number
N := x
## incrementing counter
C = $(words $N)$(eval N := x $N)$(shell export $N)
## BUILD is now defined to show the progress, this also avoids redefining T in loop
BUILD = echo "`expr " [\`expr $C '*' 100 / $T\`" : '.*\(....\)$$'`%]"
endif
MODULE_LIST = module1
MODULE_LIST := $(MODULE_LIST) module2
MODULE_LIST := $(MODULE_LIST) module3
MODULE_LIST := $(MODULE_LIST) module4
MODULE_LIST := $(MODULE_LIST) module5
progress:
@$(BUILD)
@$(BUILD)
@$(BUILD)
@$(BUILD)
@$(BUILD)
simple:
# T=5 and C increases for every access
@$(BUILD) "Cleaning Module \"module1\""
@sleep 0.1
@$(BUILD) "Cleaning Module \"module2\""
@sleep 0.1
@$(BUILD) "Cleaning Module \"module3\""
@sleep 0.1
@$(BUILD) "Cleaning Module \"module4\""
@sleep 0.1
@$(BUILD) "Cleaning Module \"module5\""
@sleep 0.1
for:
# T=1 and C increases for every access but not inside the for loop
@for MODULE in $(MODULE_LIST); do \
$(BUILD) "Cleaning Module \"$$MODULE\"" ; \
sleep 0.1 ; \
done
As you noted in your comment, the problem is that the for loop executes inside the shell, and so does not update the Makefile’s variables (or at least not more than once when Make builds the command string up by evaluating the variable references inside it).
The only feasible solution I can see is to move your loop construct into the Makefile. Try this:
This includes a couple of other changes too.
A solution that seems plausible at first glance is to
export Nfrom the makefile and design thePRINT_PROGRESScommand so thatNis always updated as an environment variable. I couldn’t find a way to make this work though, since it requires some way of getting the updated N value back into Make after the command has been written, so that separate commands still work.Edit: Output when running the exact script above (with corrected tab indents), plus versions used: