multi wildcard target in Makefile

Viewed 1995

Just simple Makefile:

a/% b/%:
    @echo $@

When I do

make a/a b/b

It's OK as expected that:

a/a

b/b

But when I do

make a/a b/a

It's appears that:

a/a

make: Nothing to be done for `b/a'.

How can I get the expect return

a/a

b/a

Tested with make version both v3.81 and v3.82 on Linux and macOS

2 Answers

Given your makefile...

a/% b/%:
        @echo $@

Consider what happens when you invoke make a/a b/b. make notices that the rule a/% b/%: matches with the stem a (i.e. the built in variable $* will be a) and runs the command. Because your rule has multiple targets make now considers both a/a and b/a to have been updated.

Make then considers the next target specified on the command line b/b. That hasn't yet been updated and so make runs the same rule again but with the stem b. So the rule is run twice -- once for each pattern stem a and b.

Now consider what happens when you invoke make a/a b/a. This time both targets will match the same rule but with the same stem a. Hence make, having run the rule with the stem a considers both a/a and b/a to have been updated and sees no need to rerun the rule for second command line target b/a.

It's not entirely clear what behaviour you require but if you want the same rule to be invoked multiple times for different targets even though the pattern stem is the same then you might want something like...

# Possible targets (for illustration purposes).
#
TARGETS := a/a a/b b/a b/b

$(TARGETS): %:
        @echo $@

The above gives...

G.M.> make -f multi-wildcard-target-in-makefile.mk a/a b/b
a/a
b/b

G.M.> make -f multi-wildcard-target-in-makefile.mk a/a b/a
a/a
b/a

If you do not want to hardcode possible targets as G.M. proposed, you may make some magic:

$ cat Makefile
define recipe
$(1):
    @echo $$@
endef

PATTERNS=a/% b/%
$(foreach pattern,$(PATTERNS),$(eval $(call recipe,$(pattern))))

Testing:

$ make a/a b/a
a/a
b/a
$ make a/a b/b
a/a
b/b

The behavior you observe is described in GNU make docs:

Pattern rules may have more than one target. Unlike normal rules, this does not act as many different rules with the same prerequisites and recipe. If a pattern rule has multiple targets, make knows that the rule’s recipe is responsible for making all of the targets. The recipe is executed only once to make all the targets.

Related