Makefile:带空格的先决条件

时间:2014-02-11 05:06:45

标签: makefile gnu-make

更新:GNU Make 3.81,Ubuntu 12.04

我有一组markdown文件,我想编译成(比方说)html文件,所以这是我的规则:

%.html: %.md
    pandoc $< -o $@

因此make foo.html会将foo.md转换为foo.html

但是,源标记文件名中有空格,我无法控制这些,即我无法更改设置以删除空格。

这意味着如果我make foo\ bar.html,我会

make: *** No rule to make target `foo bar.html'. Stop.

如何在必备文件名包含空格的情况下编写通用规则%.html: %.md

我可以通过使用:

来解决它
foo\ bar.html: foo\ bar.md
    pandoc $< -o $@

但是当我宁愿使用%构造时,我必须手动为每个这样的源文件写出这个规则。我唯一希望做某种$(foreach f,$(get list of *.md files),$(eval $(call function_to_generate_rule)))

2 个答案:

答案 0 :(得分:1)

修改

显然,对推理规则中的空格的支持取决于你正在使用的GNU Make的变体。它只是神奇地与Gentoo修补的sys-devel / make-3.82-r4一起工作(并且与Gentoo的make 3.81-r2失败)。在快速检查时,我没有注意到make-3.82的ChangeLog或NEWS或Gentoo补丁中的任何解释。所以使用空格的隐式规则可能只是make-3.82本身甚至是Gentoo的补丁集中的侥幸。官方GNU对目标空白的支持在仍然开放的GNU Make bug #712中进行跟踪。

原始误入歧途的答案

您可以使用shell支持的任何引用字符。执行宏替换时make忽略它们并将它们直接传递给shell。例如,

.SUFFIXES: .md .html
.md.html:
    pandoc "$(<)" > "$(@)"

导致$ make foo\ bar.html传递shell pandoc "foo bar.md" > "foo bar.html"。我决定使用传统的指定泛型make规则的方式,而不是涉及%的GNU Make扩展,但你也可以使用GNU Make的% - 样式规则。

这并不能解决包含引号字符的文件名的潜在问题。我认为,简单地说,大多数人都避免将"'放在文件名中,因为可能会导致Makefile或其他脚本出现问题。或者您可以使用GNU Makefile扩展名将"字符替换为\",这使得sh感到高兴(我们现在只是忽略cmd因为我甚至不......):

.SUFFIXES: .md .html
.md.html:
    pandoc "$(subst ",\",$(<))" > "$(subst ",\",$(@))"

使用名为a"b"c.md的文件对其进行了测试,该文件成功创建了a"b"c.html(免责声明:我使用了折扣的markdown命令而不是pandoc)。

答案 1 :(得分:1)

似乎@binki说GNU make 3.82可能没有这个问题,但遗憾的是我无法从我的Ubuntu 12.04机器上的v3.81进行更新。

我设法通过使用SECONDEXPANSION在先决条件中用反斜杠空格替换空格来“解决”它(因此foo bar.md的先决条件变为foo\ bar.md)。

# define a variable with a single space
space:=
space+=

.SECONDEXPANSION:
%.html: $$(subst $$(space),\$$(space),%).md
   pandoc "$<" -o "$@"

Here is the log。再次,在Ubuntu 12.04 / GNU Make 3.81上工作,也许如果你有3.82,你可以使用@ binki的解决方案,它似乎更优雅。