繁体   English   中英

Makefile使用Shell创建变量

[英]Makefile Use Shell to create variables

我使用make的shell命令来填充一些变量,并在输出时指示它们被设置为我期望的值。 然而,当我把它们传递给我的制作食谱时,它们都显示为空。 我怀疑make正在对结果做一些奇怪的解析。 例如:

MyTarget: $(MySources)
    LINE='$(shell cat $< | grep GIMME_THE_LINE_I_WANT)'
    CH9=$(shell echo $(LINE) | cut -b9)
    echo $(CH9) # doesn't print anything

我通过设置SHELL=sh -XV手动检查我的生成器命令,当我运行相同的命令时,我得到正确的值,它看起来像bash是'归零'我的变量。 知道什么是错的吗?

这里有几件事情。 首先是当你有:

MyTarget: $(MySources)
    LINE='$(shell cat $< | grep GIMME_THE_LINE_I_WANT)'

您正在设置名为LINEshell变量,而不是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

\\ is是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 ...)每次调用也在一个单独的进程中运行,因此在一个中设置的变量将在另一个中不可用。)

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}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM