GNU Make Escaping: A Walk on the Wild Side

[article]
Summary:

Sometimes you find yourself needing to insert a special character in a Makefile: perhaps you need a newline inside a $(error) message, or a space character in a $(subst) or a comma as the argument to a GNU Make function.  Those three simple things can be frustratingly hard in GNU Make; this article takes you through simple GNU Make syntax that removes the frustration.

Sometimes you find yourself needing to insert a special character in a Makefile: perhaps you need a newline inside a $(error) message, or a space character in a $(subst) or a comma as the argument to a GNU Make function.  Those three simple things can be frustratingly hard in GNU Make; this article takes you through simple GNU Make syntax that removes the frustration.

GNU Make's escaping rules
GNU Make's handling of 'tab' as the start of a command is a legendary language feature, but some other special characters can trip you up.  GNU Make's handling of $, %, ?, *, [, ~, \, and # are all special.

Every GNU Make user is familiar with $ for starting a macro reference.  It's possible to write $(macro) or ${macro} to get the value of macro and if the macro name is a single character (such as a) then the parens can be dropped and the short hand $a used.

To get a literal $ you write $$.  So to define a macro containing a single $ symbol you'd write:

dollar := $$

The % character rears its ugly head in three different places: in the vpath directive, in a $(patsubst) and in a pattern or static-pattern rule.

Escaping % is not as simple as $, but it only needs to be done in the three situation above, and the same rules apply for each.

The three rules for % escaping are:

1. % can be escaped with a single \ character (i.e. \% becomes a literal %.

2. If you need to put a literal \ in front of a % (i.e. you want the \ to not escape the %) then escape it with \ (i.e. \\% becomes a literal \ followed by a % character that will be used for the pattern match).

3. Don't worry about escaping \ anywhere else in a pattern, it will be treated as literal (i.e. \hello is \hello).

?, *, [, and ] get treated specially when they appear in a filename.  A Makefile that does

*.c:

    @command

Will actually search for all .c files in the current directory and define a rule for each.  The target (and the same applies for prerequisites and files mentioned in the include
directive) are globbed if they contain a wildcard character.  The globbing characters have the same meaning as in the Bourne shell.

The ~ character is also handled specially in filenames and is expanded to the home directory of the current user.

All of those special filename characters can be escaped with a \.  The following Makefile defines a rule for the file named literally *.c.

\*.c:

    @command

As well as the escaping function mentioned in this section, the \ can also be used as an continuation character at the end of a line:

all: \

prerequisite \

something else

    @command

The # character is used to start a comment and it can be made literal with a \ escape:

pound := \#

I just want a newline!

GNU Make does its best to insulate you from the newline character.  You can't escape a newline, there's no syntax for special characters (e.g. you can't write \n), and even the $(shell) function strips newlines from the returned value.

But you can define a macro that contains a newline using the define syntax:

define newline

endef

(Note that there are two blanks lines in the definition above).  With that definition $(newline) will expand to a newline and it can be used to format an error message nicely:

$(error This is an error message$(newline)with two lines)

Because of GNU Make's rather liberal macro naming

About the author

John Graham-Cumming's picture John Graham-Cumming

John Graham-Cumming is Co-Founder at Electric Cloud, Inc . Prior to joining Electric Cloud, John was a Venture Consultant with Accel Partners, VP of Internet Technology at Interwoven, Inc. (IWOV), VP of Engineering at Scriptics Corporation (acquired by Interwoven), and Chief Architect at Optimal Networks, Inc. John holds BA and MA degrees in Mathematics and Computation and a Doctorate in Computer Security from Oxford University. John is the creator of the highly acclaimed open source POPFile project. He also holds two patents in network analysis and has others pending.

CMCrossroads is one of the growing communities of the TechWell network.

Featuring fresh, insightful stories, TechWell.com is the place to go for what is happening in software development and delivery.  Join the conversation now!