这里发生了几件事情。首先当你有:
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的$(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
(注:尽管与此解决方案无关,但值得注意的是,每次调用$(shell ...)
也会在单独的进程中运行,因此在一个变量中设置的变量在另一个变量中不可用。)
$(LINE)
中是否有特殊字符?你应该将其引用起来,例如shell echo '$(LINE)'
。 - Barmarcat
是无用的。 - tripleee