Make has no such functionality built-in. And, in fact, keeping the list of the targets up-to-date manually is much cleaner and easier than any alternative solution. Personally, I'd probably start with something like this:
# second expansion is needed to get the value of
# $(targets) after the whole file was preprocessed
.SECONDEXPANSION:
all: $$(targets)
targets += build/a
build/a:
...
targets += build/b
build/b:
...
targets += build/c
build/c:
...
I don't believe that the requirement to add a single line per target (targets+=xxx
) could be so annoying for you.
However, this is how we can "preprocess" Makefile ourselves:
# assume all targets are explicitly defined in Makefile
targets != grep -o '^ *build/\w* *:' Makefile | sed 's/^ *//;s/ *:$$//'
all: $(targets)
build/a:
...
build/b:
...
build/c:
...
Of course, this would fail if targets are in the included files, or contain substitutions, etc. However, it works for "simple cases".