GNU Make meets file names with spaces in them

[article]
Yes
$? No
$^ No
$+ No

And it gets a little worse... even though the first four automatic variables there are

safe to use, the modified versions with D and F suffixes (that extract the directory and
file name portions of the corresponding automatic variable) are not.   That's because they
are defined in terms of the dir and notdir functions.

Consider this example Makefile:

/tmp/foo\\ bar/baz: bar\\ baz a\\ b

    @echo Making $@ from $<

The value of $@ is /tmp/foo bar/baz as expected, but the value of $(@D) is /tmp bar (/tmp/foo bar would be expected) and the value of $(@F) is foo file (instead of file).

Another way: turn spaces into ?

In "Managing Projects with GNU Make, 3rd Edition" by Mecklenburg there's a different
suggestion: turn spaces into question marks.  Here's the original simple Makefile
transformed that way:

foo?bar: bar?baz

    @echo Making $@ from $<

Since GNU Make does globbing of target and prerequisite names (and respects any spaces found) this will work.  But the results are rather inconsistent.

If foo bar exists when this Makefile runs then the pattern foo?bar will get turned into
foo bar and that value will be used for $@.   If that file were missing when the Makefile
is parsed the pattern (and hence $@) stay as foo?bar.

(Of course, there's a another problem: that ? could match something other than a space: if
there's a file called foombar on the system the Makefile may end up working on the wrong
file).

To get around this problem Mecklenburg defines two functions to add and remove spaces
automatically.  Here's the updated Makefile using two functions (sq and qs) to add and
remove question marks.

sp :=

sp +=

qs = $(subst ?,$(sp),$1)

sq = $(subst $(sp),?,$1)

$(call sq,foo bar): $(call sq,bar baz)

    @echo Making $(call qs,$@) from $(call qs,$<)

Since we can't be sure whether the automatic variables will or will not have question
marks in them (since that depends on the state of the file system when the Makefile is
parsed), it's still impossible to use the list-based automatic variables or any GNU Make
functions that handle lists.

(Aside, the first two lines above end up putting a single space in the macro sp, it's
needed for the definition of sq since the first argument to the $(subst) needs to be a
space.)

Frankly, I think Mecklenburg's approach causes more trouble than it's worth: it doesn't
give consistent results, the values of $@ and other automatic variable have to be wrapped
in a call to a function, the ? could end up matching a non-space and all targets and
prerequisites need to be wrapped up with a $(call sq).

My advice

So given that GNU Make clearly has a really hard problem with spaces in file names what
can be done.  Here's my advice:

    • Don't.  If you can rename your files to not include spaces, that's going to be the
      simplest path.  I realize that for many people this is impossible, those spaces in
      file names may have been put there by a third-party.

 

    • Use 8.3 filenames.  If you are on Windows it may be possible to use short, 8.3
      file names throughout.   This will allow you to still have spaces on disk, but avoid
      them in the Makefile.

 

  • Use the \\ escaping.  If you still need the spaces, then escape than with \\. 
    This does give consistent results; you'll have to avoid the automatic variables
    mentioned above.

If you do number 3 and yet you need to manipulate lists of file names that contain

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.

AgileConnection 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!