GNU Make Escaping: A Walk on the Wild Side


rules it's possible to actually define a macro called \n so if you line to keep things looking familiar you can do

define \n


$(error This is an error message $(\n)with two lines)

(More on special macro names in The Twilight Zone below)

Function arguments: space and comma
A problem that many GNU Make users run into is that handling of spaces and commas in GNU Make function arguments.  Consider the following use of $(subst) (which takes three arguments separated by commas: the from text, the to text and the string to change):

spaces-to-commas = $(subst  ,,,$1)

It defines a function called spaces-to-commas to convert all spaces in its argument to commas (might be handy for making a CSV file for example).  Unfortunately, it doesn't work.  It doesn't work for two reasons:

  1. The first argument of the $(subst) is a space.  Unfortunately, GNU Make strips all leading and trailing whitespace around function arguments.  In this case, the first argument is interpreted as an empty string.
  2. The second argument is a comma.  Unfortunately, GNU Make cannot distinguish between the commas used for argument separators and the comma as an argument. In  addition, there's no way to 'escape' the comma.

Fortunately, it's possible to work around this by knowning that GNU Make does the whitespace stripping, and separation of arguments before it doesn any expansion of the arguments themselves.   So, if we can define a macro containing a space and a macro containing a comma it will be possible to write:

spaces-to-commas = $(subst $(space),$(comma),$1)

to get the desired effect.

Defining a macro containing a comma is easy:

comma := ,

but space is a bit harder.   There are a couple of ways of defining a space.  The first uses the fact that whenever you append to a macro (using +=) a space is inserted before the appended text.
space :=
space +=

Another way is to first define a macro that contains nothing and then use it to surround the space so that it doesn't get stripped by GNU Make

blank :=
space := $(blank) $(blank)

This technique can also be used to get a literal tab character into a macro

blank :=
tab := $(blank)   $(blank)

(The whitespace in the definition of tab was created by hitting the tab key).

Much in the way I defined $(\n) above it's possible to define specially named space and comma macros.  GNU Make's rules are liberal enough to allow us to do:
, := ,
blank :=
space := $(blank) $(blank)
$(space) := $(space)

The first line defines a macro called , (which can be used as $(,) or even $,) containing a comma.  The last three lines define a macro called space containing a space character and then use it to define a macro name (that's right, it's name is a space character) containing a space.

With that definition it's possible to write $( ) or even $ to get a space character.  Using those definitions the spaces-to-commas function can be written:

spaces-to-commas = $(subst $( ),$(,),$1)

which I think it very clear.

The Twilight Zone
If you read this column regularly, you'll know that I'm not going to let a chance to really mess with GNU Make go by without pushing it to its limits.  Here are some other interesting macro definitions:

# Defining the $= or $(=) macro which has the value =

equals := =
$(equals) := =

# Define the $# or $(#) macro which has the value #

hash := \#
$(hash) := \#

# Define the $: or $(:) macro which has the value :

colon := :
$(colon) := :

# Define the $($$) macro which has the value $

dollar := $$
$(dollar) := $$


About the author

AgileConnection is a TechWell community.

Through conferences, training, consulting, and online resources, TechWell helps you develop and deliver great software every day.