这里发生了几件事。第一个是当你有:
MyTarget: $(MySources)
LINE='$(shell cat $< | grep GIMME_THE_LINE_I_WANT)'
您正在设置一个名为LINE 的shell 变量,而不是make 变量。目标的构建指令都是 shell 命令。所以在第一行之后,shell 变量$LINE 包含GIMME_THE_LINE_I_WANT。不过……
...构建指令中的每个 line 目标都在单独的 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 ...) 的每次调用也在单独的进程中运行,因此一个变量集在另一个进程中将不可用。)