使用 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 makemake 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 脚本

Makefile教程

如何确保将 Makefile 变量设置为先决条件?

Kubernetes 持久卷:我可以使用 env 变量或 configMap 进行值配置吗?如果是,那怎么办?

关于Lumen / Laravel .env 文件中的环境变量是如何生效的

makefile变量赋值