15
votes

I have a makefile like the following:

m1:
    @echo building m1

m1_:
    @echo building m1_


m2:
    @echo building m2

m2_:
    @echo building m2_

m3_DEPS = m2 m1

SUBSTITUTE=$(patsubst %,%_,$($@_DEPS))
.SECONDEXPANSION:

#%: $$(SUBSTITUTE)
%:  $$(patsubst \%,\%_,$$($$@_DEPS))
    @echo Building $@
    @echo Dependencies are $^

The key line is

%:  $$(patsubst \%,\%_,$$($$@_DEPS))

I am using both a pattern rule and patsubst, which itself uses percentage signs. I thought I could escape the % character with a \, but I am still not getting the expected behaviour. Running "make m3" gives the output

building m2
building m1
Building m3
Dependencies are m2 m1

However, I expect to get

building m2_
building m1_
Building m3
Dependencies are m2_ m1_

Commenting out that line and calling patsubst indirectly through a variable does in fact produce that output.

SUBSTITUTE=$(patsubst %,%_,$($@_DEPS))

%: $$(SUBSTITUTE)

Also, I have tested that using a non-pattern rule works, which makes me think it is something to do with the interaction of pattern rules and percentage signs:

m3:  $$(patsubst %,%_,$$($$@_DEPS))
3

3 Answers

18
votes

\ in makefile context is for line continuation, not for "escaping". To escape things you hide them in a variable:

PERCENT := %

The idea is, at the time a makefile fragment is parsed where the escaped character is meaningful, you escape it.

So, in your situation, you have to use $$(PERCENT):

$$(patsubst $$(PERCENT),$$(PERCENT)_,$$($$@_DEPS))

1
votes

I don't know of a way to hide '%' from the pattern rule, but in this case you can work around it:

%: $$(addsuffix _,$$($$*_DEPS))
    @echo Building $@
    @echo Dependencies are $^
0
votes

This does not appear to be possible.

For a few workarounds, see the question and Beta's answer.