我正在使用make的shell命令来填充一些变量,并且在输出时它表示它们被设置为我期望的值。然而,当我把它们传递给我的制作食谱时,它们都显示为空。我怀疑make正在对结果做一些奇怪的解析。例如:
output <- func( x = x, y = y )
我通过设置MyTarget: $(MySources)
LINE='$(shell cat $< | grep GIMME_THE_LINE_I_WANT)'
CH9=$(shell echo $(LINE) | cut -b9)
echo $(CH9) # doesn't print anything
手动检查了我的生成器命令,当我运行相同的命令时,我得到了正确的值,它看起来像bash是'归零'我的变量。知道什么是错的吗?
答案 0 :(得分:14)
这里有几件事情。首先是当你有:
MyTarget: $(MySources)
LINE='$(shell cat $< | grep GIMME_THE_LINE_I_WANT)'
您正在设置名为LINE
的 shell 变量,而不是make
变量。目标的构建指令都是shell命令。因此,在第一行之后,shell变量$LINE
包含GIMME_THE_LINE_I_WANT
。然而...
...目标的构建说明中的每个行都在单独的shell进程中运行。所以如果你有:
mytarget:
MYVAR=foo
echo $$MYVAR
您将看不到输出,因为$MYVAR
未在第二个命令的上下文中设置。另请注意此处使用$$
,否则$
将由Make解释(也就是说,写$MYVAR
实际上是make表达式$M
后跟文本YVAR
)。您可以通过逻辑将您的行连接到单个shell脚本来解决此问题,如下所示:
mytarget:
MYVAR=foo; \
echo $$MYVAR
\
是Makefile语法,它在多个物理行上扩展单个逻辑行,当然;
只是用于在一行上组合多个命令的shell语法。
考虑到这一切,我们可以像这样重写您的目标:
MyTarget: $(MySources)
LINE=$$(cat $< | grep GIMME_THE_LINE_I_WANT); \
CH9=$$(echo $$LINE | cut -b9); \
echo $$CH9
请注意,由于我们已经运行了一个shell脚本,我没有使用Make {#1}}构造,而且我确保逃脱所有$(shell ...)
个字符,以确保shell,而不是Make,正在处理变量扩展。
再远一点,你不需要在那个剧本中使用$
;你可以简单地写一下:
cat
或者:
MyTarget: $(MySources)
LINE=$$(grep GIMME_THE_LINE_I_WANT $<); \
CH9=$$(echo $$LINE | cut -b9); \
echo $$CH9
(注意:虽然与此解决方案没有密切关系,但值得注意的是MyTarget: $(MySources)
CH9=$$(grep GIMME_THE_LINE_I_WANT $< | cut -b9); \
echo $$CH9
的每次调用也都是在一个单独的流程中运行,因此一个变量集合不会成为可以在另一个。)
答案 1 :(得分:1)
make在其单独的shell中运行每个命令。因此,价值不会结转。
如有疑问,您可以随时使用 -d
选项对其进行调试。另外,一个站点注释,当您试图弄清楚为什么规则没有以您想要的方式触发时,调试选项非常有用。
~> cat Makefile
MyTarget:
LINE="somevalue"
echo ${LINE}
~>
~>
~> make -d MyTarget | tail -10
LINE="somevalue"
Putting child 0x2004fbb0 (MyTarget) PID 4052 on the chain.
Live child 0x2004fbb0 (MyTarget) PID 4052
Reaping winning child 0x2004fbb0 PID 4052
echo
Live child 0x2004fbb0 (MyTarget) PID 4192
Reaping winning child 0x2004fbb0 PID 4192
Removing child 0x2004fbb0 PID 4192 from chain.
Successfully remade target file 'MyTarget'.
~>
只是澄清那些贬低并评论我的上述解决方案不起作用的人:首先,我为我的懒惰道歉。可能我应该清楚。让我再试一次。
“make -d”不是OP问题的解决方案。
我试图向OP展示他/她如何使用调试选项来解决人们在使用makefile时遇到的各种问题(我承认,这只是解决OP问题的一个小问题)。
上面的调试显示第一个命令是在一个PID = 4052的shell中执行的,第二个命令是在另一个具有PID = 4192的shell中执行的(它没有携带该变量的值)。此外,它表明使用带有单个美元的变量($ {LINE})只会给你一个空白(因为makefile不会将它解释为shell变量)。
同样,要明确:“make -d”不是解决方案。只需将命令组合在一行中,用逗号分隔,就可以使用双倍美元;如果该行很长,则转义新行。
MyTarget:
LINE="somevalue"; \
echo $${LINE}