更新: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)))
?
答案 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的解决方案,它似乎更优雅。