In my gnu-make-3.81 Makefile, I wish to define two implicit rules, such that the more specific first one takes precedence over the more general second one:
src/%_bar.o : src/%_bar.c
$(CC) -Wall -Wno-unused-but-set-variable -c $^ -o $@
src/%.o : src/%.c
$(CC) -Wall -c $^ -o $@
The issue I have is that foo_bar.c represents autogenerated code that triggers a warning with -Wall that I'd prefer to suppress, so the first rule is meant to catch this special case.
According to make's manual:
It is possible that more than one pattern rule will meet these criteria. In that case, make will choose the rule with the shortest stem (that is, the pattern that matches most specifically).
I thought that for a filename of src/foo_bar.o, the first rule would generate the stem foo, and the second would generate foo_bar. The former is the shortest so I'd expect it to apply. However this doesn't seem to be the case, the second rule is selected by make and executed. Running make -d doesn't even show an attempt to match with the stem foo - only foo_bar is considered.
If I make the following change, by making the second rule's stem deliberately longer by shortening the prefix from src/ to sr, the second rule is still selected:
src/%_bar.o : src/%_bar.c
$(CC) -Wall -Wno-unused-but-set-variable -c $^ -o $@
sr%.o : sr%.c
$(CC) -Wall -c $^ -o $@
I can't reconcile this with the make documentation.
In addition, if I remove the src/ prefix entirely, the second rule is selected:
src/%_bar.o : src/%_bar.c
$(CC) -Wall -Wno-unused-but-set-variable -c $^ -o $@
%.o : %.c
$(CC) -Wall -c $^ -o $@
Although this solves my problem, it's actually not suitable because it overrides/interacts with another implicit rule on the current directory that I need to keep:
%.o : %.c
# do something else
My question is why does make behave this way in this case, and is this consistent with the documentation? If so, is there a better way to specify a more specialised implicit rule?