Makefile: prerequisites with spaces

自闭症网瘾萝莉.ら 提交于 2019-12-11 22:12:11

问题


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)))?


回答1:


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.




回答2:


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 Makefiles 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).



来源:https://stackoverflow.com/questions/21693582/makefile-prerequisites-with-spaces

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!