Makefile:带空格的先决条件
Posted
技术标签:
【中文标题】Makefile:带空格的先决条件【英文标题】:Makefile: prerequisites with spaces 【发布时间】:2014-03-08 18:01:16 【问题描述】:更新:GNU Make 3.81、Ubuntu 12.04
我有一组 Markdown 文件,我想编译成(比如说)html 文件,所以这是我的规则:
%.html: %.md
pandoc $< -o $@
所以make foo.html
会将foo.md
转换为foo.html
。
但是,源 Markdown 文件名中有空格,我无法控制这些,即我无法更改设置以删除空格。
这意味着如果我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)))
吗?
【问题讨论】:
Make 确实不能很好地处理目标名称中的空格。我怀疑你找到的任何解决方案都是丑陋的组合。 在尝试重现您的问题时,输入%.html: %.md
markdown $< > $@
,我无法收到关于找不到目标的make
错误。你用的是哪个版本的make?
您知道make
要正确进行推理,源文件foo bar.md
必须存在或者是make
知道如何构建的东西,对吧?
@binki:当然,foo bar.md
确实存在。 GNU 制作 3.81。我可以重现这个。
好的,我在 Windows 上的 GNU make 3.81 上看到了这个问题,但在 GNU 上的 GNU make 3.82 上没有看到这个问题。
【参考方案1】:
从@binki 所说的看来,GNU make 3.82 可能没有这个问题,但不幸的是我没有选择从我的 Ubuntu 12.04 机器上的 v3.81 更新。
我设法通过在先决条件中使用 SECONDEPANSION 用反斜杠空格替换空格来“解决”它(因此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 的解决方案。
【讨论】:
【参考方案2】:编辑
显然,make 在推理规则中对空格的支持取决于您使用的 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 Make bug #712 中跟踪了 GNU 对目标中空格的官方支持。
原来的错误答案
您可以使用您的 shell 支持的任何引号字符。 make
在执行宏替换时会忽略它们并将它们直接传递给 shell。例如,
.SUFFIXES: .md .html
.md.html:
pandoc "$(<)" > "$(@)"
导致$ make foo\ bar.html
通过外壳pandoc "foo bar.md" > "foo bar.html"
。我决定使用指定通用make
规则的传统样式,而不是涉及%
的GNU Make 扩展,但我认为您也可以使用GNU Make 的%
样式规则来做到这一点。
这并不能解决文件名中包含引号字符的潜在问题。我认为,简单地说,大多数人只是避免将"
或'
放在文件名中,因为这可能会导致Makefile
s 或其他脚本出现问题。或者您可以使用 GNU Makefile 扩展名将 "
字符替换为 \"
,这让 sh
很高兴(我们现在将忽略 cmd
,因为我什至不...):
.SUFFIXES: .md .html
.md.html:
pandoc "$(subst ",\",$(<))" > "$(subst ",\",$(@))"
这是使用名为 a"b"c.md
的文件进行测试的,该文件成功创建了 a"b"c.html
(免责声明:我使用了折扣的 markdown
命令而不是 pandoc)。
【讨论】:
谢谢,我不知道后缀规则。但是,the GNU makefule book 表示后缀规则已过时。无论如何,当我尝试上面的第一个 makefile 时,我得到了同样的错误。 查看 this pastebin 向我展示如何尝试这个 makefile。 bash 外壳。以上是关于Makefile:带空格的先决条件的主要内容,如果未能解决你的问题,请参考以下文章