本文介绍了在GNU make中,环境变量和宏是如何交互的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
在GNU生成文件中,环境变量和参数/变量/宏之间经常存在交互。还有几种不同的赋值运算符,命令行上可以提供&覆盖&变量,还有override
指令。
这些交互的优先规则是什么?
考虑这个生成文件:
# Use := to avoid infinite recursion of macro expansion
CFLAGS := -g -O2 $(CFLAGS)
hello: src/hello.c
cc $(CFLAGS) -o $@ $<
如果调用CFLAGS=-pipe make hello
,则会得到cc -g -O2 -pipe -o hello src/hello.c
。如果调用make CFLAGS=-pipe hello
,则会得到cc -pipe -o hello src/hello.c
。有什么不同?如果将生成文件更改为:
CFLAGS ?= -g -O2 $(CFLAGS)
hello: src/hello.c
cc $(CFLAGS) -o $@ $<
在这两种情况下,您都会得到cc -pipe -o hello src/hello.c
。
推荐答案
此答案基于https://stackoverflow.com/a/63187052/2954547以及GNU Make manual的评论中的信息。
优先顺序为:从强到弱:
override
指令- 命令行覆盖
=
,:=
- 环境变量
?=
有几个单独的规则交互作用来创建此优先级:
为每个环境变量创建一个宏。例如,如果设置了
HOME
,则将有$(HOME)
宏。如果已经定义了宏,
=
和:=
将覆盖以前的宏定义。这包括环境变量,这些变量(在概念上)是在解释Makefile的其余部分之前创建的。因此=
或:=
将覆盖环境变量。但如果定义了环境变量,仍然可以在赋值的右侧引用它:CFLAGS := -g -O2 $(CFLAGS)
请注意,在本例中您必须使用
:=
,因为如果您使用=
,您将获得一个在运行时尝试永远递归展开自身的宏。按照section 6.5 of the manual,
VAR ?= val
相当于:ifeq ($(origin VARIABLE), undefined) VAR = val endif
环境变量的origin设置为
'environment'
,因此?=
将始终被环境变量覆盖。与=
和:=
不同,如果设置了环境变量,则其与?=
对应的赋值将永远不会被调用。命令行&覆盖变量&覆盖所有变量。这意味着
make VAR=val
覆盖环境变量VAR
,赋值VAR = val
、VAR := val
和VAR ?= val
。override
指令覆盖所有内容,包括命令行覆盖。
-e
/--environment-overrides
选项,它会导致环境变量覆盖=
和:=
。这使得它们在宏定义方面的行为与命令行覆盖变量相同,但(我认为)后者仍将优先。 这篇关于在GNU make中,环境变量和宏是如何交互的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!