为什么我不能在GNU make' define'中创建变量。指示

时间:2017-02-02 22:10:11

标签: android makefile gnu-make recipe

我正在尝试构建一个GNU Make Canned Recipe,如下所示:

define this-will-fail
my_var=1
$(info your variable is $(my_var))
endef

$(this-will-fail)

这会导致错误*** missing separator. Stop.

但是,以下工作符合预期:

define why-does-this-work
$(eval my_var=1)
$(info your variable is $(my_var))
endef

$(why-does-this-work)

打印your variable is 1

我正在查看AOSP's build system并经常看到evaldefine配对的用法。什么是这两个项目之间的关系,为什么我不能创建变量"通常"使用define时?

1 个答案:

答案 0 :(得分:0)

答案源于一个带有大分歧的简单点 - 一个makefile有两个方言,1)make语言本身和2)你用来调用gcc之类的东西的shell语言。

提醒正常制作“规则”语法:

targets : prerequisites
        recipe

虽然make目标和先决条件在make中 语法,配方中的东西是shell语法中的,而不是语法

这就解释了为什么你不能把make变量作为配方的一部分来做,因为:

all: the_dependencies_of_all
    this_will_not_work := because_the_shell_does_not_know_what_this_line_means

在shell语法位中,make执行三个特殊的文本操作,然后将剩余的字符串逐字传递给shell。这三个步骤是

  1. 处理转义的换行符(例如反斜杠后跟换行符)
  2. 运行任何制作功能(例如$(filter ....)$(eval ..)
  3. 展开任何制作目标变量(例如$@
  4. 在正常情况下,这个3-steps-then-shell进程每个配方行发生一次,因此makefile配方的每一行都在不同的shell中运行(因此为什么对make的一些调用会产生许多/bin/sh子流程)。

    上面的操作#2解释了为什么你可以在食谱中使用eval为你的食谱添加一些make语法。 Eval将变成一个空字符串,这将导致shell没有问题,但make将评估语句中的字符串,因此可以使用变量定义之类的东西。

    评估发生的精确时刻有点难以确定 - 它似乎发生在变量首次展开时,它本身取决于你在makefile中引用该变量的位置。也许有人可以更多地澄清这一点,因为当发生这种情况时,对使用-j标志并行运行多个配方行的make的调用会产生影响

    更多信息: