Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to correctly escape "%" sign when using pattern rules and patsubst in GNU make?

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))
like image 241
Gavin Smith Avatar asked Oct 07 '13 19:10

Gavin Smith


People also ask

How do I escape a character in makefile?

I just learned that if you want to use a dollar sign inside a Makefile you need to escape $ with an extra $ , so double it. Otherwise make will think that you are accessing a make variable, not a shell one.

What is $$ in makefile?

Commands and executionIf you want a string to have a dollar sign, you can use $$ . This is how to use a shell variable in bash or sh . Note the differences between Makefile variables and Shell variables in this next example.

How do you use special characters in makefile?

Special characters in a makefile In macros, a backslash ( \ ) followed by a newline character is replaced by a space. In commands, a percent symbol ( % ) is a file specifier. To represent % literally in a command, specify a double percent sign ( %% ) in place of a single one.

What does Patsubst do in makefile?

Finds whitespace-separated words in TEXT that match PATTERN and replaces them with REPLACEMENT. Here PATTERN may contain a % which acts as a wildcard, matching any number of any characters within a word.


2 Answers

\ 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))

like image 117
Mark Galeck Avatar answered Oct 17 '22 15:10

Mark Galeck


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 $^
like image 1
Beta Avatar answered Oct 17 '22 14:10

Beta