tags:

views:

509

answers:

2

I'm using code similar to the following in a Makefile:

empty:=
space:= $(empty) $(empty)
path_escape = $(subst $(space),\$(space),$(1))

TOP=$(call path_escape,$(abspath .))
TARGET=$(TOP)/foo

$(info TOP='$(TOP)')
$(info TARGET='$(TARGET)')

all: $(TARGET)

$(TARGET):
    touch '$(notdir $@)'

.PHONY: $(TARGET)

If I use this in a directory with no spaces, say space-test, it works fine:

$ make
TOP='/tmp/space-test'
TARGET='/tmp/space-test/foo'
touch 'foo'

However, if I use it in a directory with spaces, say space test, then $(notdir) does the wrong thing:

TOP='/tmp/space\ test'
TARGET='/tmp/space\ test/foo'
touch 'space foo'

What's happening here is that $(notdir) interprets /tmp/space test/foo as two paths and returns the "file part" of both (i.e., space and foo). The weird part of this is that TARGET is properly escaped; somehow, inside the rule or inside $(notdir), the backslash escapes are being ignored.

What am I doing wrong here?

A: 

This is just a shot in the dark, please don't hate or downvote me if it doesn't work

TOP='"/home/chris/src/tests/make/space test"'

Gary Benade
Gary, I don't hate you, I am full of love. Don't take down-votes personally, they just signal whether an answer is correct and/or helpful. In this case, no, this does not work.
Chris Conway
We aren't downvoting **you**, we're downvoting your **answer**. Don't feel bad about that.
JesperE
+1  A: 

The $(notdir) function in GNU Make takes a list of arguments, separated by spaces. Some functions support escaping spaces with \\, but $(notdir) is not one of them.

This should work:

s? = $(subst $(empty) ,?,$1)
?s = $(subst ?, ,$1)
notdirx = $(call ?s,$(notdir $(call s?,$1)))

$(TARGET):
    touch '$(call notdirx,$@)'

This defines a "space-safe" version of notdir called notdirx. It's quite simple: s? first turns all spaces to question marks (hoping that they cannot be present in file names), and ?s converts back. In between we can safely call the original notdir function.

For an excellent summary on GNU Make and spaces in file names, see GNU Make meets file names with spaces in them.

Ville Laurikari
Thanks, Ville. It's pretty ridiculous that there's no way to escape inputs to $(notdir) except via this hack (or so it seems).
Chris Conway
Yeah. GNU Make could really use an optionally enabled (backwards incompatible) version 2 of the language and standard functions. Or maybe it's best to just use, say, SCons or something with a real programming language.
Ville Laurikari