请考虑以下事项:
$ cat a.sh
#!/bin/sh
echo in a.sh, BANANA=$BANANA
$ cat Makefile
.PHONY: foo
export BANANA = I am a banana
foo:
$(eval F=`./a.sh`) # BANANA is set in a.sh
echo $F
$(eval G=$(shell ./a.sh)) # BANANA is *not* set in a.sh
echo $G
$ make
# BANANA is set in a.sh
echo `./a.sh`
in a.sh, BANANA=I am a banana
# BANANA is *not* set in a.sh
echo in a.sh, BANANA=
in a.sh, BANANA=
如上所示,Make的export
指令告诉make在其子环境中设置变量BANANA
。但该设置不适用于shell
功能。它似乎适用于反引号。这是一个错误吗?如何轻松地将变量设置为shell
函数的环境?
注意:
$ make --version
GNU Make 4.0
Built for x86_64-unknown-linux-gnu
Copyright (C) 1988-2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
答案 0 :(得分:1)
首先,要清楚你的食谱的含义:
foo:
$(eval F=`./a.sh`) # BANANA is set in a.sh
echo $F
$(eval G=$(shell ./a.sh)) # BANANA is *not* set in a.sh
echo $G
此配方包含两个(不是四个)命令:
foo:
echo $F
echo $G
和两个make-functions:
$(eval F=`./a.sh`)
$(eval G=$(shell ./a.sh))
当make
决定时,将按顺序评估双线配方的范围 运行。如果您对这一点感到懊恼,请阅读this question 并回答。
另请注意,F
和G
都是 make 变量,而不是shell变量。您
只是提到$F
和$G
而不是$(F)
和$(G)
到6.1 Basics of Variable References的最后一段
美元符号后跟一个美元符号,左括号或左括号以外的字符 将该单个字符视为变量名称。因此,您可以使用'$ x'引用变量x。 但是,强烈建议不要这样做,除非是自动变量
它不适用于FF
和GG
。
因此编写makefile的正常方法是:
.PHONY: foo
export BANANA = I am a banana
foo: F=`./a.sh`
foo: G=$(shell ./a.sh)
foo:
echo $(F)
echo $(G)
具有完全相同的效果。
这或许澄清了echo $(F)
输出之间的差异
和echo $(G)
。
$(shell ./a.sh)
调用一个在shell中执行./a.sh
的make函数
由make
直接生成并返回stdout
这样做。因此,对于目标foo
,生成变量G
将会
被定义为stdout
子shell中执行./a.sh
的{{1}}。
make
不会调用任何make-function。就制造而言,它只是
一个字符串。对于目标`./a.sh`
,生产变量foo
将定义为F
导出的生成变量`./a.sh `
未注入由生成的shell的环境中
BANANA
。 5.7.2 Communicating Variables to a Sub-make
要传递或导出变量,make会将变量及其值添加到 运行食谱的每一行的环境
导出变量及其定义仅注入到shell的环境中 运行食谱。
因此$(shell ...)
在BANANA
运行a.sh
时未定义$(shell ./a.sh)
生成G
的定义。但是是在shell的环境中定义的
运行配方行echo $(F)
,$(F)
= `a.sh`
。那个shell(不是make
)解释
`a.sh`
作为子shell的反向调用,继承了定义
BANANA
。
要将BANANA
导出到$(shell ...)
的环境中,您必须这样做
它是你自己,因为它不是由make
完成的:
G=$(shell export BANANA='$(BANANA)'; ./a.sh)