如何使$(eval $(shell ...))在GNU make中工作

时间:2010-08-19 17:57:21

标签: shell makefile

make语法是换行符分隔的,但$(shell ...)用空格替换换行符。那么什么是最不丑的方式

$(eval $(shell program-that-emits-makefile-fragment))

不能按照人们喜欢的方式运作。

3 个答案:

答案 0 :(得分:13)

这可能会对你的想法有所帮助:

makefile_fragment:
  program-that-emits-makefile-fragment > $@

include makefile_fragment

这够了吗?如果需要,还可以使用其他技巧,例如让规则在程序生成的内容周围添加上下文,或者通过sed将输出管道化为一行,然后用反斜杠解析出来。

答案 1 :(得分:5)

已经向GNU make维护者报告了这个问题:

http://savannah.gnu.org/bugs/?28230

以下评论结束:

  

正如菲利普所说,这是预期/记录的行为   我建议使用“include”而不是eval;让你的脚本写出一个文件,然后包含该文件。

已添加:有一种解决方法!这是一个示例GNUmakefile(用制表符替换8个空格;是的,在define newline之后有两个空行):

define newline


endef

$(eval $(subst #,$(newline),$(shell { echo 'war:'; echo '        echo "not love?"'; echo '        echo "Give peace a chance!"'; } | tr '\n' '#')))

更一般地说,那是$(eval $(subst #,$(newline),$(shell myscript | tr '\n' '#')))

您必须选择一个不会出现在脚本输出中的字符; #似乎是一个很好的候选人。

答案 2 :(得分:0)

这是通过劫持%替换字符来实现的,所以我们不需要依赖于未出现在myscript输出中的char。

define nl


enddef
$(foreach line, $(shell myscript | sed -e 's/%/\\%/' -e 's/$$/%/'), \
  $(eval $(patsubst %, $(line), $(nl))))