考虑一段 GNU Makefile 是由命令生成的(可能是因为要定义的变量列表太复杂,否则无法实现)。
脚本
test.sh
:
echo 'V1 = foo bar'
echo 'V2 = ab cd'
如果我在 GNU Makefile 中尝试这个:
$(eval $(shell ./test.sh))
$(info V1='$(V1)')
$(info V2='$(V2)')
我明白了:
V1='foo bar V2 = ab cd'
V2=''
虽然我想要这个:
V1='foo bar'
V2='ab cd'
我知道
$(shell)
会在空间中变换新的线条。我在网上发现了类似但不相同的问题,但答案不正确。例如,在 Makefile 中使用显式 NL
变量:
define NL
endef
$(eval $(shell ./test.sh))
$(info V1='$(V1)')
$(info V2='$(V2)')
然后在脚本中创建对
$(NL)
的引用:
echo 'V1 = foo bar$(NL)'
echo 'V2 = ab cd$(NL)'
我明白了:
V1='foo bar
V2 = ab cd
'
V2=''
对
$(NL)
的引用被一个换行符替换,但该换行符被吞入 V1
而不是分隔变量的定义。
我还没有找到从命令输出中使用
include
指令的方法(除了创建一个临时文件,这在清理方面非常难看)。
对于
test.sh
的这种格式,一种方法是:
$ cat Makefile
.PHONY: all
all:
@echo "V1=$(V1). V2=$(V2). All done"
incfile: ./test.sh
cat $< | sed -e "s/echo\( \)\+//g" -e "s/'//g" -e "s/=\( \)*\(.*\)/ = '\2'/g" > $@
include incfile
第一次运行如下:
$ make
cat test.sh | sed -e "s/echo\( \)\+//g" -e "s/'//g" -e "s/=\( \)*\(.*\)/ = '\2'/g" > incfile
V1='foo bar'. V2='ab cd'. All done
虽然
incfile
不是all
的先决条件,但它是Makefile
的自动先决条件,
因为它是include
d。