Update: GNU Make 3.81, Ubuntu 12.04
I have a set of markdown files that I want to compile to (say) html files, so this is my rule:
%.html: %.md
pandoc $< -o $@
So make foo.html
would convert foo.md
into foo.html
.
However, there are spaces in the source markdown filenames and I do not have the ability to control these, that is I can't change a setting to remove the spaces.
This means if I make foo\ bar.html
, I get
make: *** No rule to make target `foo bar.html'. Stop.
How can I write a generic rule %.html: %.md
where the prerequisite filename has spaces?
I can get around it by using:
foo\ bar.html: foo\ bar.md
pandoc $< -o $@
But then I must manually write out this rule for every such source file that I have, when I'd rather use the %
construct. Is my only hope to do some sort of $(foreach f,$(get list of *.md files),$(eval $(call function_to_generate_rule)))
?
It seems from what @binki says that GNU make 3.82 might not have this issue, but unfortunately I do not have the option to update from v3.81 that is on my Ubuntu 12.04 machine.
I managed to "solve" it like so by using SECONDEXPANSION to substitute spaces with backslash-space in the prerequisite (so a prerequisite of foo bar.md
becomes foo\ bar.md
).
# define a variable with a single space
space:=
space+=
.SECONDEXPANSION:
%.html: $$(subst $$(space),\$$(space),%).md
pandoc "$<" -o "$@"
Here is the log. Again, works on Ubuntu 12.04/GNU Make 3.81, perhaps if you have 3.82 you can use @binki's solution which seems more elegant.
Edit
Apparently make’s support for whitespace in inference rules depends on what variant of GNU Make you are using. It just magically works fine with Gentoo’s patched sys-devel/make-3.82-r4 (and fails with Gentoo’s make 3.81-r2). I did not notice any explanation in make-3.82’s ChangeLog or NEWS or the Gentoo patches when quickly checking them. So implicit rules working with whitespace could just be a fluke in make-3.82 itself or even from Gentoo’s patchset. Official GNU support for whitespace in targets is tracked in the still-open GNU Make bug #712.
Original misguided answer
You can use any quoting characters that your shell supports. make
ignores them when performing macro substitution and passes them directly to the shell. For example,
.SUFFIXES: .md .html
.md.html:
pandoc "$(<)" > "$(@)"
results in $ make foo\ bar.html
passing the shell pandoc "foo bar.md" > "foo bar.html"
. I decided to use the traditional style of specifying generic make
rules instead of the GNU Make extension involving %
, but you can do this with GNU Make’s %
-style rules too, I assume.
This does not solve the potential problem of the filenames containing quote characters in them. I think that, simply, most people just avoid putting "
or '
in filenames because of the likelihood of causing issues with Makefile
s or other scripts. Or you could use a GNU Makefile extension to replace the "
characdter with \"
, something that makes sh
happy (we’re going to just ignore cmd
for now because I don’t even…):
.SUFFIXES: .md .html
.md.html:
pandoc "$(subst ",\",$(<))" > "$(subst ",\",$(@))"
This was tested with a file called a"b"c.md
which succeeded in creating a"b"c.html
(disclaimer: I used discount’s markdown
command instead of pandoc).