GNU make doc - 6.6 追加变量值

有时我们需要对已经定义过的变量进行追加,可以使用+=进行这一操作,就像下面这样

    objects += another.o

该语句取objects变量的值,并在其后追加 another.o(结果会在原变量值和another.o之间加上一个空格,即使上述语句中+=another.o之间没有空格或有多个空格),因此

    objects = main.o foo.o bar.o utils.o
    objects += another.o

会将objects设置为main.o foo.o bar.o utils.o another.o
使用+=类似于:

    objects = main.o foo.o bar.o utils.o
    objects := $(objects) another.o

但是在使用更为复杂的变量值时,这两种方式可能会有明显的差异

若对尚未定义过的变量进行操作时,+=等效于:=,定义了一个递归展开的变量.然而,当对已定义的变量进行+=操作时,实际进行的操作取决于该变量的类型(简单展开还是递归展开).关于两种变量类型请参考The Two Flavors of Variables

当使用+=追加变量时,实质就是在原先的定义上追加.
当对一个原先以:=或者::=定义的简单展开展变量进行+=操作时,make将会在追加之前将原变量展开

    variable := value
    variable += more

等效于

    variable := value
    variable := $(variable) more

另一方面,当对一个原先以=定义的递归展开变量进行+=操作时,make的表现与前一种情况有所不同,回想一下,当你定义一个循环展开变量时,make并不会立即展开变量值中包含的变量或函数引用,而是会照原样保留,只有在之后引用这个变量时,才会展开变量定义中所包含的引用.当对递归展开变量进行+=操作时,实际上make会直接在变量字面值(而不是展开后的值)上进行附加.

    variable = value
    variable += more

大致相当于

    temp = value
    variable = $(temp) more

当然,make并不会为此而实际定义temp.值得关注的是,当变量原始值包含对其他变量或函数的引用时,发生了什么,举个例子:

    CFLAGS = $(includes) -O
    …
    CFLAGS += -pg # enable profiling

第一行的CFLAGS定义包含了对另一个变量includes的引用.由于CFLAGS是用=定义的,所以它是一个循环展开变量,也就意味着make在处理CFLAGS的定义时并不会展开$(includes) -O.因此,也就意味着includes在真正生效之前不必被定义.includes只需在真正使用CFLAGS之前定义即可.如果我们试图使用除了+=之外的其他方法完成对CFLAGS的追加操作,或许会这样:

    CFLAGS := $(CFLAGS) -pg # enable profiling

这相当接近我们的目的,但并不完全是.使用:=会将CFLAGS重新定义为简单展开变量;也就意味着make会在重新为CFLAGS赋值之前展开$(CFLAGS) -pg,如果includes尚未定义,我们会得到 -O -pg,即使后来定义了includes也不会对CFLAGS产生影响.相反,使用+=会将CFLAGS设置为未展开的$(includes) -O -pg.因此也就会保留对includes的引用,所以只要在之后任何地方给出了includes的定义,对CFLAGS的引用$(CFLAGS)都会使用该值.

posted @ 2019-03-23 14:31  l_____py  阅读(213)  评论(0编辑  收藏  举报