使用 ENV 变量或默认值定义 Makefile 变量
Posted
技术标签:
【中文标题】使用 ENV 变量或默认值定义 Makefile 变量【英文标题】:Define a Makefile variable using a ENV variable or a default value 【发布时间】:2014-08-07 10:26:32 【问题描述】:我正在尝试做一件简单的事情:
TMPDIR ?= /tmp
test:
@echo $(TMPDIR)
如果我运行,这会起作用:
$ make test
/tmp
如果我运行它也可以:
$ make test -e TMPDIR=~/tmp
/home/user/tmp
我该怎么做才能让它也适用于:
$ TMPDIR=~/tmp make test
/home/user/tmp
【问题讨论】:
Erhm... 你有什么工作(如果你使用?=
并且你设置了环境变量,那么将使用环境变量的值)。究竟是什么问题(为什么你认为它不起作用)?
也仅供参考,在 makefile 中为变量值添加引号通常不是一个好主意。
是的,我仔细检查了,我使用 TMPDIR ?= "/tmp"
和 echo $(TMPDIR)
唯一的事情是不要忘记变量名周围的括号。
你对-e
的使用倒退了。 -e
表示允许环境变量覆盖在makefile中定义的变量,它们不会影响来自命令行参数的变量赋值。
对不起,纳蒂姆,但?=
确实工作。如果它没有按照您的意愿做,那么您上面的解释令人困惑,我们不理解您想要什么,或者您的真实环境中有一些东西没有反映在您的上面的问题中。
【参考方案1】:
Variables specified on make
command line override the values assigned in makefile:
TMPDIR := "/tmp"
test:
@echo $(TMPDIR)
然后:
make TMPDIR=whatever
whatever
makefile 依赖环境变量通常被认为是一种不好的做法,因为这可能会导致构建不可重现。这就是为什么建议在 make
命令行中显式传递变量覆盖的原因。
【讨论】:
好的,很高兴知道,但如果设置了环境变量,我该如何使用它作为默认值? 在这种特定情况下,TMPDIR 是一个可能存在的变量,如果存在我想使用它。 我试过TMPDIR := $(or $$TMPDIR,$$TMPDIR,"/tmp")
,但它似乎不起作用。
@Natim 为什么要多加美元符号?
似乎这些$(or
调用超出了需要。这不行吗? $(or $X,abc)
?【参考方案2】:
为了跟进我上面的 cmets,这里有一个例子:
T ?= foo
all:
: '$(T)'
现在,如果我以各种方式运行 Makefile,它的行为与我们预期的一样(只有在我没有在命令行或环境中设置 T
时,我才会得到 foo
):
$ make
: 'foo'
$ make T=bar
: 'bar'
$ T=bar make
: 'bar'
【讨论】:
这是什么:all:;:
?
all:
为目标 all 创建规则。分号结束先决条件列表并开始第一个配方行。最后一个:
是配方;冒号是一种特殊的 POSIX shell 运算符,基本上意味着“什么都不做”。所以这为 all
目标定义了一个完整的规则,它有一个不做任何事情的配方。
我实际上更喜欢原始格式,因为它无需将空格转换为制表符即可工作(在 SO 中很难将硬制表符放入示例中)。但我猜其他人批准了编辑,所以......【参考方案3】:
这是一个简单的解决方案:
SHELL := env TMPDIR=$(TMPDIR) $(SHELL)
TMPDIR ?= "/tmp"
all:
@echo $(TMPDIR)
适用于两种情况:TMPDIR=new/path make
和 make TMPDIR=new/path
。
【讨论】:
【参考方案4】:你可以做的一件事是:
TMPDIR := "/tmp"
ifdef $$TMPDIR
TMPDIR := $$TMPDIR
endif
test:
echo $(TMPDIR)
【讨论】:
它不能作为TMPDIR=~/tmp make
工作,只有在作为make TMPDIR=~/tmp
运行时才能工作,但问题是让它对两者都工作。以上是关于使用 ENV 变量或默认值定义 Makefile 变量的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Makefile 规则中将 env 变量传递给 shell 脚本
Kubernetes 持久卷:我可以使用 env 变量或 configMap 进行值配置吗?如果是,那怎么办?